Skip to content

Commit 65b6c42

Browse files
authored
Merge branch 'develop' into binospec_overscan
2 parents 2368b57 + 8bdebdc commit 65b6c42

File tree

7 files changed

+92
-42
lines changed

7 files changed

+92
-42
lines changed

pypeit/core/coadd.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2199,7 +2199,7 @@ def combspec(waves, fluxes, ivars, gpms, sn_smooth_npix,
21992199

22002200
return wave_grid_mid, wave_stack, flux_stack, ivar_stack, gpm_stack
22012201

2202-
def multi_combspec(waves, fluxes, ivars, masks, sn_smooth_npix=None,
2202+
def multi_combspec(waves, fluxes, ivars, gpms, sn_smooth_npix=None,
22032203
wave_method='linear', dwave=None, dv=None, dloglam=None, spec_samp_fact=1.0, wave_grid_min=None,
22042204
wave_grid_max=None, ref_percentile=70.0, maxiter_scale=5,
22052205
sigrej_scale=3.0, scale_method='auto', hand_scale=None, sn_min_polyscale=2.0, sn_min_medscale=0.5,
@@ -2213,17 +2213,17 @@ def multi_combspec(waves, fluxes, ivars, masks, sn_smooth_npix=None,
22132213
Parameters
22142214
----------
22152215
waves : list
2216-
List of `numpy.ndarray`_ wavelength arrays with shape (nspec_i,) with
2216+
List of `numpy.ndarray`_ arrays with shape (nspec_i,) with
22172217
the wavelength arrays of the spectra to be coadded.
22182218
fluxes : list
2219-
List of `numpy.ndarray`_ wavelength arrays with shape (nspec_i,) with
2219+
List of `numpy.ndarray`_ arrays with shape (nspec_i,) with
22202220
the flux arrays of the spectra to be coadded.
22212221
ivars : list
2222-
List of `numpy.ndarray`_ wavelength arrays with shape (nspec_i,) with
2222+
List of `numpy.ndarray`_ arrays with shape (nspec_i,) with
22232223
the ivar arrays of the spectra to be coadded.
2224-
masks : list
2225-
List of `numpy.ndarray`_ wavelength arrays with shape (nspec_i,) with
2226-
the mask arrays of the spectra to be coadded.
2224+
gpms : list
2225+
List of `numpy.ndarray`_ arrays with shape (nspec_i,) with
2226+
the GPM arrays of the spectra to be coadded (True=good).
22272227
sn_smooth_npix : int, optional
22282228
Number of pixels to median filter by when computing S/N used to decide
22292229
how to scale and weight spectra. If set to None, the code will determine
@@ -2319,7 +2319,7 @@ def multi_combspec(waves, fluxes, ivars, masks, sn_smooth_npix=None,
23192319
core.wavecal.wvutils.py for more.
23202320
wave_stack : `numpy.ndarray`_, (ngrid,)
23212321
Wavelength grid for stacked spectrum. As discussed above, this is the
2322-
weighted average of the wavelengths of each spectrum that contriuted to
2322+
weighted average of the wavelengths of each spectrum that contributed to
23232323
a bin in the input wave_grid wavelength grid. It thus has ngrid
23242324
elements, whereas wave_grid has ngrid+1 elements to specify the ngrid
23252325
total number of bins. Note that wave_stack is NOT simply the wave_grid
@@ -2341,7 +2341,7 @@ def multi_combspec(waves, fluxes, ivars, masks, sn_smooth_npix=None,
23412341
log.info('Using a sn_smooth_npix={:d} to decide how to scale and weight your spectra'.format(sn_smooth_npix))
23422342

23432343
wave_grid_mid, wave_stack, flux_stack, ivar_stack, mask_stack = combspec(
2344-
waves, fluxes,ivars, masks, wave_method=wave_method, dwave=dwave, dv=dv, dloglam=dloglam,
2344+
waves, fluxes,ivars, gpms, wave_method=wave_method, dwave=dwave, dv=dv, dloglam=dloglam,
23452345
spec_samp_fact=spec_samp_fact, wave_grid_min=wave_grid_min, wave_grid_max=wave_grid_max, ref_percentile=ref_percentile,
23462346
maxiter_scale=maxiter_scale, sigrej_scale=sigrej_scale, scale_method=scale_method, hand_scale=hand_scale,
23472347
sn_min_medscale=sn_min_medscale, sn_min_polyscale=sn_min_polyscale, sn_smooth_npix=sn_smooth_npix,

pypeit/core/wavecal/autoid.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,8 @@ def full_template(spec, lamps, par, ok_mask, det, binspectral, nsnippet=2, slit_
11001100
if par['reid_arxiv'] is None:
11011101
raise PypeItError('WavelengthSolutionPar parameter `reid_arxiv` not '
11021102
'specified for "full_template" method.')
1103+
wvstr = "the entire wavelength range" if par['wvrng_arxiv'] is None else f"wavelength range {par['wvrng_arxiv']} Angstroms"
1104+
log.info(f"Loading template from {par['reid_arxiv']} for detector {det} and {wvstr}")
11031105
temp_wv_og, temp_spec_og, temp_bin, order, lines_pix, lines_wav, lines_fit_ord = \
11041106
waveio.load_template(par['reid_arxiv'], det, wvrng=par['wvrng_arxiv'])
11051107
else:

pypeit/core/wavecal/templates.py

Lines changed: 71 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656

5757

5858
def build_template(in_files, slits, wv_cuts, binspec, outroot, outdir=None,
59-
normalize=False, subtract_conti=False, wvspec=None,
59+
scalespec=False, scalevals=None, subtract_conti=False, wvspec=None,
6060
lowredux=False, ifiles=None, det_cut=None, chk=False,
6161
miny=None, overwrite=True, ascii_tbl=False, in_vac=True,
6262
shift_wave=False, binning=None, micron=False,
@@ -93,9 +93,16 @@ def build_template(in_files, slits, wv_cuts, binspec, outroot, outdir=None,
9393
Show a plot or two
9494
miny (float):
9595
Impose a minimum value
96-
normalize (bool, optional):
97-
If provided multiple in_files, normalize each
98-
snippet to have the same maximum amplitude.
96+
scalespec (bool, optional):
97+
If True, scale the spectrum by the provided scalevals. If
98+
scalevals is None, the spectrum will be scaled to the
99+
normalization value (default is 10000). Default is False, which will not scale.
100+
scalevals (list, optional):
101+
If scalespec is True, the values to scale each spectrum by.
102+
Default is None, which will not scale. If provided, the
103+
length of scalevals must match the number of in_files. If
104+
scalespec is True and scalevals is None, the spectrum will
105+
be scaled to the normalization value (default is 10000).
99106
subtract_conti (bool, optional):
100107
Subtract the continuum for the final archive
101108
ascii_tbl (bool, optional):
@@ -117,6 +124,12 @@ def build_template(in_files, slits, wv_cuts, binspec, outroot, outdir=None,
117124
ifiles = np.arange(len(in_files))
118125
if binning is None:
119126
binning = [None]*len(ifiles)
127+
if scalespec and scalevals is None:
128+
scalevals = [None]*len(ifiles)
129+
# Prepare an axis if we are debugging
130+
if chk:
131+
plt.clf()
132+
ax = plt.gca()
120133
# Load xidl file
121134
# Grab it
122135
# Load and splice
@@ -128,6 +141,7 @@ def build_template(in_files, slits, wv_cuts, binspec, outroot, outdir=None,
128141
# Loop on the files
129142
for kk, slit in enumerate(slits):
130143
# Load up
144+
pypeitFit = None # Default value, in case a PypeItFit is not available
131145
if wvspec is None:
132146
in_file = in_files[ifiles[kk]]
133147
if lowredux:
@@ -146,9 +160,24 @@ def build_template(in_files, slits, wv_cuts, binspec, outroot, outdir=None,
146160
log.info("wvmin, wvmax of {}: {}, {}".format(in_file, wv_vac.min(), wv_vac.max()))
147161
# Cut
148162
if len(slits) > 1:
163+
# Plot the inputs if we are debugging
164+
if chk:
165+
ax.plot(wv_vac, spec, drawstyle='steps-mid')
166+
# Rebin spec if binning is different
167+
if binning is not None and binning[kk] != binspec:
168+
npix_orig = spec.size
169+
x_orig = np.arange(npix_orig) / float(npix_orig - 1)
170+
npix = int(npix_orig * binning[kk] / binspec)
171+
x = np.arange(npix) / float(npix - 1)
172+
# Interpolate the wavelengths and spectrum onto the new grid
173+
spec = (interp1d(x_orig, spec, axis=0,
174+
bounds_error=False, fill_value='extrapolate'))(x)
175+
wv_vac = (interp1d(x_orig, wv_vac, axis=0,
176+
bounds_error=False, fill_value='extrapolate'))(x)
177+
# Default good pixels
149178
wvmin, wvmax = grab_wvlim(kk, wv_cuts, len(slits))
150-
# Default
151179
gdi = (wv_vac > wvmin) & (wv_vac < wvmax)
180+
npix = wv_vac.size
152181
if shift_wave:
153182
if len(lvals) > 0:
154183
# Find pixel closet to end
@@ -161,16 +190,10 @@ def build_template(in_files, slits, wv_cuts, binspec, outroot, outdir=None,
161190
# Delta pix -- approximate but should be pretty good
162191
dpix = dwv_specs / dwv_snipp[ipix]
163192
# Calculate new wavelengths
164-
npix = wv_vac.size
165-
# Rebin spec?
166-
if binning is not None and binning[kk] != binspec:
167-
npix_orig = spec.size
168-
x_orig = np.arange(npix_orig) / float(npix_orig - 1)
169-
x = np.arange(npix) / float(npix - 1)
170-
spec = (interp1d(x_orig, spec, axis=0,
171-
bounds_error=False, fill_value='extrapolate'))(x)
172-
# Evaluate
173-
new_wave = pypeitFit.eval((-dpix + np.arange(npix)) / (npix - 1))
193+
if pypeitFit is None:
194+
new_wave = -dwv_specs + wv_vac
195+
else:
196+
new_wave = pypeitFit.eval((-dpix + np.arange(npix)) / (npix - 1))
174197
# Range
175198
iend = np.argmin(np.abs(new_wave - wvmax))
176199
# Interpolate
@@ -189,15 +212,16 @@ def build_template(in_files, slits, wv_cuts, binspec, outroot, outdir=None,
189212
for kk,spec in enumerate(yvals):
190213
_, _, _, _, spec_cont_sub = wvutils.arc_lines_from_spec(spec)
191214
yvals[kk] = spec_cont_sub
192-
# Normalize?
193-
if normalize:
194-
norm_val = 10000.
195-
# Max values
196-
maxs = []
197-
for kk,spec in enumerate(yvals):
198-
mx = np.max(spec)
199-
spec = spec * norm_val / mx
200-
yvals[kk] = spec
215+
# Scale the input spectra by the user-provided scalevals or by the maximum value of each snippet
216+
if scalespec:
217+
for kk, spec in enumerate(yvals):
218+
if scalevals[kk] is not None:
219+
scale_factor = scalevals[kk]
220+
else:
221+
norm_val = 10000.
222+
# Use the normalization value if scalevals is not provided
223+
scale_factor = norm_val / np.max(spec)
224+
yvals[kk] = spec * scale_factor
201225
# Concatenate
202226
nwspec = np.concatenate(yvals)
203227
nwwv = np.concatenate(lvals)
@@ -206,9 +230,7 @@ def build_template(in_files, slits, wv_cuts, binspec, outroot, outdir=None,
206230
nwspec = np.maximum(nwspec, miny)
207231
# Check
208232
if chk:
209-
plt.clf()
210-
ax = plt.gca()
211-
ax.plot(nwwv, nwspec)
233+
ax.plot(nwwv, nwspec, 'k-', drawstyle='steps-mid')
212234
plt.show()
213235
# Generate the table
214236
wvutils.write_template(nwwv, nwspec, binspec, outdir, outroot, det_cut=det_cut, overwrite=overwrite)
@@ -603,7 +625,7 @@ def main(flg):
603625
lcut = [7840.]
604626
wfile = template_path / 'Keck_LRIS' / 'R600_7500' / 'MasterWaveCalib_I_1_01.json'
605627
build_template(wfile, slits, lcut, binspec, outroot, lowredux=False,
606-
chk=True, normalize=True, subtract_conti=True)
628+
chk=True, scalespec=True, subtract_conti=True)
607629

608630
# ##################################
609631
# Magellan/MagE
@@ -877,6 +899,21 @@ def main(flg):
877899
outfile = dataPaths.reid_arxiv.path / iout
878900
tbl.write(outfile, overwrite=True)
879901
print("Wrote: {}".format(outfile))
902+
# Keck KCWI
903+
if flg & (2**35):
904+
pass
905+
# Keck KCRM
906+
if flg & (2**36):
907+
dirc = template_path / 'KCWI' / 'RM1'
908+
infiles = [dirc / 'keck_kcrm_rm1_lcen6230.fits',dirc / 'keck_kcrm_rm1_lcen7010.fits']
909+
outroot = 'keck_kcrm_RM1.fits'
910+
slits = [0, 0]
911+
binspec = 1 # Desired binning
912+
binning = [1, 2] # Spectral binning of each infile
913+
scalevals = [1.0, 3.4] # Scale the second one down by 2x to match the first
914+
lcut = [6910.0]
915+
build_template(infiles, slits, lcut, binspec, outroot, scalespec=True, scalevals=scalevals,
916+
binning=binning, reid_files=True, shift_wave=True, chk=True)
880917

881918

882919
# Command line execution
@@ -939,5 +976,11 @@ def main(flg):
939976
# P200 Triplespec
940977
#flg += 2**34
941978

979+
# Keck KCWI
980+
#flg += 2**35
981+
982+
# Keck KCRM
983+
flg += 2**36
984+
942985
main(flg)
943986

pypeit/data/arc_lines/reid_arxiv/README

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ DEIMOS
99

1010
Generated with the scripts in pypeit.core.wavecal.templates.py
1111

12+
Keck/KCWI + Keck/KCRM
13+
---------------------
14+
15+
Generated with the scripts in pypeit.core.wavecal.templates.py
16+
1217
Kastb
1318
-----
1419

70.3 KB
Binary file not shown.

pypeit/data/standards/blackbody/blackbody_info.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# This directory contains data files for the blackbody stars
2-
# presented in Suzuki & Fukugita, 2018, AJ, 156, 219:
2+
# presented in Suzuki & Fukugita (2018), AJ, 156, 219:
33
# https://ui.adsabs.harvard.edu/abs/2018AJ....156..219S/abstract
4-
# with updates from Cooke, Suzuki, Prochaska 2025:
5-
# <insert abs link here>
4+
# with updates from Cooke, Suzuki, Prochaska (2026), MNRAS, 546, 2246:
5+
# https://ui.adsabs.harvard.edu/abs/2026MNRAS.546f2246C/abstract
66
# The flux distribution over the range 3000 – 25000A can be
77
# generated using the "a" and "T" parameters in Table below,
88
# combined with Equation 1 from the above paper.

pypeit/wavecalib.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,7 @@ def build_wv_calib(self, arccen, method, skip_QA=False,
667667
arcfitter.store_solution(final_fit[str(slit_idx)], "", self.binspectral,
668668
# JTS: Commented out as it seems the
669669
# store solution function does not
670-
# take these arguments any more.
670+
# take these arguments anymore.
671671
# specname=self.spectrograph.name,
672672
# gratname="UNKNOWN", dispangl="UNKNOWN"
673673
)
@@ -739,7 +739,7 @@ def build_wv_calib(self, arccen, method, skip_QA=False,
739739
raise PypeItError('Unrecognized wavelength calibration method: {:}'.format(method))
740740

741741
# Build the DataContainer
742-
if self.par['redo_slits'] is not None:
742+
if self.par['redo_slits'] is not None and prev_wvcalib is not None:
743743
# If we are only redoing slits, we start from the
744744
# previous wv_calib and update only the (good) redone slits
745745
self.wv_calib = prev_wvcalib

0 commit comments

Comments
 (0)