Skip to content

Commit fec07d0

Browse files
authored
Merge pull request #2606 from desihub/coadd_normalization
Rescale individual exposures before coaddition
2 parents 3c0e3f7 + 6922100 commit fec07d0

File tree

8 files changed

+352
-24
lines changed

8 files changed

+352
-24
lines changed

py/desispec/coaddition.py

Lines changed: 313 additions & 13 deletions
Large diffs are not rendered by default.

py/desispec/data/qa/qa-params.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ exposure_qa:
3737
# bad POSITIONING flag
3838
bad_positions_mask : "BROKENFIBER|MISSINGPOSITION|BADPOSITION|POORPOSITION"
3939
# bad QAFIBERSTATUS flag
40-
bad_qafstatus_mask : "UNASSIGNED|BROKENFIBER|MISSINGPOSITION|BADPOSITION|POORPOSITION|BADFIBER|BADTRACE|BADFLAT|BADARC|MANYBADCOL|MANYREJECTED|BADAMPB|BADAMPR|BADAMPZ|BADPETALPOS|BADPETALSKY|BADPETALSTDSTAR|BADPETALFLUXCAL|BADPETALSNR|BADREADNOISE|LOWEFFTIME"
40+
bad_qafstatus_mask : "UNASSIGNED|BROKENFIBER|MISSINGPOSITION|BADPOSITION|POORPOSITION|BADFIBER|BADTRACE|BADFLAT|BADARC|MANYREJECTED|BADAMPB|BADAMPR|BADAMPZ|BADPETALPOS|BADPETALSKY|BADPETALSTDSTAR|BADPETALFLUXCAL|BADPETALSNR|BADREADNOISE|LOWEFFTIME"
4141
# bad QAFIBERSTATUS per-petal flag
4242
bad_petal_mask : "BADPETALPOS|BADPETALSKY|BADPETALSTDSTAR|BADPETALFLUXCAL|BADPETALSNR|BADREADNOISE"
4343

py/desispec/fiberbitmasking.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def get_fiberbitmasked_frame_arrays(frame,bitmask=None,ivar_framemask=True,retur
5555
Example bitmask list::
5656
5757
bitmask = [fmsk.BROKENFIBER,fmsk.UNASSIGNED,fmsk.BADFIBER,\
58-
fmsk.BADTRACE,fmsk.MANYBADCOL, fmsk.MANYREJECTED]
58+
fmsk.BADTRACE, fmsk.MANYREJECTED]
5959
bitmask = get_fiberbitmask_comparison_value(kind='fluxcalib', band='brz')
6060
bitmask = 'fluxcalib'
6161
bitmask = 4128780
@@ -154,8 +154,8 @@ def get_flat_fiberbitmask_val(band):
154154
Return mask of bad FIBERSTATUS bits for fiberflats
155155
i.e. fibers with these bits set have a bad fiberflat and cannot be used
156156
"""
157-
return (fmsk.BROKENFIBER | fmsk.BRIGHTNEIGHBOR | fmsk.BADFIBER | fmsk.BADTRACE | fmsk.BADARC | \
158-
fmsk.MANYBADCOL | fmsk.MANYREJECTED )
157+
return (fmsk.BROKENFIBER | fmsk.BRIGHTNEIGHBOR | fmsk.BADFIBER | \
158+
fmsk.BADTRACE | fmsk.BADARC | fmsk.MANYREJECTED )
159159

160160
def get_fluxcalib_fiberbitmask_val(band):
161161
"""
@@ -182,10 +182,9 @@ def get_all_nonamp_fiberbitmask_val():
182182
NEARCHARGETRAP and VARIABLETHRU are also not included since
183183
they are ok for some types of processing but not others.
184184
"""
185-
return (fmsk.BROKENFIBER | fmsk.MISSINGPOSITION | \
186-
fmsk.BADPOSITION | fmsk.BRIGHTNEIGHBOR | \
187-
fmsk.BADFIBER | fmsk.BADTRACE | fmsk.BADARC | fmsk.BADFLAT | \
188-
fmsk.MANYBADCOL | fmsk.MANYREJECTED )
185+
return (fmsk.BROKENFIBER | fmsk.MISSINGPOSITION | fmsk.BADPOSITION | \
186+
fmsk.BRIGHTNEIGHBOR | fmsk.BADFIBER | fmsk.BADTRACE | \
187+
fmsk.BADARC | fmsk.BADFLAT | fmsk.MANYREJECTED )
189188

190189
def get_justamps_fiberbitmask():
191190
"""

py/desispec/io/fibermap.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@
169169
('IN_COADD_B', 'bool', '', 'Was this exposure included in B coadd', 'coadd'),
170170
('IN_COADD_R', 'bool', '', 'Was this exposure included in R coadd', 'coadd'),
171171
('IN_COADD_Z', 'bool', '', 'Was this exposure included in Z coadd', 'coadd'),
172+
('COADD_NORM', 'f4', '', 'Flux normalization coefficient for coadd', 'coadd'),
173+
('SIGMA_COADD_NORM', 'f4', '', 'Error on COADD_NORM', 'coadd'),
172174
)
173175

174176
# dict to allow unit tests etc that augment fibermaps to look up the

py/desispec/maskbits.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
- [BADTRACE, 17, "Bad trace solution"]
7171
- [BADFLAT, 18, "Bad fiber flat"]
7272
- [BADARC, 19, "Bad arc solution"]
73-
- [MANYBADCOL, 20, ">10% of spectral bins are bad columns"]
73+
- [VARIABLE, 20, "Object or calibration suspected to be variable"]
7474
- [MANYREJECTED, 21, ">10% of spectral bins rejected in extraction"]
7575
- [BADAMPB, 22, "Issues in the amplifier readouts of camera B make this unusable"]
7676
- [BADAMPR, 23, "Issues in the amplifier readouts of camera R make this unusable"]

py/desispec/scripts/coadd_spectra.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ def parse(options=None):
4444
help="coadd spectra of different cameras. works only if wavelength grids are aligned")
4545
parser.add_argument("--onetile", action="store_true",
4646
help="input spectra are from a single tile")
47-
47+
parser.add_argument("--no-normalize", action="store_true",
48+
help="multiplicative normalization factors are not computed for each target exposure prior to coaddition")
49+
parser.add_argument("--norm-chi2-threshold", type=float, default=0.1,
50+
help="minimum reduced chi‑squared value to trigger per‑exposure normalization; use 0 to renormalize all science targets")
4851

4952
if options is None:
5053
args = parser.parse_args()
@@ -156,7 +159,8 @@ def main(args=None):
156159
onetile=args.onetile)
157160
else :
158161
log.info("coadding ...")
159-
coadd(spectra, cosmics_nsig=args.nsig, onetile=args.onetile)
162+
coadd(spectra, cosmics_nsig=args.nsig, onetile=args.onetile,
163+
no_normalize=args.no_normalize, norm_chi2_threshold=args.norm_chi2_threshold)
160164

161165
if args.lin_step is not None :
162166
log.info("resampling ...")

py/desispec/test/test_coadd.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,28 @@ def test_coadd(self):
230230
self.assertEqual(s1.flux['b'].shape[0], 1)
231231
self.assertIsInstance(s1.scores, Table)
232232

233+
def test_coadd_normalization(self):
234+
"""Test coaddition"""
235+
nspec, nwave = 10, 300
236+
bands = ('b','z')
237+
s1 = self._random_spectra( ns=nspec, nw=nwave, bands=bands)
238+
self.assertEqual(s1.flux['b'].shape[0], nspec)
239+
self.assertIsInstance(s1.scores, Table)
240+
241+
#- three different targets, one with only one exposure
242+
s1.fibermap['TARGETID'][:5] = 10
243+
for b in bands:
244+
# offset first spectrum
245+
s1.flux[b][0] +=5
246+
s1.ivar[b][0] /=3
247+
s1.fibermap['TARGETID'][5:] = 11
248+
s1.fibermap['TARGETID'][-1] = 12
249+
s1.fibermap['OBJTYPE'] = 'TGT'
250+
coadd(s1, onetile=True, no_normalize=False)
251+
self.assertEqual(s1.flux['b'].shape[0], 3)
252+
self.assertEqual(s1.exp_fibermap['COADD_NORM'][-1], 1)
253+
self.assertIsInstance(s1.scores, Table)
254+
233255
def test_coadd_exposures(self):
234256
"""Test coadd_exposures doesn't mutate input and matches in-place coadd"""
235257
nspec, nwave = 3, 10

py/desispec/test/test_lite.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ def setUpClass(cls):
4747
fibermap['TILEID'] = 1000 * np.ones(nspec, dtype='i4')
4848
fibermap['FIBERSTATUS'] = np.zeros(nspec, dtype='i4')
4949
fibermap['DESI_TARGET'] = np.arange(nspec, dtype='i8')
50+
fibermap['OBJTYPE'] = 'TGT'
5051

5152
cls.spectra = Spectra(bands=bands, wave=wave, flux=flux, ivar=ivar,
5253
resolution_data=rdat, fibermap=fibermap)

0 commit comments

Comments
 (0)