pz-rail-astro-tools 0.1.2__py3-none-any.whl → 0.1.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pz-rail-astro-tools might be problematic. Click here for more details.
- {pz_rail_astro_tools-0.1.2.dist-info → pz_rail_astro_tools-0.1.3.dist-info}/METADATA +1 -1
- {pz_rail_astro_tools-0.1.2.dist-info → pz_rail_astro_tools-0.1.3.dist-info}/RECORD +13 -11
- {pz_rail_astro_tools-0.1.2.dist-info → pz_rail_astro_tools-0.1.3.dist-info}/WHEEL +1 -1
- rail/astro_tools/_version.py +2 -2
- rail/creation/degradation/grid_selection.py +29 -16
- rail/creation/degradation/observing_condition_degrader.py +15 -8
- rail/creation/degradation/photerr_demo.ipynb +238 -0
- rail/creation/degradation/photometric_errors.py +136 -0
- rail/creation/degradation/spectroscopic_degraders.py +17 -12
- rail/creation/degradation/spectroscopic_selections.py +120 -130
- rail/tools/util_photometry.py +7 -6
- {pz_rail_astro_tools-0.1.2.dist-info → pz_rail_astro_tools-0.1.3.dist-info}/LICENSE +0 -0
- {pz_rail_astro_tools-0.1.2.dist-info → pz_rail_astro_tools-0.1.3.dist-info}/top_level.txt +0 -0
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
rail/astro_tools/__init__.py,sha256=CwIb_-fmJ0DTHnnxVNTwXYvof69yPcBxp6RiHGx6f4M,386
|
|
2
|
-
rail/astro_tools/_version.py,sha256=
|
|
3
|
-
rail/creation/degradation/grid_selection.py,sha256=
|
|
2
|
+
rail/astro_tools/_version.py,sha256=L5DCMp1QAlSqy-8bW7d51bLubTxNjZGYc5fMQkb752U,411
|
|
3
|
+
rail/creation/degradation/grid_selection.py,sha256=zUT75TuFLUzyPg9loSkGEO1HM35a5OtpbXRYSk1W9w8,12432
|
|
4
4
|
rail/creation/degradation/lsst_error_model.py,sha256=WWQxPO3w1S6sALQxl7x7_mUI1f3o1eOGpBk3Yzi-1Q0,1969
|
|
5
|
-
rail/creation/degradation/observing_condition_degrader.py,sha256=
|
|
6
|
-
rail/creation/degradation/
|
|
7
|
-
rail/creation/degradation/
|
|
5
|
+
rail/creation/degradation/observing_condition_degrader.py,sha256=jelIfFHzrgmRmRARm5uC36ZohepfMHq5djWT5wGEaZI,19987
|
|
6
|
+
rail/creation/degradation/photerr_demo.ipynb,sha256=ZT_CX2v88Qqxq8OS8MEk2BT8qiZRXJ2xNB2EDYrf9cA,6650
|
|
7
|
+
rail/creation/degradation/photometric_errors.py,sha256=HbQaEKHEcSo4ab2J3qZAiVFxlJpLAQFwjGKUnSUmG8U,3927
|
|
8
|
+
rail/creation/degradation/spectroscopic_degraders.py,sha256=zpCxK0jbKTKlU-eqe05pW-BM2O743_ocEQy2TQPP3EA,5038
|
|
9
|
+
rail/creation/degradation/spectroscopic_selections.py,sha256=nzn8KSOEsQRX-FORu0VEUa303TpR6i4VvGf9vb3ip8Q,22176
|
|
8
10
|
rail/creation/engines/gcr_engine.py,sha256=MTzbV-FDRAoWfTpUzKCrdyOGK3hsSJ5atSLpwslBE5Y,2989
|
|
9
11
|
rail/examples_data/creation_data/data/HSC_grid_settings.pkl,sha256=zpJoSR9TSnDyL64DPXivIMam3fn6GOZoyoJoeBj2LAk,141
|
|
10
12
|
rail/examples_data/creation_data/data/hsc_ratios_and_specz.hdf5,sha256=liH54wuuuHxToqjoAwQ_fFmEefk3haNweVThMwdDKN4,13823712
|
|
@@ -12,9 +14,9 @@ rail/examples_data/creation_data/data/survey_conditions/DC2-dr6-galcounts-i20-i2
|
|
|
12
14
|
rail/examples_data/creation_data/data/survey_conditions/DC2-mask-neg-nside-128.fits,sha256=79Kg4xRP4WHlOCcS-3SKqf9aP_LZRAq-izIM0DFL6bw,1581120
|
|
13
15
|
rail/examples_data/creation_data/data/survey_conditions/minion_1016_dc2_Median_airmass_i_and_nightlt1825_HEAL.fits,sha256=twvyce70G3h1MQnGGFQJG9wZc8UbuNqXc6mjtiuaL1s,1581120
|
|
14
16
|
rail/examples_data/creation_data/data/survey_conditions/minion_1016_dc2_Median_fiveSigmaDepth_i_and_nightlt1825_HEAL.fits,sha256=RbMMFSVJQxGhZnL4BnISE9VTNljfTZwV6Bax6NxverY,1581120
|
|
15
|
-
rail/tools/util_photometry.py,sha256=
|
|
16
|
-
pz_rail_astro_tools-0.1.
|
|
17
|
-
pz_rail_astro_tools-0.1.
|
|
18
|
-
pz_rail_astro_tools-0.1.
|
|
19
|
-
pz_rail_astro_tools-0.1.
|
|
20
|
-
pz_rail_astro_tools-0.1.
|
|
17
|
+
rail/tools/util_photometry.py,sha256=canY8t7rxX7ng_PfPEtfCsF1SCnv-BwGBRSGel97aPw,18425
|
|
18
|
+
pz_rail_astro_tools-0.1.3.dist-info/LICENSE,sha256=tLMEN21HbzvT-7umOVVvPjaJZbQxCa-2bAeYLwG5Q04,1102
|
|
19
|
+
pz_rail_astro_tools-0.1.3.dist-info/METADATA,sha256=1LT110NObmr7eEDKUiznHSuAtrP6pzQsobBTKedFY0M,3946
|
|
20
|
+
pz_rail_astro_tools-0.1.3.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
21
|
+
pz_rail_astro_tools-0.1.3.dist-info/top_level.txt,sha256=6R6sqn-85I8YZTzmB9gv7sqckB2QaOTHbu-QLGTWBRE,5
|
|
22
|
+
pz_rail_astro_tools-0.1.3.dist-info/RECORD,,
|
rail/astro_tools/_version.py
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Selector that emulate spectroscopic effects on photometry"""
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
import numpy as np
|
|
5
5
|
import pandas as pd
|
|
6
6
|
import pickle
|
|
7
7
|
import tables_io
|
|
8
|
-
from rail.creation.
|
|
8
|
+
from rail.creation.selector import Selector
|
|
9
9
|
from rail.core.utils import find_rail_file
|
|
10
10
|
from ceci.config import StageParameter as Param
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class GridSelection(
|
|
13
|
+
class GridSelection(Selector):
|
|
14
14
|
"""
|
|
15
15
|
Uses the ratio of HSC spectroscpic galaxies to photometric galaxies to portion a sample
|
|
16
16
|
into training and application samples. Option to implement a color-based redshift cut off in each pixel.
|
|
@@ -39,12 +39,14 @@ class GridSelection(Degrader):
|
|
|
39
39
|
Second HSC Data Release, details of which can be found here:
|
|
40
40
|
Aihara, H., AlSayyad, Y., Ando, M., et al. 2019, PASJ, 71, 114
|
|
41
41
|
doi: 10.1093/pasj/psz103
|
|
42
|
+
|
|
43
|
+
Update(Apr 16 2024): Now inherit from selector and implement the _select() instead of run()
|
|
42
44
|
"""
|
|
43
45
|
def_ratio_file = find_rail_file("examples_data/creation_data/data/hsc_ratios_and_specz.hdf5")
|
|
44
46
|
def_set_file = find_rail_file("examples_data/creation_data/data/HSC_grid_settings.pkl" )
|
|
45
47
|
|
|
46
48
|
name = 'GridSelection'
|
|
47
|
-
config_options =
|
|
49
|
+
config_options = Selector.config_options.copy()
|
|
48
50
|
config_options.update(color_redshift_cut=Param(bool, True, msg='using color-based redshift cut'),
|
|
49
51
|
percentile_cut=Param(float, 99.0, msg='percentile cut-off for each pixel in color-based redshift cut off'),
|
|
50
52
|
redshift_cut=Param(float, 100.0, msg="cut redshifts above this value"),
|
|
@@ -57,14 +59,14 @@ class GridSelection(Degrader):
|
|
|
57
59
|
|
|
58
60
|
def __init__(self, args, comm=None):
|
|
59
61
|
|
|
60
|
-
|
|
62
|
+
Selector.__init__(self, args, comm=comm)
|
|
61
63
|
|
|
62
64
|
if self.config.redshift_cut < 0:
|
|
63
65
|
raise ValueError("redshift cut must be positive")
|
|
64
66
|
if (self.config.percentile_cut < 0) | (self.config.percentile_cut > 100):
|
|
65
67
|
raise ValueError('percentile cut off must be between 0 and 100')
|
|
66
68
|
|
|
67
|
-
def
|
|
69
|
+
def _select(self):
|
|
68
70
|
"""
|
|
69
71
|
HSC galaxies were binned in color magnitude space with i-band mag from -2 to 6 and g-z color from 13 to 26
|
|
70
72
|
200 bins in each direction. The ratio of of galaxies with spectroscopic redshifts (training galaxies) to
|
|
@@ -104,8 +106,9 @@ class GridSelection(Degrader):
|
|
|
104
106
|
raise ValueError("x limits should have two elements!")
|
|
105
107
|
if len(y_lims) != 2: # pragma: no cover
|
|
106
108
|
raise ValueError("y limits should have two elements!")
|
|
107
|
-
data_hsc_like = data[(data['x_vals'] >= x_lims[0]) & (data['x_vals'] <= x_lims[1]) & (data['y_vals'] >= y_lims[0]) & (data['y_vals'] <= y_lims[1])]
|
|
108
|
-
|
|
109
|
+
# data_hsc_like = data[(data['x_vals'] >= x_lims[0]) & (data['x_vals'] <= x_lims[1]) & (data['y_vals'] >= y_lims[0]) & (data['y_vals'] <= y_lims[1])]
|
|
110
|
+
|
|
111
|
+
data_hsc_like = data
|
|
109
112
|
x_vals = data_hsc_like['x_vals'].to_numpy()
|
|
110
113
|
y_vals = data_hsc_like['y_vals'].to_numpy()
|
|
111
114
|
|
|
@@ -155,9 +158,15 @@ class GridSelection(Degrader):
|
|
|
155
158
|
|
|
156
159
|
ratio_list = []
|
|
157
160
|
max_specz_list = []
|
|
161
|
+
|
|
158
162
|
for pix_x, pix_y in zip(pixels_x, pixels_y):
|
|
159
|
-
|
|
160
|
-
|
|
163
|
+
# cover the galaxy outside the grid of ratio
|
|
164
|
+
if (pix_x in [-1,ratios.shape[0]]) or (pix_y in [-1, ratios.shape[1]]):
|
|
165
|
+
ratio_list.append(0.0)
|
|
166
|
+
max_specz_list.append(99.0)
|
|
167
|
+
else:
|
|
168
|
+
ratio_list.append(ratios[pix_y][pix_x])
|
|
169
|
+
max_specz_list.append(max_specz[pix_y][pix_x])
|
|
161
170
|
|
|
162
171
|
data_hsc_like['ratios'] = ratio_list
|
|
163
172
|
data_hsc_like['max_specz'] = max_specz_list
|
|
@@ -204,9 +213,13 @@ class GridSelection(Degrader):
|
|
|
204
213
|
else: # pragma: no cover
|
|
205
214
|
for j in range(int(number_to_keep) + 1):
|
|
206
215
|
keep_inds.append(indices_to_list[j])
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
216
|
+
|
|
217
|
+
finalcut = data_hsc_like_redshift_cut.loc[keep_inds, :]
|
|
218
|
+
finalcut = finalcut[finalcut['redshift'] > 0]
|
|
219
|
+
|
|
220
|
+
final_keep_inds = np.array(finalcut.index)
|
|
221
|
+
|
|
222
|
+
total_mask = np.zeros(len(data), dtype=bool)
|
|
223
|
+
total_mask[final_keep_inds] = True
|
|
224
|
+
|
|
225
|
+
return total_mask
|
|
@@ -9,10 +9,10 @@ import pandas as pd
|
|
|
9
9
|
from ceci.config import StageParameter as Param
|
|
10
10
|
from photerr import LsstErrorModel, LsstErrorParams
|
|
11
11
|
|
|
12
|
-
from rail.creation.
|
|
12
|
+
from rail.creation.noisifier import Noisifier
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
class ObsCondition(
|
|
15
|
+
class ObsCondition(Noisifier):
|
|
16
16
|
"""Photometric errors based on observation conditions
|
|
17
17
|
|
|
18
18
|
This degrader calculates spatially-varying photometric errors
|
|
@@ -60,7 +60,7 @@ class ObsCondition(Degrader):
|
|
|
60
60
|
"""
|
|
61
61
|
|
|
62
62
|
name = "ObsCondition"
|
|
63
|
-
config_options =
|
|
63
|
+
config_options = Noisifier.config_options.copy()
|
|
64
64
|
config_options.update(
|
|
65
65
|
nside=Param(
|
|
66
66
|
int,
|
|
@@ -117,7 +117,7 @@ class ObsCondition(Degrader):
|
|
|
117
117
|
|
|
118
118
|
|
|
119
119
|
def __init__(self, args, comm=None):
|
|
120
|
-
|
|
120
|
+
Noisifier.__init__(self, args, comm=comm)
|
|
121
121
|
|
|
122
122
|
# store a list of keys relevant for
|
|
123
123
|
# survey conditions;
|
|
@@ -407,10 +407,17 @@ class ObsCondition(Degrader):
|
|
|
407
407
|
|
|
408
408
|
return pixel_cat
|
|
409
409
|
|
|
410
|
+
|
|
411
|
+
def _initNoiseModel(self):
|
|
412
|
+
"""
|
|
413
|
+
Initialise the error model: LSSTerrorModel
|
|
414
|
+
"""
|
|
415
|
+
self.default_errorModel = LsstErrorModel()
|
|
410
416
|
|
|
411
|
-
|
|
417
|
+
|
|
418
|
+
def _addNoise(self):
|
|
412
419
|
"""
|
|
413
|
-
Run the
|
|
420
|
+
Run the noisifier.
|
|
414
421
|
"""
|
|
415
422
|
self.rng = np.random.default_rng(seed=self.config["random_seed"])
|
|
416
423
|
|
|
@@ -437,8 +444,8 @@ class ObsCondition(Degrader):
|
|
|
437
444
|
|
|
438
445
|
# first, check if pixel is -99 - these objects have default obs_conditions:
|
|
439
446
|
if pixel==-99:
|
|
440
|
-
#
|
|
441
|
-
errorModel =
|
|
447
|
+
# use the default error model for this pixel
|
|
448
|
+
errorModel = self.default_errorModel
|
|
442
449
|
|
|
443
450
|
else:
|
|
444
451
|
# get the observing conditions for this pixel
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "markdown",
|
|
5
|
+
"id": "2610a0f0-0c71-4401-896f-734442bcd66d",
|
|
6
|
+
"metadata": {},
|
|
7
|
+
"source": [
|
|
8
|
+
"## Photometric error stage demo\n",
|
|
9
|
+
"\n",
|
|
10
|
+
"author: Tianqing Zhang, John-Franklin Crenshaw\n",
|
|
11
|
+
"\n",
|
|
12
|
+
"This notebook demonstrate the use of `rail.creation.degradation.photometric_errors`, which adds column for the photometric noise to the catalog based on the package PhotErr developed by John-Franklin Crenshaw. The RAIL stage PhotoErrorModel inherit from the Noisifier base classes, and the LSST, Roman, Euclid child classes inherit from the PhotoErrorModel"
|
|
13
|
+
]
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"cell_type": "code",
|
|
17
|
+
"execution_count": null,
|
|
18
|
+
"id": "f7a6adc3-68e8-4a1d-842f-bfb0960a1c4a",
|
|
19
|
+
"metadata": {},
|
|
20
|
+
"outputs": [],
|
|
21
|
+
"source": [
|
|
22
|
+
"\n",
|
|
23
|
+
"from rail.creation.degradation.photometric_errors import LSSTErrorModel\n",
|
|
24
|
+
"from rail.creation.degradation.photometric_errors import RomanErrorModel\n",
|
|
25
|
+
"from rail.creation.degradation.photometric_errors import EuclidErrorModel\n",
|
|
26
|
+
"\n",
|
|
27
|
+
"from rail.core.data import PqHandle\n",
|
|
28
|
+
"from rail.core.stage import RailStage\n",
|
|
29
|
+
"\n",
|
|
30
|
+
"import matplotlib.pyplot as plt\n",
|
|
31
|
+
"import pandas as pd\n",
|
|
32
|
+
"import numpy as np\n",
|
|
33
|
+
"\n"
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"cell_type": "code",
|
|
38
|
+
"execution_count": null,
|
|
39
|
+
"id": "6912a740-31ea-4987-b06d-81ff17cd895a",
|
|
40
|
+
"metadata": {},
|
|
41
|
+
"outputs": [],
|
|
42
|
+
"source": [
|
|
43
|
+
"DS = RailStage.data_store\n",
|
|
44
|
+
"DS.__class__.allow_overwrite = True\n"
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"cell_type": "markdown",
|
|
49
|
+
"id": "a282c2ed-141b-4507-8254-dc8fbc9864dc",
|
|
50
|
+
"metadata": {},
|
|
51
|
+
"source": [
|
|
52
|
+
"### Create a random catalog with ugrizy+YJHF bands as the the true input"
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"cell_type": "code",
|
|
57
|
+
"execution_count": null,
|
|
58
|
+
"id": "1078bc2a-fc54-41c3-bd30-6c447bb971d4",
|
|
59
|
+
"metadata": {},
|
|
60
|
+
"outputs": [],
|
|
61
|
+
"source": [
|
|
62
|
+
"data = np.random.normal(23, 3, size = (1000,10))\n",
|
|
63
|
+
"\n",
|
|
64
|
+
"data_df = pd.DataFrame(data=data, # values\n",
|
|
65
|
+
" columns=['u', 'g', 'r', 'i', 'z', 'y', 'Y', 'J', 'H', 'F'])\n",
|
|
66
|
+
"data_truth = PqHandle('input')\n",
|
|
67
|
+
"data_truth.set_data(data_df)"
|
|
68
|
+
]
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"cell_type": "markdown",
|
|
72
|
+
"id": "1da27deb-d167-4f38-8c59-f270184d6ab3",
|
|
73
|
+
"metadata": {},
|
|
74
|
+
"source": [
|
|
75
|
+
"### The LSST error model adds noise to the optical bands"
|
|
76
|
+
]
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"cell_type": "code",
|
|
80
|
+
"execution_count": null,
|
|
81
|
+
"id": "e5f4862a-0621-46d4-8901-7e84b461c424",
|
|
82
|
+
"metadata": {},
|
|
83
|
+
"outputs": [],
|
|
84
|
+
"source": [
|
|
85
|
+
"errorModel_lsst = LSSTErrorModel.make_stage(name=\"error_model\")\n",
|
|
86
|
+
"\n",
|
|
87
|
+
"samples_w_errs = errorModel_lsst(data_truth)\n",
|
|
88
|
+
"samples_w_errs()\n"
|
|
89
|
+
]
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"cell_type": "code",
|
|
93
|
+
"execution_count": null,
|
|
94
|
+
"id": "6282c42e-1a6f-480a-aa2b-817bd30d372f",
|
|
95
|
+
"metadata": {},
|
|
96
|
+
"outputs": [],
|
|
97
|
+
"source": [
|
|
98
|
+
"fig, ax = plt.subplots(figsize=(5, 4), dpi=100)\n",
|
|
99
|
+
"\n",
|
|
100
|
+
"for band in \"ugrizy\":\n",
|
|
101
|
+
" # pull out the magnitudes and errors\n",
|
|
102
|
+
" mags = samples_w_errs.data[band].to_numpy()\n",
|
|
103
|
+
" errs = samples_w_errs.data[band + \"_err\"].to_numpy()\n",
|
|
104
|
+
"\n",
|
|
105
|
+
" # sort them by magnitude\n",
|
|
106
|
+
" mags, errs = mags[mags.argsort()], errs[mags.argsort()]\n",
|
|
107
|
+
"\n",
|
|
108
|
+
" # plot errs vs mags\n",
|
|
109
|
+
" ax.plot(mags, errs, label=band)\n",
|
|
110
|
+
"\n",
|
|
111
|
+
"ax.legend()\n",
|
|
112
|
+
"ax.set(xlabel=\"Magnitude (AB)\", ylabel=\"Error (mags)\")\n",
|
|
113
|
+
"plt.show()\n"
|
|
114
|
+
]
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"cell_type": "markdown",
|
|
118
|
+
"id": "50927ccb-4492-4bdd-a29b-0907704b2c59",
|
|
119
|
+
"metadata": {},
|
|
120
|
+
"source": [
|
|
121
|
+
"### The Roman error model adds noise to the infrared bands"
|
|
122
|
+
]
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"cell_type": "code",
|
|
126
|
+
"execution_count": null,
|
|
127
|
+
"id": "d484a34b-cf10-45bd-8571-b78dc1818180",
|
|
128
|
+
"metadata": {},
|
|
129
|
+
"outputs": [],
|
|
130
|
+
"source": [
|
|
131
|
+
"errorModel_Roman = RomanErrorModel.make_stage(name=\"error_model\")\n",
|
|
132
|
+
"\n",
|
|
133
|
+
"samples_w_errs_roman = errorModel_Roman(data_truth)\n",
|
|
134
|
+
"samples_w_errs_roman()"
|
|
135
|
+
]
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"cell_type": "code",
|
|
139
|
+
"execution_count": null,
|
|
140
|
+
"id": "a12362dc-0689-43f3-b990-edff734010bb",
|
|
141
|
+
"metadata": {},
|
|
142
|
+
"outputs": [],
|
|
143
|
+
"source": [
|
|
144
|
+
"fig, ax = plt.subplots(figsize=(5, 4), dpi=100)\n",
|
|
145
|
+
"\n",
|
|
146
|
+
"for band in \"YJHF\":\n",
|
|
147
|
+
" # pull out the magnitudes and errors\n",
|
|
148
|
+
" mags = samples_w_errs_roman.data[band].to_numpy()\n",
|
|
149
|
+
" errs = samples_w_errs_roman.data[band + \"_err\"].to_numpy()\n",
|
|
150
|
+
"\n",
|
|
151
|
+
" # sort them by magnitude\n",
|
|
152
|
+
" mags, errs = mags[mags.argsort()], errs[mags.argsort()]\n",
|
|
153
|
+
"\n",
|
|
154
|
+
" # plot errs vs mags\n",
|
|
155
|
+
" ax.plot(mags, errs, label=band)\n",
|
|
156
|
+
"\n",
|
|
157
|
+
"ax.legend()\n",
|
|
158
|
+
"ax.set(xlabel=\"Magnitude (AB)\", ylabel=\"Error (mags)\")\n",
|
|
159
|
+
"plt.show()\n"
|
|
160
|
+
]
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"cell_type": "markdown",
|
|
164
|
+
"id": "359de4ad-a47c-4dc5-8c81-53aeb92bdf42",
|
|
165
|
+
"metadata": {},
|
|
166
|
+
"source": [
|
|
167
|
+
"### The Euclid error model adds noise to YJH bands"
|
|
168
|
+
]
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"cell_type": "code",
|
|
172
|
+
"execution_count": null,
|
|
173
|
+
"id": "775d0a23-7435-4b01-83db-2234c3d24f57",
|
|
174
|
+
"metadata": {},
|
|
175
|
+
"outputs": [],
|
|
176
|
+
"source": [
|
|
177
|
+
"errorModel_Euclid = EuclidErrorModel.make_stage(name=\"error_model\")\n",
|
|
178
|
+
"\n",
|
|
179
|
+
"samples_w_errs_Euclid = errorModel_Euclid(data_truth)\n",
|
|
180
|
+
"samples_w_errs_Euclid()"
|
|
181
|
+
]
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"cell_type": "code",
|
|
185
|
+
"execution_count": null,
|
|
186
|
+
"id": "7fcfe07a-5571-4dd3-8ad0-358964c1d493",
|
|
187
|
+
"metadata": {},
|
|
188
|
+
"outputs": [],
|
|
189
|
+
"source": [
|
|
190
|
+
"fig, ax = plt.subplots(figsize=(5, 4), dpi=100)\n",
|
|
191
|
+
"\n",
|
|
192
|
+
"for band in \"YJH\":\n",
|
|
193
|
+
" # pull out the magnitudes and errors\n",
|
|
194
|
+
" mags = samples_w_errs_Euclid.data[band].to_numpy()\n",
|
|
195
|
+
" errs = samples_w_errs_Euclid.data[band + \"_err\"].to_numpy()\n",
|
|
196
|
+
"\n",
|
|
197
|
+
" # sort them by magnitude\n",
|
|
198
|
+
" mags, errs = mags[mags.argsort()], errs[mags.argsort()]\n",
|
|
199
|
+
"\n",
|
|
200
|
+
" # plot errs vs mags\n",
|
|
201
|
+
" ax.plot(mags, errs, label=band)\n",
|
|
202
|
+
"\n",
|
|
203
|
+
"ax.legend()\n",
|
|
204
|
+
"ax.set(xlabel=\"Magnitude (AB)\", ylabel=\"Error (mags)\")\n",
|
|
205
|
+
"plt.show()\n"
|
|
206
|
+
]
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
"cell_type": "code",
|
|
210
|
+
"execution_count": null,
|
|
211
|
+
"id": "268b3d37-b7fd-4ac1-8457-2104a87c9e6d",
|
|
212
|
+
"metadata": {},
|
|
213
|
+
"outputs": [],
|
|
214
|
+
"source": []
|
|
215
|
+
}
|
|
216
|
+
],
|
|
217
|
+
"metadata": {
|
|
218
|
+
"kernelspec": {
|
|
219
|
+
"display_name": "rail_env",
|
|
220
|
+
"language": "python",
|
|
221
|
+
"name": "rail_env"
|
|
222
|
+
},
|
|
223
|
+
"language_info": {
|
|
224
|
+
"codemirror_mode": {
|
|
225
|
+
"name": "ipython",
|
|
226
|
+
"version": 3
|
|
227
|
+
},
|
|
228
|
+
"file_extension": ".py",
|
|
229
|
+
"mimetype": "text/x-python",
|
|
230
|
+
"name": "python",
|
|
231
|
+
"nbconvert_exporter": "python",
|
|
232
|
+
"pygments_lexer": "ipython3",
|
|
233
|
+
"version": "3.11.4"
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
"nbformat": 4,
|
|
237
|
+
"nbformat_minor": 5
|
|
238
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"""
|
|
2
|
+
The Photometric error Model LSST, Roman, and Euclid. Based on photometric
|
|
3
|
+
error models defined in the package photerr
|
|
4
|
+
|
|
5
|
+
Author: John Franklin Crenshaw, Tianqing Zhang
|
|
6
|
+
"""
|
|
7
|
+
from dataclasses import MISSING
|
|
8
|
+
|
|
9
|
+
from ceci.config import StageParameter as Param
|
|
10
|
+
from photerr import LsstErrorModel as peLsstErrorModel
|
|
11
|
+
from photerr import LsstErrorParams as peLsstErrorParams
|
|
12
|
+
from photerr import RomanErrorModel as peRomanErrorModel
|
|
13
|
+
from photerr import RomanErrorParams as peRomanErrorParams
|
|
14
|
+
from photerr import EuclidErrorModel as peEuclidErrorModel
|
|
15
|
+
from photerr import EuclidErrorParams as peEuclidErrorParams
|
|
16
|
+
from rail.creation.noisifier import Noisifier
|
|
17
|
+
|
|
18
|
+
class PhotoErrorModel(Noisifier):
|
|
19
|
+
"""The Base Model for photometric errors.
|
|
20
|
+
|
|
21
|
+
This is a wrapper around the error model from PhotErr. The parameter
|
|
22
|
+
docstring below is dynamically added by the installed version of PhotErr:
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
name = "PhotoErrorModel"
|
|
28
|
+
|
|
29
|
+
def set_params(self, peparams):
|
|
30
|
+
"""
|
|
31
|
+
Set the photometric error parameters from photerr to
|
|
32
|
+
the ceci config
|
|
33
|
+
"""
|
|
34
|
+
PhotErrErrorParams = peparams
|
|
35
|
+
|
|
36
|
+
config_options = Noisifier.config_options.copy()
|
|
37
|
+
|
|
38
|
+
# Dynamically add all parameters from PhotErr
|
|
39
|
+
_photerr_params = PhotErrErrorParams.__dataclass_fields__
|
|
40
|
+
self._photerr_params = _photerr_params
|
|
41
|
+
for key, val in _photerr_params.items():
|
|
42
|
+
# Get the default value
|
|
43
|
+
if val.default is MISSING:
|
|
44
|
+
default = val.default_factory()
|
|
45
|
+
else:
|
|
46
|
+
default = val.default
|
|
47
|
+
|
|
48
|
+
# Add this param to config_options
|
|
49
|
+
self.config[key] = Param(
|
|
50
|
+
None, # Let PhotErr handle type checking
|
|
51
|
+
default,
|
|
52
|
+
msg="See the main docstring for details about this parameter.",
|
|
53
|
+
required=False,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
def __init__(self, args, comm=None):
|
|
57
|
+
"""
|
|
58
|
+
Constructor
|
|
59
|
+
|
|
60
|
+
Does standard Degrader initialization and sets up the error model.
|
|
61
|
+
"""
|
|
62
|
+
Noisifier.__init__(self, args, comm=comm)
|
|
63
|
+
|
|
64
|
+
def _initNoiseModel(self):
|
|
65
|
+
"""
|
|
66
|
+
Initialize the noise model by the peNoiseModel
|
|
67
|
+
"""
|
|
68
|
+
self.noiseModel = self.peNoiseModel(
|
|
69
|
+
**{key: self.config[key] for key in self._photerr_params}
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
def _addNoise(self):
|
|
73
|
+
|
|
74
|
+
"""
|
|
75
|
+
Add noise to the input catalog
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
# Load the input catalog
|
|
79
|
+
data = self.get_data("input")
|
|
80
|
+
|
|
81
|
+
# Add photometric errors
|
|
82
|
+
obsData = self.noiseModel(data, random_state=self.config.seed)
|
|
83
|
+
|
|
84
|
+
# Return the new catalog
|
|
85
|
+
self.add_data("output", obsData)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class LSSTErrorModel(PhotoErrorModel):
|
|
89
|
+
|
|
90
|
+
"""
|
|
91
|
+
The LSST Error model, defined by peLsstErrorParams and peLsstErrorModel
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
name = "LSSTErrorModel"
|
|
95
|
+
|
|
96
|
+
def __init__(self, args, comm=None):
|
|
97
|
+
|
|
98
|
+
PhotoErrorModel.__init__(self, args, comm=comm)
|
|
99
|
+
|
|
100
|
+
self.set_params(peLsstErrorParams)
|
|
101
|
+
self.peNoiseModel = peLsstErrorModel
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class RomanErrorModel(PhotoErrorModel):
|
|
107
|
+
|
|
108
|
+
"""
|
|
109
|
+
The Roman Error model, defined by peRomanErrorParams and peRomanErrorModel
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
name = "RomanErrorModel"
|
|
113
|
+
|
|
114
|
+
def __init__(self, args, comm=None):
|
|
115
|
+
|
|
116
|
+
PhotoErrorModel.__init__(self, args, comm=comm)
|
|
117
|
+
|
|
118
|
+
self.set_params(peRomanErrorParams)
|
|
119
|
+
self.peNoiseModel = peRomanErrorModel
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class EuclidErrorModel(PhotoErrorModel):
|
|
124
|
+
|
|
125
|
+
"""
|
|
126
|
+
The Roman Error model, defined by peRomanErrorParams and peRomanErrorModel
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
name = "EuclidErrorModel"
|
|
130
|
+
|
|
131
|
+
def __init__(self, args, comm=None):
|
|
132
|
+
|
|
133
|
+
PhotoErrorModel.__init__(self, args, comm=comm)
|
|
134
|
+
|
|
135
|
+
self.set_params(peEuclidErrorParams)
|
|
136
|
+
self.peNoiseModel = peEuclidErrorModel
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
import pandas as pd
|
|
5
|
-
from rail.creation.
|
|
5
|
+
from rail.creation.selector import Selector
|
|
6
|
+
from rail.creation.noisifier import Noisifier
|
|
6
7
|
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
|
|
10
|
+
class LineConfusion(Noisifier):
|
|
9
11
|
"""Degrader that simulates emission line confusion.
|
|
10
12
|
|
|
11
13
|
.. code-block:: python
|
|
@@ -37,7 +39,7 @@ class LineConfusion(Degrader):
|
|
|
37
39
|
"""
|
|
38
40
|
|
|
39
41
|
name = 'LineConfusion'
|
|
40
|
-
config_options =
|
|
42
|
+
config_options = Noisifier.config_options.copy()
|
|
41
43
|
config_options.update(true_wavelen=float,
|
|
42
44
|
wrong_wavelen=float,
|
|
43
45
|
frac_wrong=float)
|
|
@@ -45,7 +47,7 @@ class LineConfusion(Degrader):
|
|
|
45
47
|
def __init__(self, args, comm=None):
|
|
46
48
|
"""
|
|
47
49
|
"""
|
|
48
|
-
|
|
50
|
+
Noisifier.__init__(self, args, comm=comm)
|
|
49
51
|
# validate parameters
|
|
50
52
|
if self.config.true_wavelen < 0:
|
|
51
53
|
raise ValueError("true_wavelen must be positive, not {self.config.true_wavelen}")
|
|
@@ -53,8 +55,12 @@ class LineConfusion(Degrader):
|
|
|
53
55
|
raise ValueError("wrong_wavelen must be positive, not {self.config.wrong_wavelen}")
|
|
54
56
|
if self.config.frac_wrong < 0 or self.config.frac_wrong > 1:
|
|
55
57
|
raise ValueError("frac_wrong must be between 0 and 1., not {self.config.wrong_wavelen}")
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _initNoiseModel(self):
|
|
61
|
+
self.rng = np.random.default_rng(self.config.seed)
|
|
56
62
|
|
|
57
|
-
def
|
|
63
|
+
def _addNoise(self):
|
|
58
64
|
""" Run method
|
|
59
65
|
|
|
60
66
|
Applies line confusion
|
|
@@ -75,8 +81,7 @@ class LineConfusion(Degrader):
|
|
|
75
81
|
zmin = self.config.wrong_wavelen / self.config.true_wavelen - 1
|
|
76
82
|
|
|
77
83
|
# select the random fraction of galaxies whose lines are confused
|
|
78
|
-
|
|
79
|
-
idx = rng.choice(
|
|
84
|
+
idx = self.rng.choice(
|
|
80
85
|
np.where(values[:, 0] > zmin)[0],
|
|
81
86
|
size=int(self.config.frac_wrong * values.shape[0]),
|
|
82
87
|
replace=False,
|
|
@@ -92,7 +97,7 @@ class LineConfusion(Degrader):
|
|
|
92
97
|
self.add_data('output', outData)
|
|
93
98
|
|
|
94
99
|
|
|
95
|
-
class InvRedshiftIncompleteness(
|
|
100
|
+
class InvRedshiftIncompleteness(Selector):
|
|
96
101
|
"""Degrader that simulates incompleteness with a selection function
|
|
97
102
|
inversely proportional to redshift.
|
|
98
103
|
|
|
@@ -107,17 +112,17 @@ class InvRedshiftIncompleteness(Degrader):
|
|
|
107
112
|
"""
|
|
108
113
|
|
|
109
114
|
name = 'InvRedshiftIncompleteness'
|
|
110
|
-
config_options =
|
|
115
|
+
config_options = Selector.config_options.copy()
|
|
111
116
|
config_options.update(pivot_redshift=float)
|
|
112
117
|
|
|
113
118
|
def __init__(self, args, comm=None):
|
|
114
119
|
"""
|
|
115
120
|
"""
|
|
116
|
-
|
|
121
|
+
Selector.__init__(self, args, comm=comm)
|
|
117
122
|
if self.config.pivot_redshift < 0:
|
|
118
123
|
raise ValueError("pivot redshift must be positive, not {self.config.pivot_redshift}")
|
|
119
124
|
|
|
120
|
-
def
|
|
125
|
+
def _select(self):
|
|
121
126
|
""" Run method
|
|
122
127
|
|
|
123
128
|
Applies incompleteness
|
|
@@ -136,4 +141,4 @@ class InvRedshiftIncompleteness(Degrader):
|
|
|
136
141
|
rng = np.random.default_rng(self.config.seed)
|
|
137
142
|
mask = rng.random(size=data.shape[0]) <= survival_prob
|
|
138
143
|
|
|
139
|
-
|
|
144
|
+
return mask
|
|
@@ -1,39 +1,43 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Degrader that applies selection functions to catalog."""
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
|
|
5
5
|
import numpy as np
|
|
6
6
|
from ceci.config import StageParameter as Param
|
|
7
|
-
from rail.creation.
|
|
7
|
+
from rail.creation.selector import Selector
|
|
8
8
|
from scipy.interpolate import interp1d
|
|
9
|
-
from rail.core.utils import
|
|
9
|
+
from rail.core.utils import RAILDIR
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class SpecSelection(
|
|
13
|
-
"""
|
|
14
|
-
The super class of spectroscopic selections.
|
|
12
|
+
class SpecSelection(Selector):
|
|
13
|
+
"""The super class of spectroscopic selections.
|
|
15
14
|
|
|
16
15
|
Parameters
|
|
17
16
|
----------
|
|
18
|
-
N_tot:
|
|
19
|
-
total number of down-sampled, spec-selected galaxies.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
nondetect_val:
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
to N_tot galaxies.
|
|
26
|
-
success_rate_dir: string
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
17
|
+
N_tot : int
|
|
18
|
+
The total number of down-sampled, spec-selected galaxies. If N_tot is
|
|
19
|
+
greater than the number of spec-sepected galaxies, then it will be
|
|
20
|
+
ignored.
|
|
21
|
+
nondetect_val : float
|
|
22
|
+
The value to be removed for non detects
|
|
23
|
+
downsample : bool
|
|
24
|
+
If True, then downsample the pre-selected galaxies to N_tot galaxies.
|
|
25
|
+
success_rate_dir : string
|
|
26
|
+
The path to the success rate files
|
|
27
|
+
percentile_cut: int, default=100
|
|
28
|
+
If using color-based redshift cut, percentile in redshifts above which
|
|
29
|
+
redshifts will be cut from the sample. Default is 100 (no cut).
|
|
30
|
+
colnames: dict
|
|
31
|
+
A dictionary that includes necessary columns (magnitudes, colors and
|
|
32
|
+
redshift) for selection. For magnitudes, the keys are ugrizy; for
|
|
33
|
+
colors, the keys are, for example, gr standing for g-r; for redshift,
|
|
34
|
+
the key is 'redshift'.
|
|
35
|
+
random_seed : int
|
|
36
|
+
Random seed for reproducibility
|
|
33
37
|
"""
|
|
34
38
|
|
|
35
39
|
name = "specselection"
|
|
36
|
-
config_options =
|
|
40
|
+
config_options = Selector.config_options.copy()
|
|
37
41
|
config_options.update(
|
|
38
42
|
N_tot=Param(int, 10000, msg="Number of selected sources"),
|
|
39
43
|
nondetect_val=Param(float, 99.0, msg="value to be removed for non detects"),
|
|
@@ -44,7 +48,9 @@ class SpecSelection(Degrader):
|
|
|
44
48
|
),
|
|
45
49
|
success_rate_dir=Param(
|
|
46
50
|
str,
|
|
47
|
-
|
|
51
|
+
os.path.join(RAILDIR,
|
|
52
|
+
"rail/examples_data/creation_data/data/success_rate_data",
|
|
53
|
+
),
|
|
48
54
|
msg="The path to the directory containing success rate files.",
|
|
49
55
|
),
|
|
50
56
|
percentile_cut=Param(int, 100, msg="cut redshifts above this percentile"),
|
|
@@ -62,17 +68,13 @@ class SpecSelection(Degrader):
|
|
|
62
68
|
)
|
|
63
69
|
|
|
64
70
|
def __init__(self, args, comm=None):
|
|
65
|
-
|
|
66
|
-
# validate the settings
|
|
71
|
+
Selector.__init__(self, args, comm=comm)
|
|
67
72
|
self._validate_settings()
|
|
68
73
|
self.mask = None
|
|
69
74
|
self.rng = None
|
|
70
75
|
|
|
71
76
|
def _validate_settings(self):
|
|
72
|
-
"""
|
|
73
|
-
Validate all the settings.
|
|
74
|
-
"""
|
|
75
|
-
|
|
77
|
+
"""Validate all the settings."""
|
|
76
78
|
if self.config.N_tot < 0:
|
|
77
79
|
raise ValueError(
|
|
78
80
|
"Total number of selected sources must be a " "positive integer."
|
|
@@ -85,10 +87,13 @@ class SpecSelection(Degrader):
|
|
|
85
87
|
)
|
|
86
88
|
|
|
87
89
|
def validate_colnames(self, data):
|
|
88
|
-
"""
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
"""Validate the column names of data table to make sure they have
|
|
91
|
+
necessary information for each selection.
|
|
92
|
+
|
|
93
|
+
Parameters
|
|
94
|
+
----------
|
|
95
|
+
colnames : list of str
|
|
96
|
+
A list of column names
|
|
92
97
|
"""
|
|
93
98
|
colnames = self.config.colnames.values()
|
|
94
99
|
check = all(item in data.columns for item in colnames)
|
|
@@ -101,15 +106,15 @@ class SpecSelection(Degrader):
|
|
|
101
106
|
)
|
|
102
107
|
|
|
103
108
|
def selection(self, data):
|
|
104
|
-
"""
|
|
105
|
-
|
|
106
|
-
corresponding to different
|
|
109
|
+
"""Selection functions.
|
|
110
|
+
|
|
111
|
+
This should be overwritten by the subclasses corresponding to different
|
|
112
|
+
spec selections.
|
|
107
113
|
"""
|
|
108
114
|
|
|
109
115
|
def invalid_cut(self, data):
|
|
110
|
-
"""
|
|
111
|
-
|
|
112
|
-
(nondetect_val or NaN)
|
|
116
|
+
"""Removes entries in the data that have invalid magnitude values (NaN
|
|
117
|
+
or nondetect_val).
|
|
113
118
|
"""
|
|
114
119
|
nondetect_val = self.config.nondetect_val
|
|
115
120
|
for band in "ugrizy":
|
|
@@ -121,9 +126,7 @@ class SpecSelection(Degrader):
|
|
|
121
126
|
)
|
|
122
127
|
|
|
123
128
|
def downsampling_N_tot(self):
|
|
124
|
-
"""
|
|
125
|
-
Method to randomly sample down the objects to a given
|
|
126
|
-
number of data objects.
|
|
129
|
+
"""Randomly sample down the objects to a given number of data objects.
|
|
127
130
|
"""
|
|
128
131
|
N_tot = self.config.N_tot
|
|
129
132
|
N_selected = np.count_nonzero(self.mask)
|
|
@@ -146,11 +149,9 @@ class SpecSelection(Degrader):
|
|
|
146
149
|
# update the internal state
|
|
147
150
|
self.mask &= mask
|
|
148
151
|
|
|
149
|
-
def
|
|
150
|
-
"""
|
|
151
|
-
|
|
152
|
-
"""
|
|
153
|
-
self.rng = np.random.default_rng(seed=self.config.seed)
|
|
152
|
+
def _select(self):
|
|
153
|
+
"""Run the selection."""
|
|
154
|
+
self.rng = np.random.default_rng(seed=self.config.random_seed)
|
|
154
155
|
# get the bands and bandNames present in the data
|
|
155
156
|
data = self.get_data("input", allow_missing=True)
|
|
156
157
|
self.validate_colnames(data)
|
|
@@ -159,10 +160,11 @@ class SpecSelection(Degrader):
|
|
|
159
160
|
self.selection(data)
|
|
160
161
|
if self.config.downsample is True:
|
|
161
162
|
self.downsampling_N_tot()
|
|
163
|
+
|
|
164
|
+
return self.mask
|
|
165
|
+
# data_selected = data.iloc[np.where(self.mask == 1)[0]]
|
|
162
166
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
self.add_data("output", data_selected)
|
|
167
|
+
# self.add_data("output", data_selected)
|
|
166
168
|
|
|
167
169
|
def __repr__(self):
|
|
168
170
|
"""
|
|
@@ -171,25 +173,22 @@ class SpecSelection(Degrader):
|
|
|
171
173
|
|
|
172
174
|
|
|
173
175
|
class SpecSelection_GAMA(SpecSelection):
|
|
174
|
-
"""
|
|
175
|
-
The class of spectroscopic selections with GAMA.
|
|
176
|
-
The GAMA survey covers an area of 286 deg^2, with ~238000 objects
|
|
177
|
-
The necessary column is r band
|
|
178
|
-
"""
|
|
176
|
+
"""The class of spectroscopic selections with GAMA.
|
|
179
177
|
|
|
178
|
+
The GAMA survey covers an area of 286 deg^2, with ~238000 objects.
|
|
179
|
+
|
|
180
|
+
The necessary column is r band.
|
|
181
|
+
"""
|
|
182
|
+
|
|
180
183
|
name = "specselection_gama"
|
|
181
184
|
|
|
182
185
|
def selection(self, data):
|
|
183
|
-
"""
|
|
184
|
-
GAMA selection function
|
|
185
|
-
"""
|
|
186
|
+
"""GAMA selection function. """
|
|
186
187
|
print("Applying the selection from GAMA survey...")
|
|
187
188
|
self.mask *= data[self.config.colnames["r"]] < 19.87
|
|
188
189
|
|
|
189
190
|
def __repr__(self):
|
|
190
|
-
"""
|
|
191
|
-
Define how the model is represented and printed.
|
|
192
|
-
"""
|
|
191
|
+
"""Define how the model is represented and printed."""
|
|
193
192
|
# start message
|
|
194
193
|
printMsg = "Applying the GAMA selection."
|
|
195
194
|
|
|
@@ -197,22 +196,22 @@ class SpecSelection_GAMA(SpecSelection):
|
|
|
197
196
|
|
|
198
197
|
|
|
199
198
|
class SpecSelection_BOSS(SpecSelection):
|
|
200
|
-
"""
|
|
201
|
-
|
|
199
|
+
"""The class of spectroscopic selections with BOSS.
|
|
200
|
+
|
|
202
201
|
BOSS selection function is based on
|
|
203
202
|
http://www.sdss3.org/dr9/algorithms/boss_galaxy_ts.php
|
|
204
|
-
|
|
203
|
+
|
|
204
|
+
The selection has changed slightly compared to Dawson+13.
|
|
205
|
+
|
|
205
206
|
BOSS covers an area of 9100 deg^2 with 893,319 galaxies.
|
|
207
|
+
|
|
206
208
|
For BOSS selection, the data should at least include gri bands.
|
|
207
209
|
"""
|
|
208
210
|
|
|
209
211
|
name = "specselection_boss"
|
|
210
212
|
|
|
211
213
|
def selection(self, data):
|
|
212
|
-
"""
|
|
213
|
-
The BOSS selection function.
|
|
214
|
-
"""
|
|
215
|
-
|
|
214
|
+
"""The BOSS selection function."""
|
|
216
215
|
print("Applying the selection from BOSS survey...")
|
|
217
216
|
# cut quantities (unchanged)
|
|
218
217
|
c_p = 0.7 * (
|
|
@@ -252,9 +251,7 @@ class SpecSelection_BOSS(SpecSelection):
|
|
|
252
251
|
self.mask *= low_z | cmass
|
|
253
252
|
|
|
254
253
|
def __repr__(self):
|
|
255
|
-
"""
|
|
256
|
-
Define how the model is represented and printed.
|
|
257
|
-
"""
|
|
254
|
+
""" Define how the model is represented and printed."""
|
|
258
255
|
# start message
|
|
259
256
|
printMsg = "Applying the BOSS selection."
|
|
260
257
|
|
|
@@ -262,26 +259,27 @@ class SpecSelection_BOSS(SpecSelection):
|
|
|
262
259
|
|
|
263
260
|
|
|
264
261
|
class SpecSelection_DEEP2(SpecSelection):
|
|
265
|
-
"""
|
|
266
|
-
|
|
262
|
+
"""The class of spectroscopic selections with DEEP2.
|
|
263
|
+
|
|
267
264
|
DEEP2 has a sky coverage of 2.8 deg^2 with ~53000 spectra.
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
265
|
+
|
|
266
|
+
For DEEP2, one needs R band magnitude, B-R/R-I colors--which are not
|
|
267
|
+
available for the time being, so we use LSST gri bands now. When the
|
|
268
|
+
conversion degrader is ready, this subclass will be updated accordingly.
|
|
271
269
|
"""
|
|
272
270
|
|
|
273
271
|
name = "specselection_deep2"
|
|
274
272
|
|
|
275
273
|
def photometryCut(self, data):
|
|
276
|
-
"""
|
|
277
|
-
|
|
278
|
-
This modified selection gives the best match to the data n(z) with
|
|
279
|
-
|
|
274
|
+
"""Applies DEEP2 photometric cut based on Newman+13.
|
|
275
|
+
|
|
276
|
+
This modified selection gives the best match to the data n(z) with its
|
|
277
|
+
cut at z~0.75 and the B-R/R-I distribution (Newman+13, Fig. 12).
|
|
280
278
|
|
|
281
279
|
Notes
|
|
282
280
|
-----
|
|
283
|
-
We cannot apply the surface brightness cut and do not apply the
|
|
284
|
-
|
|
281
|
+
We cannot apply the surface brightness cut and do not apply the Gaussian
|
|
282
|
+
weighted sampling near the original colour cuts.
|
|
285
283
|
"""
|
|
286
284
|
mask = (
|
|
287
285
|
(data[self.config.colnames["r"]] > 18.5)
|
|
@@ -312,8 +310,7 @@ class SpecSelection_DEEP2(SpecSelection):
|
|
|
312
310
|
self.mask &= mask
|
|
313
311
|
|
|
314
312
|
def speczSuccess(self, data):
|
|
315
|
-
"""
|
|
316
|
-
Spec-z success rate as function of r_AB for Q>=3 read of Figure 13 in
|
|
313
|
+
"""Spec-z success rate as function of r_AB for Q>=3 read of Figure 13 in
|
|
317
314
|
Newman+13 for DEEP2 fields 2-4. Values are binned in steps of 0.2 mag
|
|
318
315
|
with the first and last bin centered on 19 and 24.
|
|
319
316
|
"""
|
|
@@ -338,16 +335,12 @@ class SpecSelection_DEEP2(SpecSelection):
|
|
|
338
335
|
self.mask &= mask
|
|
339
336
|
|
|
340
337
|
def selection(self, data):
|
|
341
|
-
"""
|
|
342
|
-
DEEP2 selection function
|
|
343
|
-
"""
|
|
338
|
+
"""DEEP2 selection function."""
|
|
344
339
|
self.photometryCut(data)
|
|
345
340
|
self.speczSuccess(data)
|
|
346
341
|
|
|
347
342
|
def __repr__(self):
|
|
348
|
-
"""
|
|
349
|
-
Define how the model is represented and printed.
|
|
350
|
-
"""
|
|
343
|
+
"""Define how the model is represented and printed."""
|
|
351
344
|
# start message
|
|
352
345
|
printMsg = "Applying the DEEP2 selection."
|
|
353
346
|
|
|
@@ -355,21 +348,22 @@ class SpecSelection_DEEP2(SpecSelection):
|
|
|
355
348
|
|
|
356
349
|
|
|
357
350
|
class SpecSelection_VVDSf02(SpecSelection):
|
|
358
|
-
"""
|
|
359
|
-
|
|
351
|
+
"""The class of spectroscopic selections with VVDSf02.
|
|
352
|
+
|
|
360
353
|
It covers an area of 0.5 deg^2 with ~10000 sources.
|
|
354
|
+
|
|
361
355
|
Necessary columns are i band magnitude and redshift.
|
|
362
356
|
"""
|
|
363
357
|
|
|
364
358
|
name = "specselection_VVDSf02"
|
|
365
359
|
|
|
366
360
|
def photometryCut(self, data):
|
|
367
|
-
"""
|
|
368
|
-
Photometric cut of VVDS 2h-field based on LeFèvre+05.
|
|
361
|
+
"""Photometric cut of VVDS 2h-field based on LeFèvre+05.
|
|
369
362
|
|
|
370
363
|
Notes
|
|
371
364
|
-----
|
|
372
|
-
The oversight of 1.0 magnitudes on the bright end misses 0.2% of
|
|
365
|
+
The oversight of 1.0 magnitudes on the bright end misses 0.2% of
|
|
366
|
+
galaxies.
|
|
373
367
|
"""
|
|
374
368
|
mask = (data[self.config.colnames["i"]] > 17.5) & (
|
|
375
369
|
data[self.config.colnames["i"]] < 24.0
|
|
@@ -378,18 +372,17 @@ class SpecSelection_VVDSf02(SpecSelection):
|
|
|
378
372
|
self.mask &= mask
|
|
379
373
|
|
|
380
374
|
def speczSuccess(self, data):
|
|
381
|
-
"""
|
|
382
|
-
Success rate of VVDS 2h-field
|
|
375
|
+
"""Success rate of VVDS 2h-field.
|
|
383
376
|
|
|
384
377
|
Notes
|
|
385
378
|
-----
|
|
386
|
-
We use a redshift-based and I-band based success rate
|
|
387
|
-
|
|
388
|
-
|
|
379
|
+
We use a redshift-based and I-band based success rate independently here
|
|
380
|
+
since we do not know their correlation, which makes the success rate
|
|
381
|
+
worse than in reality.
|
|
389
382
|
|
|
390
|
-
Spec-z success rate as function of i_AB read of Figure 16 in
|
|
391
|
-
|
|
392
|
-
|
|
383
|
+
Spec-z success rate as function of i_AB read of Figure 16 in LeFevre+05
|
|
384
|
+
for the VVDS 2h field. Values are binned in steps of 0.5 mag with the
|
|
385
|
+
first starting at 17 and the last bin ending at 24.
|
|
393
386
|
"""
|
|
394
387
|
success_I_bins = np.arange(17.0, 24.0 + 0.01, 0.5)
|
|
395
388
|
success_I_centers = (success_I_bins[1:] + success_I_bins[:-1]) / 2.0
|
|
@@ -458,9 +451,7 @@ class SpecSelection_VVDSf02(SpecSelection):
|
|
|
458
451
|
self.speczSuccess(data)
|
|
459
452
|
|
|
460
453
|
def __repr__(self):
|
|
461
|
-
"""
|
|
462
|
-
Define how the model is represented and printed.
|
|
463
|
-
"""
|
|
454
|
+
"""Define how the model is represented and printed."""
|
|
464
455
|
# start message
|
|
465
456
|
printMsg = "Applying the VVDSf02 selection."
|
|
466
457
|
|
|
@@ -468,19 +459,21 @@ class SpecSelection_VVDSf02(SpecSelection):
|
|
|
468
459
|
|
|
469
460
|
|
|
470
461
|
class SpecSelection_zCOSMOS(SpecSelection):
|
|
471
|
-
"""
|
|
472
|
-
|
|
462
|
+
"""The class of spectroscopic selections with zCOSMOS.
|
|
463
|
+
|
|
473
464
|
It covers an area of 1.7 deg^2 with ~20000 galaxies.
|
|
465
|
+
|
|
474
466
|
For zCOSMOS, the data should at least include i band and redshift.
|
|
475
467
|
"""
|
|
476
468
|
|
|
477
469
|
name = "specselection_zCOSMOS"
|
|
478
470
|
|
|
479
471
|
def photometryCut(self, data):
|
|
480
|
-
"""
|
|
481
|
-
|
|
472
|
+
"""Photometry cut for zCOSMOS based on Lilly+09.
|
|
473
|
+
|
|
474
|
+
Updates the internal state.
|
|
475
|
+
|
|
482
476
|
NOTE: This only includes zCOSMOS bright.
|
|
483
|
-
update the internal state
|
|
484
477
|
"""
|
|
485
478
|
mask = (data[self.config.colnames["i"]] > 15.0) & (
|
|
486
479
|
data[self.config.colnames["i"]] < 22.5
|
|
@@ -489,8 +482,7 @@ class SpecSelection_zCOSMOS(SpecSelection):
|
|
|
489
482
|
self.mask &= mask
|
|
490
483
|
|
|
491
484
|
def speczSuccess(self, data):
|
|
492
|
-
"""
|
|
493
|
-
Spec-z success rate as function of redshift (x) and I_AB (y) read of
|
|
485
|
+
"""Spec-z success rate as function of redshift (x) and I_AB (y) read of
|
|
494
486
|
Figure 3 in Lilly+09 for zCOSMOS bright sample.
|
|
495
487
|
"""
|
|
496
488
|
success_rate_dir = self.config.success_rate_dir
|
|
@@ -522,9 +514,7 @@ class SpecSelection_zCOSMOS(SpecSelection):
|
|
|
522
514
|
self.speczSuccess(data)
|
|
523
515
|
|
|
524
516
|
def __repr__(self):
|
|
525
|
-
"""
|
|
526
|
-
Define how the model is represented and printed.
|
|
527
|
-
"""
|
|
517
|
+
"""Defines how the model is represented and printed."""
|
|
528
518
|
# start message
|
|
529
519
|
printMsg = "Applying the zCOSMOS selection."
|
|
530
520
|
|
|
@@ -532,16 +522,16 @@ class SpecSelection_zCOSMOS(SpecSelection):
|
|
|
532
522
|
|
|
533
523
|
|
|
534
524
|
class SpecSelection_HSC(SpecSelection):
|
|
535
|
-
"""
|
|
536
|
-
|
|
537
|
-
|
|
525
|
+
"""The class of spectroscopic selections with HSC.
|
|
526
|
+
|
|
527
|
+
For HSC, the data should at least include giz bands and redshift.
|
|
538
528
|
"""
|
|
539
529
|
|
|
540
530
|
name = "specselection_HSC"
|
|
541
531
|
|
|
542
532
|
def photometryCut(self, data):
|
|
543
|
-
"""
|
|
544
|
-
|
|
533
|
+
"""HSC galaxies were binned in color magnitude space with i-band mag
|
|
534
|
+
from -2 to 6 and g-z color from 13 to 26.
|
|
545
535
|
"""
|
|
546
536
|
mask = (data[self.config.colnames["i"]] > 13.0) & (
|
|
547
537
|
data[self.config.colnames["i"]] < 26.0
|
|
@@ -552,11 +542,13 @@ class SpecSelection_HSC(SpecSelection):
|
|
|
552
542
|
self.mask &= mask
|
|
553
543
|
|
|
554
544
|
def speczSuccess(self, data):
|
|
555
|
-
"""
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
galaxies with only photometry in HSC wide field (application
|
|
559
|
-
|
|
545
|
+
"""HSC galaxies were binned in color magnitude space with i-band mag
|
|
546
|
+
from -2 to 6 and g-z color from 13 to 26 (200 bins in each direction).
|
|
547
|
+
The ratio of galaxies with spectroscopic redshifts (training galaxies)
|
|
548
|
+
to galaxies with only photometry in HSC wide field (application
|
|
549
|
+
galaxies) was computed for each pixel. We divide the data into the same
|
|
550
|
+
pixels and randomly select galaxies into the training sample based on
|
|
551
|
+
the HSC ratios.
|
|
560
552
|
"""
|
|
561
553
|
success_rate_dir = self.config.success_rate_dir
|
|
562
554
|
x_edge = np.linspace(13, 26, 201, endpoint=True)
|
|
@@ -608,10 +600,8 @@ class SpecSelection_HSC(SpecSelection):
|
|
|
608
600
|
self.speczSuccess(data)
|
|
609
601
|
|
|
610
602
|
def __repr__(self):
|
|
611
|
-
"""
|
|
612
|
-
Define how the model is represented and printed.
|
|
613
|
-
"""
|
|
603
|
+
"""Defines how the model is represented and printed."""
|
|
614
604
|
# start message
|
|
615
605
|
printMsg = "Applying the HSC selection."
|
|
616
606
|
|
|
617
|
-
return printMsg
|
|
607
|
+
return printMsg
|
rail/tools/util_photometry.py
CHANGED
|
@@ -415,8 +415,8 @@ class LSSTFluxToMagConverter(RailStage):
|
|
|
415
415
|
class Dereddener(RailStage):
|
|
416
416
|
"""Utility stage that does dereddening
|
|
417
417
|
|
|
418
|
-
Note: set
|
|
419
|
-
columns in data
|
|
418
|
+
Note: set copy_all_cols=True to copy all
|
|
419
|
+
columns in data, copy_cols will be ignored
|
|
420
420
|
"""
|
|
421
421
|
name = 'Dereddener'
|
|
422
422
|
|
|
@@ -427,6 +427,7 @@ class Dereddener(RailStage):
|
|
|
427
427
|
config_options.update(dustmap_name='sfd')
|
|
428
428
|
config_options.update(dustmap_dir=str)
|
|
429
429
|
config_options.update(copy_cols=[])
|
|
430
|
+
config_options.update(copy_all_cols=False)
|
|
430
431
|
|
|
431
432
|
inputs = [('input', Hdf5Handle)]
|
|
432
433
|
outputs = [('output', Hdf5Handle)]
|
|
@@ -470,12 +471,12 @@ class Dereddener(RailStage):
|
|
|
470
471
|
mag_vals = data[band_mag_name]
|
|
471
472
|
out_data[band_mag_name] = mag_vals - ebvvec*self.config.band_a_env[i]
|
|
472
473
|
band_mag_name_list.append(band_mag_name)
|
|
473
|
-
|
|
474
|
-
# check if
|
|
475
|
-
if
|
|
474
|
+
|
|
475
|
+
# check if copy_all_cols set to true:
|
|
476
|
+
if self.config.copy_all_cols==False: # pragma: no cover
|
|
476
477
|
for col_ in self.config.copy_cols: # pragma: no cover
|
|
477
478
|
out_data[col_] = data[col_]
|
|
478
|
-
elif self.config.
|
|
479
|
+
elif self.config.copy_all_cols==True: # pragma: no cover
|
|
479
480
|
for col_ in data:
|
|
480
481
|
# make sure we do not overwrite the photometry columns
|
|
481
482
|
if col_ not in band_mag_name_list:
|
|
File without changes
|
|
File without changes
|