pz-rail-astro-tools 1.0.5__tar.gz → 1.0.7__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.

Files changed (54) hide show
  1. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/PKG-INFO +1 -1
  2. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/pz_rail_astro_tools.egg-info/PKG-INFO +1 -1
  3. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/pz_rail_astro_tools.egg-info/SOURCES.txt +1 -1
  4. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/rail/astro_tools/_version.py +2 -2
  5. pz_rail_astro_tools-1.0.7/src/rail/creation/degraders/unrec_bl_model.py +178 -0
  6. pz_rail_astro_tools-1.0.7/src/rail/pipelines/degradation/truth_to_observed.py +83 -0
  7. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/tests/astro_tools/test_degraders.py +18 -6
  8. pz_rail_astro_tools-1.0.7/tests/astro_tools/test_pipline.py +17 -0
  9. pz_rail_astro_tools-1.0.5/src/rail/creation/degraders/bl_demo.ipynb +0 -206
  10. pz_rail_astro_tools-1.0.5/src/rail/creation/degraders/unrec_bl_model.py +0 -98
  11. pz_rail_astro_tools-1.0.5/tests/astro_tools/test_pipline.py +0 -16
  12. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/.copier-answers.yml +0 -0
  13. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/.github/ISSUE_TEMPLATE/0-general_issue.md +0 -0
  14. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/.github/ISSUE_TEMPLATE/1-bug_report.md +0 -0
  15. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/.github/ISSUE_TEMPLATE/2-feature_request.md +0 -0
  16. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/.github/pull_request_template.md +0 -0
  17. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/.github/workflows/add-issue-to-project-tracker.yml +0 -0
  18. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/.github/workflows/linting.yml +0 -0
  19. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/.github/workflows/publish-to-pypi.yml +0 -0
  20. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/.github/workflows/smoke-test.yml +0 -0
  21. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/.github/workflows/testing-and-coverage.yml +0 -0
  22. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/.gitignore +0 -0
  23. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/.pre-commit-config.yaml +0 -0
  24. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/LICENSE +0 -0
  25. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/README.md +0 -0
  26. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/environment.yml +0 -0
  27. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/pyproject.toml +0 -0
  28. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/setup.cfg +0 -0
  29. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/setup.py +0 -0
  30. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/pz_rail_astro_tools.egg-info/dependency_links.txt +0 -0
  31. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/pz_rail_astro_tools.egg-info/requires.txt +0 -0
  32. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/pz_rail_astro_tools.egg-info/top_level.txt +0 -0
  33. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/rail/astro_tools/__init__.py +0 -0
  34. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/rail/creation/degraders/grid_selection.py +0 -0
  35. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/rail/creation/degraders/observing_condition_degrader.py +0 -0
  36. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/rail/creation/degraders/photometric_errors.py +0 -0
  37. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/rail/creation/degraders/spectroscopic_degraders.py +0 -0
  38. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/rail/creation/degraders/spectroscopic_selections.py +0 -0
  39. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/rail/creation/engines/gcr_engine.py +0 -0
  40. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/rail/examples_data/creation_data/data/HSC_grid_settings.pkl +0 -0
  41. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/rail/examples_data/creation_data/data/hsc_ratios_and_specz.hdf5 +0 -0
  42. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/rail/examples_data/creation_data/data/survey_conditions/DC2-dr6-galcounts-i20-i25.3-nside-128.fits +0 -0
  43. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/rail/examples_data/creation_data/data/survey_conditions/DC2-mask-neg-nside-128.fits +0 -0
  44. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/rail/examples_data/creation_data/data/survey_conditions/minion_1016_dc2_Median_airmass_i_and_nightlt1825_HEAL.fits +0 -0
  45. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/rail/examples_data/creation_data/data/survey_conditions/minion_1016_dc2_Median_fiveSigmaDepth_i_and_nightlt1825_HEAL.fits +0 -0
  46. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/rail/examples_data/testdata/rubin_dm_dc2_example2.pq +0 -0
  47. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/rail/pipelines/degradation/apply_phot_errors.py +0 -0
  48. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/rail/pipelines/degradation/blending.py +0 -0
  49. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/rail/pipelines/degradation/spectroscopic_selection_pipeline.py +0 -0
  50. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/src/rail/tools/photometry_tools.py +0 -0
  51. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/tests/astro_tools/gcr_test_data/schema.yaml +0 -0
  52. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/tests/astro_tools/gcr_test_data/test_object_tract_4850.hdf5 +0 -0
  53. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/tests/astro_tools/test_core.py +0 -0
  54. {pz_rail_astro_tools-1.0.5 → pz_rail_astro_tools-1.0.7}/tests/astro_tools/test_gcr_engine.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pz-rail-astro-tools
3
- Version: 1.0.5
3
+ Version: 1.0.7
4
4
  Author-email: "LSST Dark Energy Science Collaboration (DESC)" <lsst-desc-rail-admin@slac.stanford.edu>
5
5
  License: MIT License
6
6
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pz-rail-astro-tools
3
- Version: 1.0.5
3
+ Version: 1.0.7
4
4
  Author-email: "LSST Dark Energy Science Collaboration (DESC)" <lsst-desc-rail-admin@slac.stanford.edu>
5
5
  License: MIT License
6
6
 
@@ -22,7 +22,6 @@ src/pz_rail_astro_tools.egg-info/requires.txt
22
22
  src/pz_rail_astro_tools.egg-info/top_level.txt
23
23
  src/rail/astro_tools/__init__.py
24
24
  src/rail/astro_tools/_version.py
25
- src/rail/creation/degraders/bl_demo.ipynb
26
25
  src/rail/creation/degraders/grid_selection.py
27
26
  src/rail/creation/degraders/observing_condition_degrader.py
28
27
  src/rail/creation/degraders/photometric_errors.py
@@ -40,6 +39,7 @@ src/rail/examples_data/testdata/rubin_dm_dc2_example2.pq
40
39
  src/rail/pipelines/degradation/apply_phot_errors.py
41
40
  src/rail/pipelines/degradation/blending.py
42
41
  src/rail/pipelines/degradation/spectroscopic_selection_pipeline.py
42
+ src/rail/pipelines/degradation/truth_to_observed.py
43
43
  src/rail/tools/photometry_tools.py
44
44
  tests/astro_tools/test_core.py
45
45
  tests/astro_tools/test_degraders.py
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '1.0.5'
16
- __version_tuple__ = version_tuple = (1, 0, 5)
15
+ __version__ = version = '1.0.7'
16
+ __version_tuple__ = version_tuple = (1, 0, 7)
@@ -0,0 +1,178 @@
1
+ """Model for Creating Unrecognized Blends"""
2
+
3
+ from ceci.config import StageParameter as Param
4
+ from rail.creation.degrader import Degrader
5
+ from rail.core.data import PqHandle
6
+ from rail.core.common_params import SHARED_PARAMS
7
+ import numpy as np, pandas as pd
8
+ import FoFCatalogMatching
9
+
10
+
11
+ class UnrecBlModel(Degrader):
12
+ """Model for Creating Unrecognized Blends.
13
+
14
+ Finding objects nearby each other. Merge them into one blended
15
+ Use Friends of Friends for matching. May implement shape matching in the future.
16
+ Take avergaged Ra and Dec for blended source, and sum up fluxes in each band. May implement merged shapes in the future.
17
+
18
+ """
19
+ name = "UnrecBlModel"
20
+ config_options = Degrader.config_options.copy()
21
+ config_options.update(ra_label=Param(str, 'ra', msg='ra column name'),
22
+ dec_label=Param(str, 'dec', msg='dec column name'),
23
+ linking_lengths=Param(float, 1.0, msg='linking_lengths for FoF matching'),
24
+ bands=SHARED_PARAMS,
25
+ ref_band=SHARED_PARAMS,
26
+ redshift_col=SHARED_PARAMS,
27
+ match_size=Param(bool, False, msg='consider object size for finding blends'),
28
+ match_shape=Param(bool, False, msg='consider object shape for finding blends'),
29
+ obj_size=Param(str, 'obj_size', msg='object size column name'),
30
+ a=Param(str, 'semi_major', msg='semi major axis column name'),
31
+ b=Param(str, 'semi_minor', msg='semi minor axis column name'),
32
+ theta=Param(str, 'orientation', msg='orientation angle column name'))
33
+
34
+ outputs = [("output", PqHandle), ("compInd", PqHandle)]
35
+
36
+ blend_info_cols = ['group_id', 'n_obj', 'brightest_flux', 'total_flux', 'z_brightest', 'z_weighted', 'z_mean', 'z_stdev']
37
+
38
+ def __call__(self, sample, seed: int = None):
39
+ """The main interface method for ``Degrader``.
40
+
41
+ Applies degradation.
42
+
43
+ This will attach the sample to this `Degrader` (for introspection and
44
+ provenance tracking).
45
+
46
+ Then it will call the run() and finalize() methods, which need to be
47
+ implemented by the sub-classes.
48
+
49
+ The run() method will need to register the data that it creates to this
50
+ Estimator by using ``self.add_data('output', output_data)``.
51
+
52
+ Finally, this will return a PqHandle providing access to that output
53
+ data.
54
+
55
+ Parameters
56
+ ----------
57
+ sample : table-like
58
+ The sample to be degraded
59
+ seed : int, default=None
60
+ An integer to set the numpy random seed
61
+
62
+ Returns
63
+ -------
64
+ output_data : PqHandle
65
+ A handle giving access to a table with degraded sample
66
+ """
67
+ if seed is not None:
68
+ self.config.seed = seed
69
+
70
+ self.set_data("input", sample)
71
+ self.run()
72
+ self.finalize()
73
+
74
+ return {'output':self.get_handle("output"), 'compInd':self.get_handle("compInd")}
75
+
76
+ def __match_bl__(self, data):
77
+
78
+ """Group sources with friends of friends"""
79
+
80
+ ra_label, dec_label = self.config.ra_label, self.config.dec_label
81
+ linking_lengths = self.config.linking_lengths
82
+
83
+ results = FoFCatalogMatching.match({'truth': data}, linking_lengths=linking_lengths, ra_label=ra_label, dec_label=dec_label)
84
+ results.remove_column('catalog_key')
85
+
86
+ results = results.to_pandas(index='row_index')
87
+ results.sort_values(by='row_index', inplace=True)
88
+
89
+ ## adding the group id as the last column to data
90
+ matchData = pd.merge(data, results, left_index=True, right_index=True)
91
+
92
+ return matchData, results
93
+
94
+ def __merge_bl__(self, data):
95
+
96
+ """Merge sources within a group into unrecognized blends."""
97
+
98
+ group_id = data['group_id']
99
+ unique_id = np.unique(group_id)
100
+
101
+ ra_label, dec_label = self.config.ra_label, self.config.dec_label
102
+ cols = [ra_label, dec_label] + [b for b in self.config.bands] + self.blend_info_cols
103
+
104
+ N_rows = len(unique_id)
105
+ N_cols = len(cols)
106
+
107
+ # compute the fluxes once for all the galaxies
108
+ fluxes = {b:10**(-data[b]/2.5) for b in self.config.bands}
109
+
110
+ # pull the column indices
111
+ idx_ra = cols.index(ra_label)
112
+ idx_dec = cols.index(dec_label)
113
+ idx_n_obj = cols.index('n_obj')
114
+ idx_brightest_flux = cols.index('brightest_flux')
115
+ idx_total_flux = cols.index('total_flux')
116
+ idx_z_brightest = cols.index('z_brightest')
117
+ idx_z_mean = cols.index('z_mean')
118
+ idx_z_weighted = cols.index('z_weighted')
119
+ idx_z_stdev = cols.index('z_stdev')
120
+
121
+ mergeData = np.zeros((N_rows, N_cols))
122
+ for i, id in enumerate(unique_id):
123
+
124
+ # Get the mask for this grouping
125
+ mask = data['group_id'] == id
126
+
127
+ # Get the data and fluxes for this grouping
128
+ this_group = data[mask]
129
+ these_fluxes = {b:fluxes[b][mask] for b in self.config.bands}
130
+
131
+ # Pull put some useful stuff
132
+ n_obj = len(this_group)
133
+ ref_fluxes = these_fluxes[self.config.ref_band]
134
+ these_redshifts = this_group[self.config.redshift_col]
135
+
136
+ ## take the average position for the blended source
137
+ mergeData[i, idx_ra] = this_group[ra_label].mean()
138
+ mergeData[i, idx_dec] = this_group[dec_label].mean()
139
+
140
+ ## sum up the fluxes into the blended source
141
+ for b in self.config.bands:
142
+ mergeData[i, cols.index(b)] = -2.5*np.log10(np.sum(these_fluxes[b]))
143
+
144
+ brighest_idx = np.argmax(ref_fluxes)
145
+
146
+ mergeData[i, idx_n_obj] = n_obj
147
+ mergeData[i, idx_brightest_flux] = ref_fluxes.max()
148
+ mergeData[i, idx_total_flux] = np.sum(ref_fluxes)
149
+ mergeData[i, idx_z_brightest] = these_redshifts.iloc[brighest_idx]
150
+ mergeData[i, idx_z_mean] = np.mean(these_redshifts)
151
+ mergeData[i, idx_z_weighted] = np.sum(these_redshifts*ref_fluxes)/np.sum(ref_fluxes)
152
+ if n_obj > 1:
153
+ mergeData[i, idx_z_stdev] = np.std(these_redshifts)
154
+ else:
155
+ mergeData[i, idx_z_stdev] = 0.
156
+
157
+ mergeData[:,cols.index('group_id')] = unique_id
158
+ mergeData_df = pd.DataFrame(data=mergeData, columns=cols)
159
+ mergeData_df['group_id'] = mergeData_df['group_id'].astype(int)
160
+ mergeData_df['n_obj'] = mergeData_df['n_obj'].astype(int)
161
+
162
+ return mergeData_df
163
+
164
+ def run(self):
165
+ """Return pandas DataFrame with blending errors."""
166
+
167
+ # Load the input catalog
168
+ data = self.get_data("input")
169
+
170
+ # Match for close-by objects
171
+ matchData, compInd = self.__match_bl__(data)
172
+
173
+ # Merge matched objects into unrec-bl
174
+ blData = self.__merge_bl__(matchData)
175
+
176
+ # Return the new catalog and component index in original catalog
177
+ self.add_data("output", blData)
178
+ self.add_data("compInd", compInd)
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env python
2
+ # coding: utf-8
3
+
4
+ # Prerquisites, os, and numpy
5
+ import os
6
+ import numpy as np
7
+
8
+ # Various rail modules
9
+ from rail.tools.photometry_tools import Dereddener, Reddener
10
+
11
+ from rail.core.stage import RailStage, RailPipeline
12
+
13
+ import ceci
14
+
15
+ from rail.core.utils import RAILDIR
16
+
17
+ from rail.creation.degraders.unrec_bl_model import UnrecBlModel
18
+
19
+ from .spectroscopic_selection_pipeline import SELECTORS, CommonConfigParams
20
+ from .apply_phot_errors import ERROR_MODELS
21
+
22
+
23
+ if 'PZ_DUSTMAP_DIR' not in os.environ: # pragma: no cover
24
+ os.environ['PZ_DUSTMAP_DIR'] = '.'
25
+
26
+ dustmap_dir = os.path.expandvars("${PZ_DUSTMAP_DIR}")
27
+
28
+
29
+ class TruthToObservedPipeline(RailPipeline):
30
+
31
+ default_input_dict = dict(input='dummy.in')
32
+
33
+ def __init__(self, error_models=None, selectors=None, blending=False):
34
+ RailPipeline.__init__(self)
35
+
36
+ DS = RailStage.data_store
37
+ DS.__class__.allow_overwrite = True
38
+
39
+ if error_models is None:
40
+ error_models = ERROR_MODELS.copy()
41
+
42
+ if selectors is None:
43
+ selectors = SELECTORS.copy()
44
+
45
+ config_pars = CommonConfigParams.copy()
46
+
47
+ self.reddener = Reddener.build(
48
+ dustmap_dir=dustmap_dir,
49
+ copy_all_cols=True,
50
+ )
51
+ previous_stage = self.reddener
52
+
53
+ if blending:
54
+ self.unrec_bl = UnrecBlModel.build()
55
+ previous_stage = self.unrec_bl
56
+
57
+ for key, val in error_models.items():
58
+ error_model_class = ceci.PipelineStage.get_stage(val['ErrorModel'], val['Module'])
59
+ the_error_model = error_model_class.make_and_connect(
60
+ name=f'error_model_{key}',
61
+ connections=dict(input=previous_stage.io.output),
62
+ hdf5_groupname='',
63
+ )
64
+ self.add_stage(the_error_model)
65
+ previous_stage = the_error_model
66
+
67
+ dereddener_errors = Dereddener.make_and_connect(
68
+ name=f"deredden_{key}",
69
+ dustmap_dir=dustmap_dir,
70
+ connections=dict(input=previous_stage.io.output),
71
+ copy_all_cols=True,
72
+ )
73
+ self.add_stage(dereddener_errors)
74
+ previous_stage = dereddener_errors
75
+
76
+ for key2, val2 in selectors.items():
77
+ the_class = ceci.PipelineStage.get_stage(val2['Select'], val2['Module'])
78
+ the_selector = the_class.make_and_connect(
79
+ name=f'select_{key}_{key2}',
80
+ connections=dict(input=previous_stage.io.output),
81
+ **config_pars,
82
+ )
83
+ self.add_stage(the_selector)
@@ -83,16 +83,14 @@ def data_for_bl():
83
83
  DS.__class__.allow_overwrite = True
84
84
 
85
85
  # generate random normal data
86
- columns=['ra', 'dec', 'redshift', 'u', 'g', 'r', 'i', 'z', 'y']
86
+ columns=['ra', 'dec', 'u', 'g', 'r', 'i', 'z', 'y', 'redshift']
87
87
  rng = np.random.default_rng(0)
88
88
  x = rng.normal(loc=23, scale=3, size=(1000, len(columns)))
89
89
 
90
90
  # replace positions with constrained values
91
91
  x[:, 0] = np.random.uniform(low=0, high=0.02, size=1000)
92
92
  x[:, 1] = np.random.uniform(low=0, high=0.02, size=1000)
93
-
94
- # replace redshifts with reasonable values
95
- x[:, 2] = np.linspace(0, 2, x.shape[0])
93
+ x[:, 8] = np.random.uniform(low=0, high=3.00, size=1000)
96
94
 
97
95
  # return data in handle wrapping a pandas DataFrame
98
96
  df = pd.DataFrame(x, columns=columns)
@@ -423,12 +421,26 @@ def test_EucliErrorModel(data):
423
421
 
424
422
  def test_BLModel(data_for_bl):
425
423
  # Setup the stage
426
- degrader = UnrecBlModel.make_stage()
424
+
425
+ degrader = UnrecBlModel.make_stage(
426
+ name='unrec_bl_model',
427
+ ra_label='ra',
428
+ dec_label='dec',
429
+ linking_lengths=1.0,
430
+ bands='ugrizy',
431
+ ref_band='i',
432
+ seed=1234)
427
433
 
428
434
  # Apply the degrader and get the data out
429
- degraded_data = degrader(data_for_bl).data
435
+ outputs = degrader(data_for_bl)
436
+ degraded_data = outputs['output'].data
437
+ truth_components = outputs['compInd'].data
430
438
 
431
439
  # Check output data has less rows than input data
432
440
  assert degraded_data.shape[0] < data_for_bl.data.shape[0]
433
441
 
442
+ # Check components has the same rows as input data
443
+ assert truth_components.shape[0] == data_for_bl.data.shape[0]
444
+
434
445
  os.remove(degrader.get_output(degrader.get_aliased_tag("output"), final_name=True))
446
+ os.remove(degrader.get_output(degrader.get_aliased_tag("compInd"), final_name=True))
@@ -0,0 +1,17 @@
1
+ import os
2
+ from rail.utils.testing_utils import build_and_read_pipeline
3
+
4
+ import pytest
5
+
6
+ @pytest.mark.parametrize(
7
+ "pipeline_class, options",
8
+ [
9
+ ('rail.pipelines.degradation.apply_phot_errors.ApplyPhotErrorsPipeline', {}),
10
+ ('rail.pipelines.degradation.blending.BlendingPipeline', {}),
11
+ ('rail.pipelines.degradation.spectroscopic_selection_pipeline.SpectroscopicSelectionPipeline', {}),
12
+ ('rail.pipelines.degradation.truth_to_observed.TruthToObservedPipeline', {'blending':True}),
13
+ ]
14
+ )
15
+ def test_build_and_read_pipeline(pipeline_class, options):
16
+ build_and_read_pipeline(pipeline_class, **options)
17
+
@@ -1,206 +0,0 @@
1
- {
2
- "cells": [
3
- {
4
- "cell_type": "markdown",
5
- "id": "2610a0f0-0c71-4401-896f-734442bcd66d",
6
- "metadata": {},
7
- "source": [
8
- "## Blending Degrader demo\n",
9
- "\n",
10
- "author: Shuang Liang\n",
11
- "\n",
12
- "This notebook demonstrate the use of `rail.creation.degradation.unrec_bl_model`, which uses Friends of Friends to finds sources close to each other and merge them into unrecognized blends"
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
- "from rail.creation.degraders.unrec_bl_model import UnrecBlModel\n",
23
- "\n",
24
- "from rail.core.data import PqHandle\n",
25
- "from rail.core.stage import RailStage\n",
26
- "\n",
27
- "import matplotlib.pyplot as plt\n",
28
- "import pandas as pd, numpy as np"
29
- ]
30
- },
31
- {
32
- "cell_type": "code",
33
- "execution_count": null,
34
- "id": "6912a740-31ea-4987-b06d-81ff17cd895a",
35
- "metadata": {},
36
- "outputs": [],
37
- "source": [
38
- "DS = RailStage.data_store\n",
39
- "DS.__class__.allow_overwrite = True\n"
40
- ]
41
- },
42
- {
43
- "cell_type": "markdown",
44
- "id": "a282c2ed-141b-4507-8254-dc8fbc9864dc",
45
- "metadata": {},
46
- "source": [
47
- "### Create a random catalog with ugrizy+YJHF bands as the the true input"
48
- ]
49
- },
50
- {
51
- "cell_type": "code",
52
- "execution_count": null,
53
- "id": "1078bc2a-fc54-41c3-bd30-6c447bb971d4",
54
- "metadata": {},
55
- "outputs": [],
56
- "source": [
57
- "data = np.random.normal(23, 3, size = (1000,12))\n",
58
- "data[:, 0] = np.random.uniform(low=0, high=0.03, size=1000)\n",
59
- "data[:, 1] = np.random.uniform(low=0, high=0.03, size=1000)\n",
60
- "\n",
61
- "data_df = pd.DataFrame(data=data, # values\n",
62
- " columns=['ra', 'dec', 'u', 'g', 'r', 'i', 'z', 'y', 'Y', 'J', 'H', 'F'])\n",
63
- "\n",
64
- "data_truth = DS.add_data('input', data_df, PqHandle)"
65
- ]
66
- },
67
- {
68
- "cell_type": "code",
69
- "execution_count": null,
70
- "id": "33c99a4d-8375-4003-9a9a-70fa85a3eb82",
71
- "metadata": {},
72
- "outputs": [],
73
- "source": [
74
- "#data_df.to_parquet('bl_test.pq')"
75
- ]
76
- },
77
- {
78
- "cell_type": "code",
79
- "execution_count": null,
80
- "id": "a5636721-a734-4746-bd93-8101bc558b6e",
81
- "metadata": {},
82
- "outputs": [],
83
- "source": [
84
- "plt.scatter(data_truth.data['ra'], data_truth.data['dec'], s=5)\n",
85
- "plt.xlabel(\"Ra [Deg]\", fontsize=14)\n",
86
- "plt.ylabel(\"Dec [Deg]\", fontsize=14)\n",
87
- "plt.show()\n"
88
- ]
89
- },
90
- {
91
- "cell_type": "markdown",
92
- "id": "1da27deb-d167-4f38-8c59-f270184d6ab3",
93
- "metadata": {},
94
- "source": [
95
- "### The blending model"
96
- ]
97
- },
98
- {
99
- "cell_type": "code",
100
- "execution_count": null,
101
- "id": "a07f72a0-e24c-4844-90f0-d5a49ac4362b",
102
- "metadata": {},
103
- "outputs": [],
104
- "source": [
105
- "## radius cut is in arcsecs\n",
106
- "blModel = UnrecBlModel.make_stage(name='unrec_bl_model', ra_label='ra', dec_label='dec', linking_lengths=1.0, \\\n",
107
- " bands='ugrizyYJHF')\n",
108
- "blModel.get_config_dict()\n"
109
- ]
110
- },
111
- {
112
- "cell_type": "code",
113
- "execution_count": null,
114
- "id": "e5f4862a-0621-46d4-8901-7e84b461c424",
115
- "metadata": {},
116
- "outputs": [],
117
- "source": [
118
- "samples_w_bl = blModel(data_truth)\n",
119
- "samples_w_bl()\n"
120
- ]
121
- },
122
- {
123
- "cell_type": "code",
124
- "execution_count": null,
125
- "id": "bc5158dd-f474-4731-b847-b4a7358656b9",
126
- "metadata": {},
127
- "outputs": [],
128
- "source": [
129
- "fig, ax = plt.subplots(figsize=(6, 5), dpi=100)\n",
130
- "\n",
131
- "ax.scatter(data_truth.data['ra'], data_truth.data['dec'], s=10, facecolors='none', edgecolors='b', label='Original')\n",
132
- "ax.scatter(samples_w_bl.data['ra'], samples_w_bl.data['dec'], s=5, c='r', label='w. Unrec-BL')\n",
133
- "\n",
134
- "ax.legend(loc=2, fontsize=12)\n",
135
- "ax.set_xlabel(\"Ra [Deg]\", fontsize=14)\n",
136
- "ax.set_ylabel(\"Dec [Deg]\", fontsize=14)\n",
137
- "\n",
138
- "plt.show()\n"
139
- ]
140
- },
141
- {
142
- "cell_type": "code",
143
- "execution_count": null,
144
- "id": "268b3d37-b7fd-4ac1-8457-2104a87c9e6d",
145
- "metadata": {},
146
- "outputs": [],
147
- "source": [
148
- "b = 'r'\n",
149
- "plt.hist(data_truth.data[b], bins=np.linspace(10, 30, 20), label='Original')\n",
150
- "plt.hist(samples_w_bl.data[b], bins=np.linspace(10, 30, 20), fill=False, label='w. Unrec-BL')\n",
151
- "\n",
152
- "plt.xlabel(fr'Magnitude ${b}$', fontsize=14)\n",
153
- "plt.legend(fontsize=12)\n",
154
- "plt.show()\n"
155
- ]
156
- },
157
- {
158
- "cell_type": "code",
159
- "execution_count": null,
160
- "id": "a1d51c15-1e04-4b22-9abb-9b267965dbeb",
161
- "metadata": {},
162
- "outputs": [],
163
- "source": [
164
- "flux = 10**(-(data_truth.data[b]-28.10)/2.5) # r band zp for lsst is 28.10\n",
165
- "flux_bl = 10**(-(samples_w_bl.data[b]-28.10)/2.5)\n",
166
- "\n",
167
- "plt.hist(flux, bins=np.linspace(0, 10000, 40), label='Original')\n",
168
- "plt.hist(flux_bl, bins=np.linspace(0, 10000, 40), fill=False, label='w. Unrec-BL')\n",
169
- "\n",
170
- "plt.xlabel(fr'Flux ${b}$', fontsize=14)\n",
171
- "plt.yscale('log')\n",
172
- "plt.legend(fontsize=12)\n",
173
- "plt.show()\n"
174
- ]
175
- },
176
- {
177
- "cell_type": "code",
178
- "execution_count": null,
179
- "id": "da2b37c8-4667-4ad2-ad09-b1c68d2612b8",
180
- "metadata": {},
181
- "outputs": [],
182
- "source": []
183
- }
184
- ],
185
- "metadata": {
186
- "kernelspec": {
187
- "display_name": "Python 3 (ipykernel)",
188
- "language": "python",
189
- "name": "python3"
190
- },
191
- "language_info": {
192
- "codemirror_mode": {
193
- "name": "ipython",
194
- "version": 3
195
- },
196
- "file_extension": ".py",
197
- "mimetype": "text/x-python",
198
- "name": "python",
199
- "nbconvert_exporter": "python",
200
- "pygments_lexer": "ipython3",
201
- "version": "3.12.3"
202
- }
203
- },
204
- "nbformat": 4,
205
- "nbformat_minor": 5
206
- }
@@ -1,98 +0,0 @@
1
- """Model for Creating Unrecognized Blends"""
2
-
3
- from ceci.config import StageParameter as Param
4
- from rail.creation.degrader import Degrader
5
- import numpy as np, pandas as pd
6
- import FoFCatalogMatching
7
-
8
-
9
- class UnrecBlModel(Degrader):
10
- """Model for Creating Unrecognized Blends.
11
-
12
- Finding objects nearby each other. Merge them into one blended
13
- Use Friends of Friends for matching. May implement shape matching in the future.
14
- Take avergaged Ra and Dec for blended source, and sum up fluxes in each band. May implement merged shapes in the future.
15
-
16
- """
17
- name = "UnrecBlModel"
18
- config_options = Degrader.config_options.copy()
19
- config_options.update(ra_label=Param(str, 'ra', msg='ra column name'),
20
- dec_label=Param(str, 'dec', msg='dec column name'),
21
- linking_lengths=Param(float, 1.0, msg='linking_lengths for FoF matching'),
22
- bands=Param(str, 'ugrizy', msg='name of filters'),
23
- match_size=Param(bool, False, msg='consider object size for finding blends'),
24
- match_shape=Param(bool, False, msg='consider object shape for finding blends'),
25
- obj_size=Param(str, 'obj_size', msg='object size column name'),
26
- a=Param(str, 'semi_major', msg='semi major axis column name'),
27
- b=Param(str, 'semi_minor', msg='semi minor axis column name'),
28
- theta=Param(str, 'orientation', msg='orientation angle column name'))
29
-
30
- def __match_bl__(self, data):
31
-
32
- """Group sources with friends of friends"""
33
-
34
- ra_label, dec_label = self.config.ra_label, self.config.dec_label
35
- linking_lengths = self.config.linking_lengths
36
-
37
- results = FoFCatalogMatching.match({'truth': data}, linking_lengths=linking_lengths, ra_label=ra_label, dec_label=dec_label)
38
- results.remove_column('catalog_key')
39
-
40
- results = results.to_pandas(index='row_index')
41
- results.sort_values(by='row_index', inplace=True)
42
-
43
- ## adding the group id as the last column to data
44
- matchData = pd.merge(data, results, left_index=True, right_index=True)
45
-
46
- return matchData
47
-
48
- def __merge_bl__(self, data):
49
-
50
- """Merge sources within a group into unrecognized blends."""
51
-
52
- group_id = data['group_id']
53
- unique_id = np.unique(group_id)
54
-
55
- ra_label, dec_label = self.config.ra_label, self.config.dec_label
56
-
57
- cols = list(data.columns)
58
- ra_ind = cols.index(ra_label)
59
- dec_ind = cols.index(dec_label)
60
- bands_ind = {b:cols.index(b) for b in self.config.bands}
61
-
62
- N_rows = len(unique_id)
63
- N_cols = len(cols)
64
-
65
- mergeData = np.zeros((N_rows, N_cols))
66
-
67
- for i, id in enumerate(unique_id):
68
-
69
- this_group = data.query(f'group_id=={id}')
70
-
71
- ## take the average position for the blended source
72
- mergeData[i, ra_ind] = this_group[ra_label].mean()
73
- mergeData[i, dec_ind] = this_group[dec_label].mean()
74
-
75
- ## sum up the fluxes into the blended source
76
- for b in self.config.bands:
77
- mergeData[i, bands_ind[b]] = -2.5*np.log10(np.sum(10**(-this_group[b]/2.5)))
78
-
79
- mergeData[:,-1] = unique_id
80
- mergeData_df = pd.DataFrame(data=mergeData, columns=cols)
81
- mergeData_df['group_id'] = mergeData_df['group_id'].astype(int)
82
-
83
- return mergeData_df
84
-
85
- def run(self):
86
- """Return pandas DataFrame with blending errors."""
87
-
88
- # Load the input catalog
89
- data = self.get_data("input")
90
-
91
- # Match for close-by objects
92
- matchData = self.__match_bl__(data)
93
-
94
- # Merge matched objects into unrec-bl
95
- blData = self.__merge_bl__(matchData)
96
-
97
- # Return the new catalog
98
- self.add_data("output", blData)
@@ -1,16 +0,0 @@
1
- import os
2
- from rail.utils.testing_utils import build_and_read_pipeline
3
-
4
- import pytest
5
-
6
- @pytest.mark.parametrize(
7
- "pipeline_class",
8
- [
9
- 'rail.pipelines.degradation.apply_phot_errors.ApplyPhotErrorsPipeline',
10
- 'rail.pipelines.degradation.blending.BlendingPipeline',
11
- 'rail.pipelines.degradation.spectroscopic_selection_pipeline.SpectroscopicSelectionPipeline',
12
- ]
13
- )
14
- def test_build_and_read_pipeline(pipeline_class):
15
- build_and_read_pipeline(pipeline_class)
16
-