pz-rail-astro-tools 1.0.6__py3-none-any.whl → 1.0.8__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.

@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: pz-rail-astro-tools
3
- Version: 1.0.6
3
+ Version: 1.0.8
4
4
  Author-email: "LSST Dark Energy Science Collaboration (DESC)" <lsst-desc-rail-admin@slac.stanford.edu>
5
5
  License: MIT License
6
6
 
@@ -34,9 +34,9 @@ Requires-Python: >=3.9
34
34
  Description-Content-Type: text/markdown
35
35
  License-File: LICENSE
36
36
  Requires-Dist: deprecated
37
- Requires-Dist: pz-rail-base >=1.0.3
37
+ Requires-Dist: pz-rail-base>=1.0.3
38
38
  Requires-Dist: numpy
39
- Requires-Dist: pandas >=2.2.2
39
+ Requires-Dist: pandas>=2.2.2
40
40
  Requires-Dist: astropy
41
41
  Requires-Dist: healpy
42
42
  Requires-Dist: photerr
@@ -45,11 +45,11 @@ Requires-Dist: pz-hyperbolic-temp
45
45
  Requires-Dist: lsstdesc-gcr-catalogs
46
46
  Requires-Dist: FoFCatalogMatching
47
47
  Provides-Extra: dev
48
- Requires-Dist: tables-io[full] ; extra == 'dev'
49
- Requires-Dist: pytest ; extra == 'dev'
50
- Requires-Dist: pytest-cov ; extra == 'dev'
51
- Requires-Dist: pre-commit ; extra == 'dev'
52
- Requires-Dist: pylint ; extra == 'dev'
48
+ Requires-Dist: tables-io[full]; extra == "dev"
49
+ Requires-Dist: pytest; extra == "dev"
50
+ Requires-Dist: pytest-cov; extra == "dev"
51
+ Requires-Dist: pre-commit; extra == "dev"
52
+ Requires-Dist: pylint; extra == "dev"
53
53
 
54
54
  # pz-rail-astro-tools
55
55
 
@@ -1,11 +1,11 @@
1
1
  rail/astro_tools/__init__.py,sha256=4J-E0Ug0RP3Y38g8kJ6auAPDPEI4Osf19tuSOAACfxk,432
2
- rail/astro_tools/_version.py,sha256=T17ZEPR5Omt5RLA0TuZWTufRi58PzGIPek75nFcuMQY,411
2
+ rail/astro_tools/_version.py,sha256=vy0P95Si-KzUl6NsixjrWEHfr5xcmkA_oO_S3bQRmvE,411
3
3
  rail/creation/degraders/grid_selection.py,sha256=gJKM0AYdG-HgvjTS3ovupbyoB5bxKhZn9FAAb94pQXY,12429
4
4
  rail/creation/degraders/observing_condition_degrader.py,sha256=y6Nal_kSdAz6N8amY4oV6mQ3upa2nIgVbV9P6F0PKwA,19977
5
- rail/creation/degraders/photometric_errors.py,sha256=xeLI5dH4P-kseClMsy7vTes6EBXh2Ca8_-9-nnFt3b0,4396
5
+ rail/creation/degraders/photometric_errors.py,sha256=jx7JL5-lzKm6IbNTYwHqkEeGZduXC59Tad2UNwEJWlc,4703
6
6
  rail/creation/degraders/spectroscopic_degraders.py,sha256=27kylHksXf4MhgdfefSL7C2S3WCK-0YQ1Oc8dOHIBhc,5350
7
7
  rail/creation/degraders/spectroscopic_selections.py,sha256=TXlghBWLAniokbUpgw4IQVf3y3R6BwralS0ddiVgMp4,22205
8
- rail/creation/degraders/unrec_bl_model.py,sha256=8kDTDADMOu46BPRBKG9HtVCI9Q71WeQkxYcItzcQC8M,5192
8
+ rail/creation/degraders/unrec_bl_model.py,sha256=E89DVV67FcHozCjtUz4ty3Ak3q8H9lnNnh5wNWi_R8M,7476
9
9
  rail/creation/engines/gcr_engine.py,sha256=LSp599uQGu8GcFNUmib792ScQwSB_Og8VxPLTt9aSNU,2981
10
10
  rail/examples_data/creation_data/data/HSC_grid_settings.pkl,sha256=zpJoSR9TSnDyL64DPXivIMam3fn6GOZoyoJoeBj2LAk,141
11
11
  rail/examples_data/creation_data/data/hsc_ratios_and_specz.hdf5,sha256=liH54wuuuHxToqjoAwQ_fFmEefk3haNweVThMwdDKN4,13823712
@@ -14,12 +14,13 @@ rail/examples_data/creation_data/data/survey_conditions/DC2-mask-neg-nside-128.f
14
14
  rail/examples_data/creation_data/data/survey_conditions/minion_1016_dc2_Median_airmass_i_and_nightlt1825_HEAL.fits,sha256=twvyce70G3h1MQnGGFQJG9wZc8UbuNqXc6mjtiuaL1s,1581120
15
15
  rail/examples_data/creation_data/data/survey_conditions/minion_1016_dc2_Median_fiveSigmaDepth_i_and_nightlt1825_HEAL.fits,sha256=RbMMFSVJQxGhZnL4BnISE9VTNljfTZwV6Bax6NxverY,1581120
16
16
  rail/examples_data/testdata/rubin_dm_dc2_example2.pq,sha256=_Iihbbcz1A332QAkaMiFacT4QAbBQBMTOwpfrS7AclE,25884
17
- rail/pipelines/degradation/apply_phot_errors.py,sha256=vj2avYWxfavORIXzJ7925V9YkuRmRMBSP0C8-DmgkSw,1958
17
+ rail/pipelines/degradation/apply_phot_errors.py,sha256=E6H1Qza1IkO9VWqqxeny6MYkw3gURWscwKxzgUHEOko,2087
18
18
  rail/pipelines/degradation/blending.py,sha256=oxZHy1Tai70wT4g4xnBr24z2LxmR1p_J6lMoTN0nFc8,564
19
19
  rail/pipelines/degradation/spectroscopic_selection_pipeline.py,sha256=D0sDi6nrasv5CvQkLXgmMp0QbDrhGFRXzt6sWjlbD68,2028
20
+ rail/pipelines/degradation/truth_to_observed.py,sha256=nfzMKdZd69_P1HnHy56UcjMUpFdRHf6g55oNhlW5Gzg,2995
20
21
  rail/tools/photometry_tools.py,sha256=wfKAeMz5T_CYDPC661MHtU1aJXVqomvahZl87KuE7uY,19541
21
- pz_rail_astro_tools-1.0.6.dist-info/LICENSE,sha256=tLMEN21HbzvT-7umOVVvPjaJZbQxCa-2bAeYLwG5Q04,1102
22
- pz_rail_astro_tools-1.0.6.dist-info/METADATA,sha256=FZnRuWE7ouiTsuikU28i2mrssyUgeGsNsEcYW6xzpGs,4040
23
- pz_rail_astro_tools-1.0.6.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
24
- pz_rail_astro_tools-1.0.6.dist-info/top_level.txt,sha256=6R6sqn-85I8YZTzmB9gv7sqckB2QaOTHbu-QLGTWBRE,5
25
- pz_rail_astro_tools-1.0.6.dist-info/RECORD,,
22
+ pz_rail_astro_tools-1.0.8.dist-info/LICENSE,sha256=tLMEN21HbzvT-7umOVVvPjaJZbQxCa-2bAeYLwG5Q04,1102
23
+ pz_rail_astro_tools-1.0.8.dist-info/METADATA,sha256=6crQYG2g1fqpab7nJGcE-I2pXAbhy0qkoiERUSj2NmM,4033
24
+ pz_rail_astro_tools-1.0.8.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
25
+ pz_rail_astro_tools-1.0.8.dist-info/top_level.txt,sha256=6R6sqn-85I8YZTzmB9gv7sqckB2QaOTHbu-QLGTWBRE,5
26
+ pz_rail_astro_tools-1.0.8.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.5.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -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.6'
16
- __version_tuple__ = version_tuple = (1, 0, 6)
15
+ __version__ = version = '1.0.8'
16
+ __version_tuple__ = version_tuple = (1, 0, 8)
@@ -47,21 +47,27 @@ class PhotoErrorModel(Noisifier):
47
47
  default = val.default
48
48
 
49
49
  # Add this param to config_options
50
- self.config[key] = Param(
50
+ # Use setattr() becuase ceci.StageConfig has
51
+ # implemented __setitem__ to just set the value
52
+ # rather than add the parameters
53
+ param = Param(
51
54
  None, # Let PhotErr handle type checking
52
55
  default,
53
56
  msg="See the main docstring for details about this parameter.",
54
57
  required=False,
55
58
  )
59
+ setattr(self.config, key, param)
56
60
 
57
61
  def reload_pars(self, args):
58
62
  """ This is needed b/c the parameters are dynamically defined,
59
63
  so we have to reload them _after_ then have been defined """
60
- copy_args = args.copy()
61
64
  if isinstance(args, dict):
65
+ # coming from python, add 'config' to the configuration
66
+ copy_args = args.copy()
62
67
  copy_args['config'] = args
63
68
  else: # pragma: no cover
64
- copy_args['config'] = vars(args)
69
+ # coming from cli, just convert to a dict
70
+ copy_args = vars(args).copy()
65
71
  self.load_configs(copy_args)
66
72
  self._io_checked = False
67
73
  self.check_io()
@@ -3,10 +3,13 @@
3
3
  from ceci.config import StageParameter as Param
4
4
  from rail.creation.degrader import Degrader
5
5
  from rail.core.data import PqHandle
6
+ from rail.core.common_params import SHARED_PARAMS
6
7
  import numpy as np, pandas as pd
7
8
  import FoFCatalogMatching
8
9
 
9
10
 
11
+ lsst_zp_dict = {'u':12.65, 'g':14.69, 'r':14.56, 'i': 14.38, 'z':13.99, 'y': 13.02}
12
+
10
13
  class UnrecBlModel(Degrader):
11
14
  """Model for Creating Unrecognized Blends.
12
15
 
@@ -20,7 +23,10 @@ class UnrecBlModel(Degrader):
20
23
  config_options.update(ra_label=Param(str, 'ra', msg='ra column name'),
21
24
  dec_label=Param(str, 'dec', msg='dec column name'),
22
25
  linking_lengths=Param(float, 1.0, msg='linking_lengths for FoF matching'),
23
- bands=Param(str, 'ugrizy', msg='name of filters'),
26
+ bands=SHARED_PARAMS,
27
+ zp_dict=Param(dict, lsst_zp_dict, msg='magnitude zeropoints dictionary'),
28
+ ref_band=SHARED_PARAMS,
29
+ redshift_col=SHARED_PARAMS,
24
30
  match_size=Param(bool, False, msg='consider object size for finding blends'),
25
31
  match_shape=Param(bool, False, msg='consider object shape for finding blends'),
26
32
  obj_size=Param(str, 'obj_size', msg='object size column name'),
@@ -30,6 +36,8 @@ class UnrecBlModel(Degrader):
30
36
 
31
37
  outputs = [("output", PqHandle), ("compInd", PqHandle)]
32
38
 
39
+ blend_info_cols = ['group_id', 'n_obj', 'brightest_flux', 'total_flux', 'z_brightest', 'z_weighted', 'z_mean', 'z_stdev']
40
+
33
41
  def __call__(self, sample, seed: int = None):
34
42
  """The main interface method for ``Degrader``.
35
43
 
@@ -89,32 +97,73 @@ class UnrecBlModel(Degrader):
89
97
  def __merge_bl__(self, data):
90
98
 
91
99
  """Merge sources within a group into unrecognized blends."""
92
-
100
+
93
101
  group_id = data['group_id']
94
102
  unique_id = np.unique(group_id)
95
103
 
96
104
  ra_label, dec_label = self.config.ra_label, self.config.dec_label
97
- cols = [ra_label, dec_label] + [b for b in self.config.bands] + ['group_id']
105
+ cols = [ra_label, dec_label] + [b for b in self.config.bands] + [self.config.redshift_col] + self.blend_info_cols
98
106
 
99
107
  N_rows = len(unique_id)
100
108
  N_cols = len(cols)
101
109
 
110
+ # compute the fluxes once for all the galaxies
111
+ fluxes = {b:10**(-(data[b] - self.config.zp_dict[b])/2.5) for b in self.config.bands}
112
+
113
+ # pull the column indices
114
+ idx_ra = cols.index(ra_label)
115
+ idx_dec = cols.index(dec_label)
116
+ idx_redshift = cols.index(self.config.redshift_col)
117
+ idx_n_obj = cols.index('n_obj')
118
+ idx_brightest_flux = cols.index('brightest_flux')
119
+ idx_total_flux = cols.index('total_flux')
120
+ idx_z_brightest = cols.index('z_brightest')
121
+ idx_z_mean = cols.index('z_mean')
122
+ idx_z_weighted = cols.index('z_weighted')
123
+ idx_z_stdev = cols.index('z_stdev')
124
+
102
125
  mergeData = np.zeros((N_rows, N_cols))
103
126
  for i, id in enumerate(unique_id):
104
127
 
105
- this_group = data.query(f'group_id=={id}')
128
+ # Get the mask for this grouping
129
+ mask = data['group_id'] == id
130
+
131
+ # Get the data and fluxes for this grouping
132
+ this_group = data[mask]
133
+ these_fluxes = {b:fluxes[b][mask] for b in self.config.bands}
134
+
135
+ # Pull put some useful stuff
136
+ n_obj = len(this_group)
137
+ ref_fluxes = these_fluxes[self.config.ref_band]
138
+ these_redshifts = this_group[self.config.redshift_col]
106
139
 
107
140
  ## take the average position for the blended source
108
- mergeData[i, cols.index(ra_label)] = this_group[ra_label].mean()
109
- mergeData[i, cols.index(dec_label)] = this_group[dec_label].mean()
141
+ mergeData[i, idx_ra] = this_group[ra_label].mean()
142
+ mergeData[i, idx_dec] = this_group[dec_label].mean()
110
143
 
111
144
  ## sum up the fluxes into the blended source
112
145
  for b in self.config.bands:
113
- mergeData[i, cols.index(b)] = -2.5*np.log10(np.sum(10**(-this_group[b]/2.5)))
146
+ mergeData[i, cols.index(b)] = -2.5*np.log10(np.sum(these_fluxes[b])) + self.config.zp_dict[b]
147
+
148
+ brighest_idx = np.argmax(ref_fluxes)
149
+ redshifts = these_redshifts.iloc[brighest_idx]
150
+
151
+ mergeData[i, idx_redshift] = redshifts
152
+ mergeData[i, idx_n_obj] = n_obj
153
+ mergeData[i, idx_brightest_flux] = ref_fluxes.max()
154
+ mergeData[i, idx_total_flux] = np.sum(ref_fluxes)
155
+ mergeData[i, idx_z_brightest] = redshifts
156
+ mergeData[i, idx_z_mean] = np.mean(these_redshifts)
157
+ mergeData[i, idx_z_weighted] = np.sum(these_redshifts*ref_fluxes)/np.sum(ref_fluxes)
158
+ if n_obj > 1:
159
+ mergeData[i, idx_z_stdev] = np.std(these_redshifts)
160
+ else:
161
+ mergeData[i, idx_z_stdev] = 0.
114
162
 
115
163
  mergeData[:,cols.index('group_id')] = unique_id
116
164
  mergeData_df = pd.DataFrame(data=mergeData, columns=cols)
117
165
  mergeData_df['group_id'] = mergeData_df['group_id'].astype(int)
166
+ mergeData_df['n_obj'] = mergeData_df['n_obj'].astype(int)
118
167
 
119
168
  return mergeData_df
120
169
 
@@ -133,4 +182,3 @@ class UnrecBlModel(Degrader):
133
182
  # Return the new catalog and component index in original catalog
134
183
  self.add_data("output", blData)
135
184
  self.add_data("compInd", compInd)
136
-
@@ -13,6 +13,7 @@ from rail.core.stage import RailStage, RailPipeline
13
13
  import ceci
14
14
 
15
15
  from rail.core.utils import RAILDIR
16
+ from rail.utils import catalog_utils
16
17
 
17
18
  if 'PZ_DUSTMAP_DIR' not in os.environ:
18
19
  os.environ['PZ_DUSTMAP_DIR'] = '.'
@@ -62,6 +63,7 @@ class ApplyPhotErrorsPipeline(RailPipeline):
62
63
  name=f'error_model_{key}',
63
64
  connections=dict(input=previous_stage.io.output),
64
65
  hdf5_groupname='',
66
+ renameDict=catalog_utils.CatalogConfigBase.active_class().band_name_dict(),
65
67
  )
66
68
  self.add_stage(the_error_model)
67
69
  previous_stage = the_error_model
@@ -0,0 +1,89 @@
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
+ from rail.utils import catalog_utils
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
+ active_catalog_config = catalog_utils.CatalogConfigBase.active_class()
40
+ band_name_dict = active_catalog_config.band_name_dict()
41
+
42
+ if error_models is None:
43
+ error_models = ERROR_MODELS.copy()
44
+
45
+ if selectors is None:
46
+ selectors = SELECTORS.copy()
47
+
48
+ config_pars = CommonConfigParams.copy()
49
+ config_pars['colnames'] = band_name_dict.copy()
50
+ config_pars['colnames']['redshift'] = active_catalog_config.redshift_col
51
+
52
+ self.reddener = Reddener.build(
53
+ dustmap_dir=dustmap_dir,
54
+ copy_all_cols=True,
55
+ )
56
+ previous_stage = self.reddener
57
+
58
+ if blending:
59
+ self.unrec_bl = UnrecBlModel.build()
60
+ previous_stage = self.unrec_bl
61
+
62
+ for key, val in error_models.items():
63
+ error_model_class = ceci.PipelineStage.get_stage(val['ErrorModel'], val['Module'])
64
+ the_error_model = error_model_class.make_and_connect(
65
+ name=f'error_model_{key}',
66
+ connections=dict(input=previous_stage.io.output),
67
+ hdf5_groupname='',
68
+ renameDict=band_name_dict,
69
+ )
70
+ self.add_stage(the_error_model)
71
+ previous_stage = the_error_model
72
+
73
+ dereddener_errors = Dereddener.make_and_connect(
74
+ name=f"deredden_{key}",
75
+ dustmap_dir=dustmap_dir,
76
+ connections=dict(input=previous_stage.io.output),
77
+ copy_all_cols=True,
78
+ )
79
+ self.add_stage(dereddener_errors)
80
+ previous_stage = dereddener_errors
81
+
82
+ for key2, val2 in selectors.items():
83
+ the_class = ceci.PipelineStage.get_stage(val2['Select'], val2['Module'])
84
+ the_selector = the_class.make_and_connect(
85
+ name=f'select_{key}_{key2}',
86
+ connections=dict(input=previous_stage.io.output),
87
+ **config_pars,
88
+ )
89
+ self.add_stage(the_selector)