pz-rail-astro-tools 0.1.2__tar.gz → 0.1.3__tar.gz
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 → pz_rail_astro_tools-0.1.3}/PKG-INFO +1 -1
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/src/pz_rail_astro_tools.egg-info/PKG-INFO +1 -1
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/src/pz_rail_astro_tools.egg-info/SOURCES.txt +2 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/src/rail/astro_tools/_version.py +2 -2
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/src/rail/creation/degradation/grid_selection.py +29 -16
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/src/rail/creation/degradation/observing_condition_degrader.py +15 -8
- pz_rail_astro_tools-0.1.3/src/rail/creation/degradation/photerr_demo.ipynb +238 -0
- pz_rail_astro_tools-0.1.3/src/rail/creation/degradation/photometric_errors.py +136 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/src/rail/creation/degradation/spectroscopic_degraders.py +17 -12
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/src/rail/creation/degradation/spectroscopic_selections.py +120 -130
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/src/rail/tools/util_photometry.py +7 -6
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/tests/astro_tools/test_degraders.py +75 -3
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/.copier-answers.yml +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/.github/ISSUE_TEMPLATE/0-general_issue.md +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/.github/ISSUE_TEMPLATE/1-bug_report.md +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/.github/ISSUE_TEMPLATE/2-feature_request.md +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/.github/pull_request_template.md +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/.github/workflows/add-issue-to-project-tracker.yml +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/.github/workflows/linting.yml +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/.github/workflows/publish-to-pypi.yml +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/.github/workflows/smoke-test.yml +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/.github/workflows/testing-and-coverage.yml +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/.gitignore +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/.pre-commit-config.yaml +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/LICENSE +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/README.md +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/environment.yml +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/pyproject.toml +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/setup.cfg +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/setup.py +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/src/pz_rail_astro_tools.egg-info/dependency_links.txt +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/src/pz_rail_astro_tools.egg-info/requires.txt +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/src/pz_rail_astro_tools.egg-info/top_level.txt +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/src/rail/astro_tools/__init__.py +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/src/rail/creation/degradation/lsst_error_model.py +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/src/rail/creation/engines/gcr_engine.py +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/src/rail/examples_data/creation_data/data/HSC_grid_settings.pkl +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/src/rail/examples_data/creation_data/data/hsc_ratios_and_specz.hdf5 +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/src/rail/examples_data/creation_data/data/survey_conditions/DC2-dr6-galcounts-i20-i25.3-nside-128.fits +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/src/rail/examples_data/creation_data/data/survey_conditions/DC2-mask-neg-nside-128.fits +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/src/rail/examples_data/creation_data/data/survey_conditions/minion_1016_dc2_Median_airmass_i_and_nightlt1825_HEAL.fits +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/src/rail/examples_data/creation_data/data/survey_conditions/minion_1016_dc2_Median_fiveSigmaDepth_i_and_nightlt1825_HEAL.fits +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/tests/astro_tools/gcr_test_data/schema.yaml +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/tests/astro_tools/gcr_test_data/test_object_tract_4850.hdf5 +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/tests/astro_tools/test_core.py +0 -0
- {pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/tests/astro_tools/test_gcr_engine.py +0 -0
{pz-rail-astro-tools-0.1.2 → pz_rail_astro_tools-0.1.3}/src/pz_rail_astro_tools.egg-info/SOURCES.txt
RENAMED
|
@@ -25,6 +25,8 @@ src/rail/astro_tools/_version.py
|
|
|
25
25
|
src/rail/creation/degradation/grid_selection.py
|
|
26
26
|
src/rail/creation/degradation/lsst_error_model.py
|
|
27
27
|
src/rail/creation/degradation/observing_condition_degrader.py
|
|
28
|
+
src/rail/creation/degradation/photerr_demo.ipynb
|
|
29
|
+
src/rail/creation/degradation/photometric_errors.py
|
|
28
30
|
src/rail/creation/degradation/spectroscopic_degraders.py
|
|
29
31
|
src/rail/creation/degradation/spectroscopic_selections.py
|
|
30
32
|
src/rail/creation/engines/gcr_engine.py
|
|
@@ -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
|