14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132 | class BuildCalOB(KPFFunction):
'''From a set of standard prescriptions, build the described calibration OB.
Given a list of input strings, parse them in to variations of the standard
calibrations and create an OB for them.
The input string format is `[CalSource],[Object],[nExp],[keywords]`. The
first 3 entries are required while the keywords section is optional. Any
unspecified values default to match the same CalSource entry in the example
OB file in this repo at `kpf/ObservingBlocks/exampleOBs/Calibration.yaml`.
For example, and input of `EtalonFiber,slewcal,5` will generate an OB which
takes 5 etalon frames with the object name of "slewcal". No keywords are
provided, so all other elements of the OB are the default values (e.g. the
exposure time and ND filters).
The keywords can be used to modify those default values in the OB. For
example, if the input is:
`[CalSource],[Object],[nExp],[keywords],IntensityMonitor=True`
then the resulting OB will have the `IntensityMonitor` value set to True
rather than the default of False and
`[CalSource],[Object],[nExp],[keywords],ExpTime=30`
will result in an OB with 30 second exposure times instead of the default
of 40 seconds.
Multiple inputs can be given to create multi-calibration OBs, either as a
list in python or on the command line. For example:
`kpfdo BuildCalOB Dark,autocal-dark,1,ExpTime=1200 EtalonFiber,autocal-etalon-all-midday,3,IntensityMonitor=True BrdbandFiber,autocal-flat-all,95,IntensityMonitor=True`
will generate an OB with three calibrations: a 1200 second dark, 3 Etalon
frames, and 95 flat field frames.
Args:
calinputs (list of strings): Input strings as described above.
estimate (bool): Generate the OB, run the `EstimateOBDuration` tool,
and print the results to screen.
save (string): Save resulting OB to the specified file.
overwrite (bool): Overwrite output file if it exists?
execute (bool): Execute the resulting OB?
Functions Called:
- `EstimateOBDuration`
- `RunOB`
'''
@classmethod
def pre_condition(cls, args):
pass
@classmethod
def perform(cls, args):
# Build dict of example calibrations
example_cal_file = Path(__file__).parent.parent / 'ObservingBlocks' / 'exampleOBs' / 'Calibrations.yaml'
if example_cal_file.exists() != True:
print(f'Failed to open {example_cal_file:s}')
return
example_OB = ObservingBlock(example_cal_file)
example_cals = {}
for cal in example_OB.Calibrations:
if cal.CalSource not in example_cals.keys():
example_cals[str(cal.CalSource)] = cal
# Build fresh OB
OB = ObservingBlock({})
for calinput in args.get('calinputs'):
calspec = calinput.split(',')
# [CalSource],[Object],[nExp],**kwargs
example = example_cals.get(calspec[0], None)
if example is None:
print(f'Unable to find example calibrations for {calspec[0]}')
else:
cal = copy.deepcopy(example)
cal.set('Object', calspec[1])
cal.set('nExp', int(calspec[2]))
if len(calspec) > 3:
kwargs = calspec[3:]
for kwarg in kwargs:
key,value = kwarg.split('=')
if key in ['Exptime']:
cal.set(key, float(value))
elif key in ['TriggerCaHK', 'TriggerGreen', 'TriggerRed',
'IntensityMonitor', 'OpenScienceShutter',
'OpenSkyShutter', 'TakeSimulCal']:
cal.set(key, bool(value))
else:
cal.set(key, value)
OB.Calibrations.append(cal)
if args.get('save', '') not in ['', None]:
OB.write_to(args.get('save'), overwrite=args.get('overwrite', False))
if args.get('estimate', False) or args.get('execute', False):
cal_strings = [str(cal) for cal in OB.Calibrations]
cal_string = ','.join(cal_strings)
print(f"# {cal_string}")
duration = EstimateOBDuration.execute({'verbose': True}, OB=OB)
if args.get('execute', False):
RunOB.execute({}, OB=OB)
return OB
@classmethod
def post_condition(cls, args):
pass
@classmethod
def add_cmdline_args(cls, parser):
parser.add_argument('calinputs', nargs='*',
help="Calibrations to take in the form ")
parser.add_argument("-v", "-t", "--time", "--estimate", dest="estimate",
default=False, action="store_true",
help="Estimate the execution time for this OB?")
parser.add_argument("-s", "--save", dest="save", type=str, default='',
help="Save resulting OB to the specified file.")
parser.add_argument("-o", "--overwrite", dest="overwrite",
default=False, action="store_true",
help="Overwrite output file if it exists?")
parser.add_argument("--execute", dest="execute",
default=False, action="store_true",
help="Execute the resulting OB?")
return super().add_cmdline_args(parser)
|