ScheduleFilesCheck

Bases: 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.

Parameters:
  • email (bool) –

    Send an email if a problem is detected?

Functions Called:

  • kpf.observatoryAPIs.GetScheduledPrograms
  • kpf.utils.SendEmail
Source code in kpf/utils/ScheduleFilesCheck.py
 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)