Magnitude and SNR Cuts

[1]:
from sorcha.modules.PPBrightLimit import PPBrightLimit
from sorcha.modules.PPMagnitudeLimit import PPMagnitudeLimit
from sorcha.modules.PPSNRLimit import PPSNRLimit
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

There are three filters in the survey simulator that perform simple cuts based on SNR or magnitude, the latter to either drop observations too faint to be interesting or too bright and therefore saturating the detector. These are PPSNRLimit, PPMagnitudeLimit, and PPBrightLimit.

This notebook will demonstrate each in turn. First we generate some randomised (and rather unphysical) test data.

[2]:
rng = np.random.default_rng()
data_size = 1000

filters = ['r', 'g', 'i']

random_magnitudes = 17.5 + (rng.random(data_size) * 6.5)
random_SNRs = 0.5 + (rng.random(data_size) * 7)
random_filters = rng.choice(filters, data_size)

test_data = pd.DataFrame({'PSFMag': random_magnitudes, 'SNR': random_SNRs, 'optFilter': random_filters})

test_data
[2]:
PSFMag SNR optFilter
0 18.181149 6.134108 r
1 23.134903 2.389628 r
2 22.936785 4.619613 g
3 23.031516 3.607125 g
4 23.069938 2.539725 r
... ... ... ...
995 23.613129 7.040533 r
996 19.478289 5.023488 g
997 20.135023 1.512182 r
998 23.342629 2.482078 r
999 19.186506 6.342341 r

1000 rows × 3 columns

Let’s look at the magnitude filters first. The below shows the original randomised magnitudes.

[3]:
fig, ax = plt.subplots(1)
ax.hist(random_magnitudes, 50, color='thistle')
ax.set_ylabel('frequency')
ax.set_xlabel('magnitude')
ax.autoscale(axis='x', tight=True)
plt.show()
../_images/notebooks_demo_MagnitudeAndSNRCuts_5_0.png

Testing first the magnitude filter for cutting faint objects, we will cut everything fainter than 21 mag.

[4]:
test_data_maglimit = PPMagnitudeLimit(test_data, 21.,colname='PSFMag')
[5]:
maglimit_magnitudes = test_data_maglimit['PSFMag'].values

fig, ax = plt.subplots(1)
ax.hist(maglimit_magnitudes, 50, color='thistle')
ax.set_ylabel('frequency')
ax.set_xlabel('magnitude')
ax.set_xlim((17.5, 24))
ax.axvline(21, linestyle='--', linewidth=1., color='darkslateblue')
plt.show()
../_images/notebooks_demo_MagnitudeAndSNRCuts_8_0.png

Now we will use the brightness limit filter. This allows the user to set a different saturation limit for each filter. As we have data in g, r and i, we will set the saturation limits as 18, 19 and 20 (chosen for clarity, not accuracy!).

[6]:
test_data_brightlimit = PPBrightLimit(test_data, filters, [18., 19., 20.])
[7]:
r_magnitudes = test_data_brightlimit[test_data_brightlimit['optFilter'] == 'r']['PSFMag'].values
g_magnitudes = test_data_brightlimit[test_data_brightlimit['optFilter'] == 'g']['PSFMag'].values
i_magnitudes = test_data_brightlimit[test_data_brightlimit['optFilter'] == 'i']['PSFMag'].values
[8]:
fig, ax = plt.subplots(3, figsize=(5, 12))

ax[0].hist(r_magnitudes, 50, color='lightpink')
ax[0].axvline(18, linestyle='--', linewidth=1., color='crimson')
ax[0].set_ylabel('frequency')

ax[1].hist(g_magnitudes, 50, color='lightgreen')
ax[1].axvline(19, linestyle='--', linewidth=1., color='forestgreen')

ax[2].hist(i_magnitudes, 50, color='paleturquoise')
ax[2].axvline(20, linestyle='--', linewidth=1., color='lightseagreen')

for a in ax:
    a.set_xlabel('magnitude')
    a.set_xlim((17.5, 24))

plt.show()
../_images/notebooks_demo_MagnitudeAndSNRCuts_12_0.png

Alternatively, we can set a single brightness limit of 18.5 across all filters.

[9]:
test_data_brightlimit_single = PPBrightLimit(test_data, filters, 18.5)
[10]:
singlelimit_magnitudes = test_data_brightlimit_single['PSFMag'].values

fig, ax = plt.subplots(1)
ax.hist(singlelimit_magnitudes, 50, color='thistle')
ax.set_ylabel('frequency')
ax.set_xlabel('magnitude')
ax.set_xlim((17.5, 24))
ax.axvline(18.5, linestyle='--', linewidth=1., color='darkslateblue')
plt.show()
../_images/notebooks_demo_MagnitudeAndSNRCuts_15_0.png

Now we will look at the SNR limit. First, the original randomised SNRs.

[11]:
fig, ax = plt.subplots(1)
ax.hist(random_SNRs, 50, color='palegoldenrod')
ax.set_ylabel('frequency')
ax.set_xlabel('SNR')
ax.autoscale(axis='x', tight=True)
plt.show()
../_images/notebooks_demo_MagnitudeAndSNRCuts_17_0.png

Now we will cut everything with an SNR lower than 2 (which is the default in the code).

[12]:
test_data_SNRlimit = PPSNRLimit(test_data, 2.)
[13]:
limit_SNRs = test_data_SNRlimit['SNR'].values

fig, ax = plt.subplots(1)
ax.hist(limit_SNRs, 50, color='palegoldenrod')
ax.set_ylabel('frequency')
ax.set_xlabel('SNR')
ax.set_xlim((0.5, 7.5))
ax.axvline(2, linestyle='--', linewidth=1., color='gold')
plt.show()
../_images/notebooks_demo_MagnitudeAndSNRCuts_20_0.png