pyreduce-astro 0.7a4__cp313-cp313-win_amd64.whl → 0.7a6__cp313-cp313-win_amd64.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.
- pyreduce/__main__.py +86 -22
- pyreduce/cli.py +1 -1
- pyreduce/clib/Release/_slitfunc_2d.obj +0 -0
- pyreduce/clib/Release/_slitfunc_bd.obj +0 -0
- pyreduce/clib/_slitfunc_2d.cp313-win_amd64.pyd +0 -0
- pyreduce/clib/_slitfunc_bd.cp313-win_amd64.pyd +0 -0
- pyreduce/combine_frames.py +33 -25
- pyreduce/instruments/aj.yaml +1 -1
- pyreduce/instruments/andes.py +17 -17
- pyreduce/instruments/andes.yaml +1 -1
- pyreduce/instruments/common.py +257 -69
- pyreduce/instruments/crires_plus.py +26 -36
- pyreduce/instruments/crires_plus.yaml +0 -2
- pyreduce/instruments/filters.py +1 -1
- pyreduce/instruments/harpn.py +14 -14
- pyreduce/instruments/harpn.yaml +2 -2
- pyreduce/instruments/harps.py +21 -14
- pyreduce/instruments/harps.yaml +2 -2
- pyreduce/instruments/instrument_info.py +14 -14
- pyreduce/instruments/jwst_miri.py +6 -4
- pyreduce/instruments/jwst_miri.yaml +2 -2
- pyreduce/instruments/jwst_niriss.py +12 -8
- pyreduce/instruments/jwst_niriss.yaml +2 -2
- pyreduce/instruments/lick_apf.py +3 -3
- pyreduce/instruments/lick_apf.yaml +2 -2
- pyreduce/instruments/mcdonald.py +5 -5
- pyreduce/instruments/mcdonald.yaml +3 -3
- pyreduce/instruments/metis_ifu.py +5 -5
- pyreduce/instruments/metis_ifu.yaml +3 -3
- pyreduce/instruments/metis_lss.py +5 -5
- pyreduce/instruments/metis_lss.yaml +3 -3
- pyreduce/instruments/micado.py +5 -5
- pyreduce/instruments/micado.yaml +3 -3
- pyreduce/instruments/models.py +30 -6
- pyreduce/instruments/neid.py +51 -79
- pyreduce/instruments/neid.yaml +40 -41
- pyreduce/instruments/nirspec.py +10 -10
- pyreduce/instruments/nirspec.yaml +1 -1
- pyreduce/instruments/nte.py +6 -6
- pyreduce/instruments/nte.yaml +1 -1
- pyreduce/instruments/uves.py +8 -8
- pyreduce/instruments/uves.yaml +2 -2
- pyreduce/instruments/xshooter.py +4 -4
- pyreduce/instruments/xshooter.yaml +3 -3
- pyreduce/pipeline.py +32 -32
- pyreduce/reduce.py +39 -39
- pyreduce/settings/settings_AJ.json +1 -1
- pyreduce/settings/settings_ANDES.json +1 -1
- pyreduce/settings/settings_CRIRES_PLUS.json +1 -1
- pyreduce/settings/settings_HARPN.json +1 -1
- pyreduce/settings/settings_HARPS.json +1 -1
- pyreduce/settings/settings_JWST_MIRI.json +1 -1
- pyreduce/settings/settings_JWST_NIRISS.json +1 -1
- pyreduce/settings/settings_LICK_APF.json +1 -1
- pyreduce/settings/settings_MCDONALD.json +1 -1
- pyreduce/settings/settings_METIS_IFU.json +1 -1
- pyreduce/settings/settings_METIS_LSS.json +1 -1
- pyreduce/settings/settings_MICADO.json +1 -1
- pyreduce/settings/settings_NEID.json +9 -18
- pyreduce/settings/settings_NIRSPEC.json +1 -1
- pyreduce/settings/settings_NTE.json +1 -1
- pyreduce/settings/settings_UVES.json +1 -1
- pyreduce/settings/settings_XSHOOTER.json +1 -1
- pyreduce/settings/settings_pyreduce.json +1 -1
- pyreduce/settings/settings_schema.json +3 -3
- {pyreduce_astro-0.7a4.dist-info → pyreduce_astro-0.7a6.dist-info}/METADATA +5 -7
- {pyreduce_astro-0.7a4.dist-info → pyreduce_astro-0.7a6.dist-info}/RECORD +73 -85
- pyreduce/clib/Release/_slitfunc_2d.cp311-win_amd64.exp +0 -0
- pyreduce/clib/Release/_slitfunc_2d.cp311-win_amd64.lib +0 -0
- pyreduce/clib/Release/_slitfunc_2d.cp312-win_amd64.exp +0 -0
- pyreduce/clib/Release/_slitfunc_2d.cp312-win_amd64.lib +0 -0
- pyreduce/clib/Release/_slitfunc_bd.cp311-win_amd64.exp +0 -0
- pyreduce/clib/Release/_slitfunc_bd.cp311-win_amd64.lib +0 -0
- pyreduce/clib/Release/_slitfunc_bd.cp312-win_amd64.exp +0 -0
- pyreduce/clib/Release/_slitfunc_bd.cp312-win_amd64.lib +0 -0
- pyreduce/clib/_slitfunc_2d.cp311-win_amd64.pyd +0 -0
- pyreduce/clib/_slitfunc_2d.cp312-win_amd64.pyd +0 -0
- pyreduce/clib/_slitfunc_bd.cp311-win_amd64.pyd +0 -0
- pyreduce/clib/_slitfunc_bd.cp312-win_amd64.pyd +0 -0
- /pyreduce/wavecal/{crires_plus_J1228_Open_det1.npz → crires_plus_J1228_det1.npz} +0 -0
- /pyreduce/wavecal/{crires_plus_J1228_Open_det2.npz → crires_plus_J1228_det2.npz} +0 -0
- /pyreduce/wavecal/{crires_plus_J1228_Open_det3.npz → crires_plus_J1228_det3.npz} +0 -0
- {pyreduce_astro-0.7a4.dist-info → pyreduce_astro-0.7a6.dist-info}/WHEEL +0 -0
- {pyreduce_astro-0.7a4.dist-info → pyreduce_astro-0.7a6.dist-info}/entry_points.txt +0 -0
- {pyreduce_astro-0.7a4.dist-info → pyreduce_astro-0.7a6.dist-info}/licenses/LICENSE +0 -0
pyreduce/__main__.py
CHANGED
|
@@ -4,8 +4,8 @@ PyReduce command-line interface.
|
|
|
4
4
|
Usage:
|
|
5
5
|
uv run reduce --help
|
|
6
6
|
uv run reduce run UVES HD132205 --night 2010-04-01
|
|
7
|
-
uv run reduce run UVES HD132205 --steps bias,flat,
|
|
8
|
-
uv run reduce
|
|
7
|
+
uv run reduce run UVES HD132205 --steps bias,flat,trace
|
|
8
|
+
uv run reduce trace UVES HD132205
|
|
9
9
|
uv run reduce combine --output combined.fits *.final.fits
|
|
10
10
|
"""
|
|
11
11
|
|
|
@@ -14,7 +14,7 @@ import click
|
|
|
14
14
|
ALL_STEPS = (
|
|
15
15
|
"bias",
|
|
16
16
|
"flat",
|
|
17
|
-
"
|
|
17
|
+
"trace",
|
|
18
18
|
"curvature",
|
|
19
19
|
"scatter",
|
|
20
20
|
"norm_flat",
|
|
@@ -40,7 +40,7 @@ def cli():
|
|
|
40
40
|
@click.argument("instrument")
|
|
41
41
|
@click.argument("target")
|
|
42
42
|
@click.option("--night", "-n", default=None, help="Observation night (YYYY-MM-DD)")
|
|
43
|
-
@click.option("--
|
|
43
|
+
@click.option("--channel", "-c", default=None, help="Instrument channel")
|
|
44
44
|
@click.option(
|
|
45
45
|
"--steps",
|
|
46
46
|
"-s",
|
|
@@ -71,7 +71,7 @@ def run(
|
|
|
71
71
|
instrument,
|
|
72
72
|
target,
|
|
73
73
|
night,
|
|
74
|
-
|
|
74
|
+
channel,
|
|
75
75
|
steps,
|
|
76
76
|
base_dir,
|
|
77
77
|
input_dir,
|
|
@@ -106,7 +106,7 @@ def run(
|
|
|
106
106
|
instrument=instrument,
|
|
107
107
|
target=target,
|
|
108
108
|
night=night,
|
|
109
|
-
|
|
109
|
+
channels=channel,
|
|
110
110
|
steps=steps,
|
|
111
111
|
base_dir=base_dir or "",
|
|
112
112
|
input_dir=input_dir,
|
|
@@ -279,30 +279,94 @@ def make_step_command(step_name):
|
|
|
279
279
|
|
|
280
280
|
@click.command(name=step_name)
|
|
281
281
|
@click.argument("instrument")
|
|
282
|
-
@click.argument("target")
|
|
282
|
+
@click.argument("target", required=False, default="")
|
|
283
283
|
@click.option("--night", "-n", default=None, help="Observation night")
|
|
284
|
-
@click.option("--
|
|
284
|
+
@click.option("--channel", "-c", default=None, help="Instrument channel")
|
|
285
285
|
@click.option("--base-dir", "-b", default=None, help="Base directory")
|
|
286
286
|
@click.option("--input-dir", "-i", default="raw", help="Input directory")
|
|
287
287
|
@click.option("--output-dir", "-o", default="reduced", help="Output directory")
|
|
288
288
|
@click.option("--plot", "-p", default=0, help="Plot level")
|
|
289
|
-
|
|
289
|
+
@click.option(
|
|
290
|
+
"--file",
|
|
291
|
+
"-f",
|
|
292
|
+
default=None,
|
|
293
|
+
help="Specific input file (bypasses file discovery)",
|
|
294
|
+
)
|
|
295
|
+
def cmd(
|
|
296
|
+
instrument, target, night, channel, base_dir, input_dir, output_dir, plot, file
|
|
297
|
+
):
|
|
290
298
|
from .configuration import get_configuration_for_instrument
|
|
291
299
|
from .reduce import main as reduce_main
|
|
292
300
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
301
|
+
if file:
|
|
302
|
+
# Direct file mode: run step on specific file
|
|
303
|
+
import os
|
|
304
|
+
|
|
305
|
+
import numpy as np
|
|
306
|
+
|
|
307
|
+
from . import reduce as reduce_module
|
|
308
|
+
from .configuration import get_configuration_for_instrument
|
|
309
|
+
from .instruments.instrument_info import load_instrument
|
|
310
|
+
|
|
311
|
+
inst = load_instrument(instrument)
|
|
312
|
+
channel = channel or (inst.channels[0] if inst.channels else "")
|
|
313
|
+
output_dir_full = output_dir
|
|
314
|
+
if base_dir:
|
|
315
|
+
output_dir_full = os.path.join(base_dir, output_dir)
|
|
316
|
+
os.makedirs(output_dir_full, exist_ok=True)
|
|
317
|
+
|
|
318
|
+
# Load configuration for this step
|
|
319
|
+
config = get_configuration_for_instrument(instrument)
|
|
320
|
+
step_config = config.get(step_name, {})
|
|
321
|
+
step_config["plot"] = plot
|
|
322
|
+
|
|
323
|
+
# Get the step class
|
|
324
|
+
step_classes = {
|
|
325
|
+
"bias": reduce_module.Bias,
|
|
326
|
+
"flat": reduce_module.Flat,
|
|
327
|
+
"trace": reduce_module.OrderTracing,
|
|
328
|
+
"curvature": reduce_module.SlitCurvatureDetermination,
|
|
329
|
+
"scatter": reduce_module.BackgroundScatter,
|
|
330
|
+
"norm_flat": reduce_module.NormalizeFlatField,
|
|
331
|
+
"wavecal_master": reduce_module.WavelengthCalibrationMaster,
|
|
332
|
+
"wavecal_init": reduce_module.WavelengthCalibrationInitialize,
|
|
333
|
+
"wavecal": reduce_module.WavelengthCalibrationFinalize,
|
|
334
|
+
"freq_comb_master": reduce_module.LaserFrequencyCombMaster,
|
|
335
|
+
"freq_comb": reduce_module.LaserFrequencyCombFinalize,
|
|
336
|
+
"science": reduce_module.ScienceExtraction,
|
|
337
|
+
"continuum": reduce_module.ContinuumNormalization,
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if step_name not in step_classes:
|
|
341
|
+
raise click.ClickException(
|
|
342
|
+
f"Step '{step_name}' does not support --file option"
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
step_class = step_classes[step_name]
|
|
346
|
+
step = step_class(
|
|
347
|
+
inst,
|
|
348
|
+
channel,
|
|
349
|
+
target=target or "",
|
|
350
|
+
night=night,
|
|
351
|
+
output_dir=output_dir_full,
|
|
352
|
+
order_range=None,
|
|
353
|
+
**step_config,
|
|
354
|
+
)
|
|
355
|
+
step.run(files=np.array([file]), mask=None, bias=None)
|
|
356
|
+
else:
|
|
357
|
+
config = get_configuration_for_instrument(instrument)
|
|
358
|
+
reduce_main(
|
|
359
|
+
instrument=instrument,
|
|
360
|
+
target=target,
|
|
361
|
+
night=night,
|
|
362
|
+
channels=channel,
|
|
363
|
+
steps=(step_name,),
|
|
364
|
+
base_dir=base_dir or "",
|
|
365
|
+
input_dir=input_dir,
|
|
366
|
+
output_dir=output_dir,
|
|
367
|
+
configuration=config,
|
|
368
|
+
plot=plot,
|
|
369
|
+
)
|
|
306
370
|
|
|
307
371
|
cmd.__doc__ = f"Run the '{step_name}' step."
|
|
308
372
|
return cmd
|
pyreduce/cli.py
CHANGED
|
@@ -287,7 +287,7 @@ def run(config_file: str, steps: str, skip_existing: bool, plot: int):
|
|
|
287
287
|
pipe = pipe.flat(_expand_globs(files["flat"]))
|
|
288
288
|
|
|
289
289
|
if "trace" in config_steps:
|
|
290
|
-
trace_files = files.get("
|
|
290
|
+
trace_files = files.get("trace") or files.get("flat")
|
|
291
291
|
pipe = pipe.trace_orders(_expand_globs(trace_files) if trace_files else None)
|
|
292
292
|
|
|
293
293
|
if "scatter" in config_steps:
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
pyreduce/combine_frames.py
CHANGED
|
@@ -146,7 +146,7 @@ def fix_bad_pixels(probability, buffer, readnoise, gain, threshold):
|
|
|
146
146
|
|
|
147
147
|
|
|
148
148
|
def combine_frames_simple(
|
|
149
|
-
files, instrument,
|
|
149
|
+
files, instrument, channel, extension=None, dtype=np.float32, **kwargs
|
|
150
150
|
):
|
|
151
151
|
"""
|
|
152
152
|
Simple addition of similar images.
|
|
@@ -157,8 +157,8 @@ def combine_frames_simple(
|
|
|
157
157
|
list of fits files to combine
|
|
158
158
|
instrument : str
|
|
159
159
|
instrument id for modinfo
|
|
160
|
-
|
|
161
|
-
instrument
|
|
160
|
+
channel : str
|
|
161
|
+
instrument channel
|
|
162
162
|
extension : int, optional
|
|
163
163
|
fits extension to load (default: 1)
|
|
164
164
|
dtype : np.dtype, optional
|
|
@@ -175,13 +175,13 @@ def combine_frames_simple(
|
|
|
175
175
|
|
|
176
176
|
# Load the first file to get the shape and header
|
|
177
177
|
result, head = instrument.load_fits(
|
|
178
|
-
files[0],
|
|
178
|
+
files[0], channel, dtype=dtype, extension=extension, **kwargs
|
|
179
179
|
)
|
|
180
180
|
|
|
181
181
|
# Sum the remaining files
|
|
182
182
|
for fname in files[1:]:
|
|
183
183
|
data, _ = instrument.load_fits(
|
|
184
|
-
fname,
|
|
184
|
+
fname, channel, dtype=dtype, extension=extension, **kwargs
|
|
185
185
|
)
|
|
186
186
|
result += data
|
|
187
187
|
|
|
@@ -208,7 +208,7 @@ def combine_frames_simple(
|
|
|
208
208
|
def combine_frames(
|
|
209
209
|
files,
|
|
210
210
|
instrument,
|
|
211
|
-
|
|
211
|
+
channel,
|
|
212
212
|
extension=None,
|
|
213
213
|
threshold=3.5,
|
|
214
214
|
window=50,
|
|
@@ -276,8 +276,8 @@ def combine_frames(
|
|
|
276
276
|
list of fits files to combine
|
|
277
277
|
instrument : str
|
|
278
278
|
instrument id for arminfo
|
|
279
|
-
|
|
280
|
-
instrument
|
|
279
|
+
channel : str
|
|
280
|
+
instrument channel
|
|
281
281
|
extension : int, optional
|
|
282
282
|
fits extension to load (default: 1)
|
|
283
283
|
threshold : float, optional
|
|
@@ -305,6 +305,14 @@ def combine_frames(
|
|
|
305
305
|
if instrument is None or isinstance(instrument, str):
|
|
306
306
|
instrument = load_instrument(instrument)
|
|
307
307
|
|
|
308
|
+
# For multi-amplifier instruments, use simple combination since the
|
|
309
|
+
# row-by-row approach doesn't work with multi-extension assembly
|
|
310
|
+
if instrument.config.amplifiers is not None:
|
|
311
|
+
logger.debug("Multi-amplifier instrument detected, using simple combination")
|
|
312
|
+
return combine_frames_simple(
|
|
313
|
+
files, instrument, channel, extension=extension, dtype=dtype, **kwargs
|
|
314
|
+
)
|
|
315
|
+
|
|
308
316
|
# summarize file info
|
|
309
317
|
logger.debug("Files:")
|
|
310
318
|
for i, fname in zip(range(len(files)), files, strict=False):
|
|
@@ -315,7 +323,7 @@ def combine_frames(
|
|
|
315
323
|
raise ValueError("No files given for combine frames")
|
|
316
324
|
elif len(files) == 1:
|
|
317
325
|
result, head = instrument.load_fits(
|
|
318
|
-
files[0],
|
|
326
|
+
files[0], channel, dtype=dtype, extension=extension, **kwargs
|
|
319
327
|
)
|
|
320
328
|
readnoise = np.atleast_1d(head.get("e_readn", 0))
|
|
321
329
|
total_exposure_time = head.get("exptime", 0)
|
|
@@ -325,12 +333,12 @@ def combine_frames(
|
|
|
325
333
|
# Two images
|
|
326
334
|
elif len(files) == 2:
|
|
327
335
|
bias1, head1 = instrument.load_fits(
|
|
328
|
-
files[0],
|
|
336
|
+
files[0], channel, dtype=dtype, extension=extension, **kwargs
|
|
329
337
|
)
|
|
330
338
|
exp1 = head1.get("exptime", 0)
|
|
331
339
|
|
|
332
340
|
bias2, head2 = instrument.load_fits(
|
|
333
|
-
files[1],
|
|
341
|
+
files[1], channel, dtype=dtype, extension=extension, **kwargs
|
|
334
342
|
)
|
|
335
343
|
exp2 = head2.get("exptime", 0)
|
|
336
344
|
readnoise = head2.get("e_readn", 0)
|
|
@@ -349,7 +357,7 @@ def combine_frames(
|
|
|
349
357
|
|
|
350
358
|
heads = [
|
|
351
359
|
instrument.load_fits(
|
|
352
|
-
f,
|
|
360
|
+
f, channel, header_only=True, dtype=dtype, extension=extension, **kwargs
|
|
353
361
|
)
|
|
354
362
|
for f in files
|
|
355
363
|
]
|
|
@@ -398,7 +406,7 @@ def combine_frames(
|
|
|
398
406
|
# Load all image hdus, but leave the data on the disk, using memmap
|
|
399
407
|
# Need to scale data later
|
|
400
408
|
if extension is None:
|
|
401
|
-
extension = [instrument.get_extension(h,
|
|
409
|
+
extension = [instrument.get_extension(h, channel) for h in heads]
|
|
402
410
|
else:
|
|
403
411
|
extension = [extension] * len(heads)
|
|
404
412
|
|
|
@@ -524,7 +532,7 @@ def combine_frames(
|
|
|
524
532
|
def combine_calibrate(
|
|
525
533
|
files,
|
|
526
534
|
instrument,
|
|
527
|
-
|
|
535
|
+
channel,
|
|
528
536
|
mask=None,
|
|
529
537
|
bias=None,
|
|
530
538
|
bhead=None,
|
|
@@ -545,8 +553,8 @@ def combine_calibrate(
|
|
|
545
553
|
list of file names to load
|
|
546
554
|
instrument : Instrument
|
|
547
555
|
PyReduce instrument object with load_fits method
|
|
548
|
-
|
|
549
|
-
descriptor of the instrument
|
|
556
|
+
channel : str
|
|
557
|
+
descriptor of the instrument channel
|
|
550
558
|
mask : array
|
|
551
559
|
2D Bad Pixel Mask to apply to the master image
|
|
552
560
|
bias : tuple(bias, bhead), optional
|
|
@@ -575,7 +583,7 @@ def combine_calibrate(
|
|
|
575
583
|
Unrecognised bias_scaling option
|
|
576
584
|
"""
|
|
577
585
|
# Combine the images and try to remove bad pixels
|
|
578
|
-
orig, thead = combine_frames(files, instrument,
|
|
586
|
+
orig, thead = combine_frames(files, instrument, channel, mask=mask, **kwargs)
|
|
579
587
|
|
|
580
588
|
# Subtract bias
|
|
581
589
|
if bias is not None and bias_scaling is not None and bias_scaling != "none":
|
|
@@ -636,7 +644,7 @@ def combine_calibrate(
|
|
|
636
644
|
|
|
637
645
|
|
|
638
646
|
def combine_polynomial(
|
|
639
|
-
files, instrument,
|
|
647
|
+
files, instrument, channel, mask, degree=1, plot=False, plot_title=None
|
|
640
648
|
):
|
|
641
649
|
"""
|
|
642
650
|
Combine the input files by fitting a polynomial of the pixel value versus
|
|
@@ -648,8 +656,8 @@ def combine_polynomial(
|
|
|
648
656
|
list of file names
|
|
649
657
|
instrument : Instrument
|
|
650
658
|
PyReduce instrument object with load_fits method
|
|
651
|
-
|
|
652
|
-
|
|
659
|
+
channel : str
|
|
660
|
+
channel identifier for this instrument
|
|
653
661
|
mask : array
|
|
654
662
|
bad pixel mask to apply to the coefficients
|
|
655
663
|
degree : int, optional
|
|
@@ -666,7 +674,7 @@ def combine_polynomial(
|
|
|
666
674
|
bhead : Header
|
|
667
675
|
combined FITS header of the coefficients
|
|
668
676
|
"""
|
|
669
|
-
hdus = [instrument.load_fits(f,
|
|
677
|
+
hdus = [instrument.load_fits(f, channel) for f in tqdm(files)]
|
|
670
678
|
data = np.array([h[0] for h in hdus])
|
|
671
679
|
exptimes = np.array([h[1]["EXPTIME"] for h in hdus])
|
|
672
680
|
# Numpy polyfit can fit all polynomials at the same time
|
|
@@ -708,7 +716,7 @@ def combine_polynomial(
|
|
|
708
716
|
def combine_bias(
|
|
709
717
|
files,
|
|
710
718
|
instrument,
|
|
711
|
-
|
|
719
|
+
channel,
|
|
712
720
|
extension=None,
|
|
713
721
|
plot=False,
|
|
714
722
|
plot_title=None,
|
|
@@ -724,7 +732,7 @@ def combine_bias(
|
|
|
724
732
|
files : list(str)
|
|
725
733
|
bias files to combine
|
|
726
734
|
instrument : str
|
|
727
|
-
instrument
|
|
735
|
+
instrument channel for arminfo
|
|
728
736
|
extension : {int, str}, optional
|
|
729
737
|
fits extension to use (default: 1)
|
|
730
738
|
xr : 2-tuple(int), optional
|
|
@@ -756,10 +764,10 @@ def combine_bias(
|
|
|
756
764
|
n2 = len(list2)
|
|
757
765
|
|
|
758
766
|
# Separately images in two groups.
|
|
759
|
-
bias1, head1 = combine_frames(list1, instrument,
|
|
767
|
+
bias1, head1 = combine_frames(list1, instrument, channel, extension, **kwargs)
|
|
760
768
|
bias1 /= n1
|
|
761
769
|
|
|
762
|
-
bias2, head = combine_frames(list2, instrument,
|
|
770
|
+
bias2, head = combine_frames(list2, instrument, channel, extension, **kwargs)
|
|
763
771
|
bias2 /= n2
|
|
764
772
|
|
|
765
773
|
# Make sure we know the gain.
|
pyreduce/instruments/aj.yaml
CHANGED
pyreduce/instruments/andes.py
CHANGED
|
@@ -25,30 +25,30 @@ class ANDES(Instrument):
|
|
|
25
25
|
self.filters["decker"] = Filter(self.info["id_decker"])
|
|
26
26
|
self.shared += ["band", "decker"]
|
|
27
27
|
|
|
28
|
-
def add_header_info(self, header,
|
|
28
|
+
def add_header_info(self, header, channel, **kwargs):
|
|
29
29
|
"""read data from header and add it as REDUCE keyword back to the header"""
|
|
30
30
|
# "Normal" stuff is handled by the general version, specific changes to values happen here
|
|
31
31
|
# alternatively you can implement all of it here, whatever works
|
|
32
|
-
band, decker, detector = self.
|
|
32
|
+
band, decker, detector = self.parse_channel(channel)
|
|
33
33
|
header = super().add_header_info(header, band)
|
|
34
34
|
self.load_info()
|
|
35
35
|
|
|
36
36
|
return header
|
|
37
37
|
|
|
38
|
-
def
|
|
38
|
+
def get_supported_channels(self):
|
|
39
39
|
settings = self.info["settings"]
|
|
40
40
|
deckers = self.info["deckers"]
|
|
41
41
|
detectors = self.info["chips"]
|
|
42
|
-
|
|
42
|
+
channels = [
|
|
43
43
|
"_".join([s, d, c]) for s, d, c in product(settings, deckers, detectors)
|
|
44
44
|
]
|
|
45
|
-
return
|
|
45
|
+
return channels
|
|
46
46
|
|
|
47
|
-
def
|
|
47
|
+
def parse_channel(self, channel):
|
|
48
48
|
pattern = r"([A-Z]+)(_(Open|pos1|pos2))?_det(\d)"
|
|
49
|
-
match = re.match(pattern,
|
|
49
|
+
match = re.match(pattern, channel, flags=re.IGNORECASE)
|
|
50
50
|
if not match:
|
|
51
|
-
raise ValueError(f"Invalid
|
|
51
|
+
raise ValueError(f"Invalid channel format: {channel}")
|
|
52
52
|
band = match.group(1).upper()
|
|
53
53
|
if match.group(3) is not None:
|
|
54
54
|
decker = match.group(3).lower().capitalize()
|
|
@@ -57,9 +57,9 @@ class ANDES(Instrument):
|
|
|
57
57
|
detector = match.group(4)
|
|
58
58
|
return band, decker, detector
|
|
59
59
|
|
|
60
|
-
def get_expected_values(self, target, night,
|
|
60
|
+
def get_expected_values(self, target, night, channel):
|
|
61
61
|
expectations = super().get_expected_values(target, night)
|
|
62
|
-
band, decker, detector = self.
|
|
62
|
+
band, decker, detector = self.parse_channel(channel)
|
|
63
63
|
|
|
64
64
|
for key in expectations.keys():
|
|
65
65
|
if key == "bias":
|
|
@@ -69,28 +69,28 @@ class ANDES(Instrument):
|
|
|
69
69
|
|
|
70
70
|
return expectations
|
|
71
71
|
|
|
72
|
-
def get_extension(self, header,
|
|
73
|
-
band, decker, detector = self.
|
|
72
|
+
def get_extension(self, header, channel):
|
|
73
|
+
band, decker, detector = self.parse_channel(channel)
|
|
74
74
|
extension = int(detector)
|
|
75
75
|
return extension
|
|
76
76
|
|
|
77
|
-
def get_wavecal_filename(self, header,
|
|
77
|
+
def get_wavecal_filename(self, header, channel, **kwargs):
|
|
78
78
|
"""Get the filename of the wavelength calibration config file"""
|
|
79
79
|
cwd = os.path.dirname(__file__)
|
|
80
|
-
fname = f"{self.name}_{
|
|
80
|
+
fname = f"{self.name}_{channel}.npz"
|
|
81
81
|
fname = os.path.join(cwd, "..", "wavecal", fname)
|
|
82
82
|
return fname
|
|
83
83
|
|
|
84
|
-
def get_mask_filename(self,
|
|
84
|
+
def get_mask_filename(self, channel, **kwargs):
|
|
85
85
|
i = self.name.lower()
|
|
86
|
-
band, decker, detector = self.
|
|
86
|
+
band, decker, detector = self.parse_channel(channel)
|
|
87
87
|
|
|
88
88
|
fname = f"mask_{i}_det{detector}.fits.gz"
|
|
89
89
|
cwd = os.path.dirname(__file__)
|
|
90
90
|
fname = os.path.join(cwd, "..", "masks", fname)
|
|
91
91
|
return fname
|
|
92
92
|
|
|
93
|
-
def get_wavelength_range(self, header,
|
|
93
|
+
def get_wavelength_range(self, header, channel, **kwargs):
|
|
94
94
|
wmin = [header["ESO INS WLEN MIN%i" % i] for i in range(1, 11)]
|
|
95
95
|
wmax = [header["ESO INS WLEN MAX%i" % i] for i in range(1, 11)]
|
|
96
96
|
|
pyreduce/instruments/andes.yaml
CHANGED