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 | class ScheduleFilesCheck(KPFFunction):
'''Check whether all expected schedule files are present and count the
number of lines in each file and see if it is larger than 1.
Args:
email (bool): Send an email if a problem is detected?
Functions Called:
- `kpf.observatoryAPIs.GetScheduledPrograms`
- `kpf.utils.SendEmail`
'''
@classmethod
def pre_condition(cls, args):
pass
@classmethod
def perform(cls, args):
errors = []
utnow = datetime.datetime.utcnow()
date_string = utnow.strftime('%Y-%m-%d')
log.info(f"# Checking for schedule for the night of {date_string} HST")
semester, s_start, s_end = get_semester_dates(utnow)
log.info(f'# KPF-CC Schedule File Check')
band_names = ['full-band1', 'full-band2', 'full-band3']
params = {'date': date_string, 'numdays': 1, 'telnr': 1, 'instrument': 'KPF'}
all_programs = query_observatoryAPI('schedule', 'getSchedule', params)
classical = [p for p in all_programs if p['Instrument'] == 'KPF']
cadence = [p for p in all_programs if p['Instrument'] == 'KPF-CC']
cadence_projects = [p['ProjCode'] for p in cadence]
if len(cadence_projects) > 0:
log.info(f"# Found cadence programs: {cadence_projects}")
band_names.extend(['band1', 'band2', 'band3'])
log.info(f"# Checking for {len(band_names)} schedules: {band_names}")
base_path = Path('/s/sdata1701/Schedules')
semester_path = base_path / semester
date_path = semester_path / date_string
if date_path.exists() is False:
err = f"{str(date_path)} does not exist"
errors.append(err)
log.error(err)
band_paths = [date_path / band for band in band_names]
line_counts = {}
for band_path in band_paths:
if band_path.exists() is False:
err = f"{str(band_path)} does not exist"
errors.append(err)
log.error(err)
output_path = band_path / 'output'
if output_path.exists() is False:
err = f"{str(output_path)} does not exist"
errors.append(err)
log.error(err)
output_file = output_path / 'night_plan.csv'
if output_file.exists() is False:
err = f"{str(output_file)} does not exist"
errors.append(err)
log.error(err)
try:
with open(output_file, 'r') as f:
lines = f.readlines()
nlines = len(lines)
line_counts[band_path.name] = nlines
if nlines <= 1:
err = f"{str(output_file)} has only {nlines} lines"
errors.append(err)
log.error(err)
except:
err = f'Failed to read {str(output_file)}'
errors.append(err)
log.error(err)
# Results
log.info(f'# {str(date_path)}')
result_str = 'Band Line Count'
log.info(f'# {result_str}')
result_str += '\n'
for band in sorted(line_counts.keys()):
newline = f'{band:11s} {line_counts[band]:d}'
if line_counts[band] <= 1:
newline += ' <-- Low target count!'
log.info(f'# {newline}')
result_str += f"{newline}\n"
# Send Email
if len(errors) > 0:
msg = 'KPF-CC Schedule May Be Bad\n\n'
if args.get('email', False) == True:
try:
to_value = cfg.get('operations', 'lead_sa', 'jwalawender')
SendEmail.execute({'Subject': f'KPF-CC Schedule May Be Bad',
'Message': msg+result_str,
'To': f'{to_value}@keck.hawaii.edu'})
except Exception as email_err:
log.error(f'Sending email failed')
log.error(email_err)
@classmethod
def post_condition(cls, args):
pass
@classmethod
def add_cmdline_args(cls, parser):
parser.add_argument('--email', dest="email",
default=False, action="store_true",
help='Send email if SoCal is not shut down?')
return super().add_cmdline_args(parser)
|