예제 #1
0
파일: spacecraft.py 프로젝트: sot/hopper
def run_cmds(cmds, or_list_file=None, ofls_characteristics_file=None, initial_state=None):
    obsreqs = parse_cm.read_or_list(or_list_file) if or_list_file else None
    if ofls_characteristics_file:
        odb_si_align = parse_cm.read_characteristics(ofls_characteristics_file, item="ODB_SI_ALIGN")
        characteristics = {"odb_si_align": odb_si_align}
    else:
        characteristics = None

    sc = Spacecraft(cmds, obsreqs, characteristics, initial_state)
    sc.run()

    return sc
예제 #2
0
def get_ccd_temps(oflsdir, outdir='out',
                  json_obsids=sys.stdin,
                  model_spec=None, char_file=None, orlist=None,
                  verbose=1, **kwargs):
    """
    Using the cmds and cmd_states sybase databases, available telemetry, and
    the pitches determined from the planning products, calculate xija ACA model
    temperatures for the given week.

    :param oflsdir: products directory
    :param outdir: output directory for plots
    :param json_obsids: file-like object or string containing JSON of
                        starcheck Obsid objects
    :param model_spec: xija ACA model specification
    :param verbose: Verbosity (0=quiet, 1=normal, 2=debug)
    :returns: JSON dictionary of labeled dwell intervals with max temperatures
    """
    if not os.path.exists(outdir):
        os.mkdir(outdir)

    config_logging(outdir, verbose)

    # Store info relevant to processing for use in outputs
    proc = {'run_user': os.environ['USER'],
            'run_time': time.ctime(),
            'errors': []}
    logger.info('##############################'
                '#######################################')
    logger.info('# %s run at %s by %s'
                % (TASK_NAME, proc['run_time'], proc['run_user']))
    logger.info('# {} version = {}'.format(TASK_NAME, VERSION))
    logger.info('###############################'
                '######################################\n')

    # load more general starcheck characteristics to get red/yellow limits
    char = yaml.load(open(char_file))

    # save spec file in out directory
    shutil.copy(model_spec, outdir)

    # json_obsids can be either a string or a file-like object.  Try those options in order.
    try:
        sc_obsids = json.loads(json_obsids)
    except TypeError:
        sc_obsids = json.load(json_obsids)

    tnow = DateTime().secs

    # Get tstart, tstop, commands from backstop file in opt.oflsdir
    bs_cmds = get_bs_cmds(oflsdir)
    tstart = bs_cmds[0]['time']
    tstop = bs_cmds[-1]['time']
    proc['datestart'] = DateTime(tstart).date
    proc['datestop'] = DateTime(tstop).date

    # Get temperature telemetry for 30 days prior to min(tstart, NOW)
    tlm = get_telem_values(min(tstart, tnow),
                           ['aacccdpt', 'pitch'],
                           days=30)

    states = get_week_states(tstart, tstop, bs_cmds, tlm)
    # if the last obsid interval extends over the end of states
    # extend the state / predictions
    if ((states[-1]['obsid'] == sc_obsids[-1]['obsid'])
        & (sc_obsids[-1]['obs_tstop'] > states[-1]['tstop'])):
        tstop = sc_obsids[-1]['obs_tstop']
        states[-1]['tstop'] = sc_obsids[-1]['obs_tstop']
        states[-1]['datestop'] = DateTime(sc_obsids[-1]['obs_tstop']).date

    if tstart >  DateTime(MODEL_VALID_FROM).secs:
        times, ccd_temp = make_week_predict(model_spec, states, tstop)
    else:
        times, ccd_temp = mock_telem_predict(states)

    make_check_plots(outdir, states, times,
                     ccd_temp, tstart, tstop, char=char)
    intervals = get_obs_intervals(sc_obsids)
    obsreqs = None if orlist is None else {obs['obsid']: obs for obs in read_or_list(orlist)}
    obstemps = get_interval_data(intervals, times, ccd_temp, obsreqs)
    return json.dumps(obstemps, sort_keys=True, indent=4,
	                  cls=NumpyAwareJSONEncoder)
예제 #3
0
def make_pcad_attitude_check_report(backstop_file, or_list_file=None, mm_file=None,
                                    simtrans_file=None, simfocus_file=None,
                                    ofls_characteristics_file=None, out=None,
                                    dynamic_offsets_file=None,
                                    ):
    """
    Make a report for checking PCAD attitudes

    """
    all_ok = True
    lines = []  # output report lines

    mm = read_maneuver_summary(mm_file)
    q = [mm[0][key] for key in ['q1_0', 'q2_0', 'q3_0', 'q4_0']]
    bs = read_backstop(backstop_file)
    simfa_time, simfa = recent_sim_history(DateTime(bs[0]['date']).secs,
                                           simfocus_file)
    simpos_time, simpos = recent_sim_history(DateTime(bs[0]['date']).secs,
                                             simtrans_file)
    initial_state = {'q_att': q,
                     'simpos': simpos,
                     'simfa_pos': simfa}

    or_list = None if or_list_file is None else read_or_list(or_list_file)
    if or_list is None:
        lines.append('ERROR: No OR list provided, cannot check attitudes')
        all_ok = False

    # If dynamical offsets file is available then load was planned using
    # Matlab tools 2016_210 later, which implements the "Cycle 18 aimpoint
    # transition plan".  This code injects new OR list attributes for the
    # dynamical offset.
    if dynamic_offsets_file is not None and or_list is not None:
        # Existing OFLS characteristics file is not relevant for post 2016_210.
        # Products are planned using the Matlab tools SI align which matches the
        # baseline mission align matrix from pre-November 2015.
        ofls_characteristics_file = None

        lines.append('INFO: using dynamic offsets file {}'.format(dynamic_offsets_file))
        or_map = {or_['obsid']: or_ for or_ in or_list}

        doffs = Table.read(dynamic_offsets_file, format='ascii.basic', guess=False)
        for doff in doffs:
            obsid = doff['obsid']
            if obsid in or_map:
                or_map[obsid]['aca_offset_y'] = doff['aca_offset_y'] / 3600.
                or_map[obsid]['aca_offset_z'] = doff['aca_offset_z'] / 3600.

        # Check that obsids in dynamic offsets table are all in OR list
        if not set(doffs['obsid']).issubset(set(or_map)):
            all_ok = False
            obsid_mismatch = set(doffs['obsid']) - set(or_map)
            lines.append('WARNING: Obsid in dynamic offsets table but missing in OR list {}'
                         .format(list(obsid_mismatch)))

    # Run the commands and populate attributes in `sc`, the spacecraft state.
    # In particular sc.checks is a dict of checks by obsid.
    # Any state value (e.g. obsid or q_att) has a corresponding plural that
    # gives the history of updates as a dict with a `value` and `date` key.
    sc = hopper.run_cmds(backstop_file, or_list, ofls_characteristics_file,
                         initial_state=initial_state)
    # Iterate through obsids in order
    obsids = [obj['value'] for obj in sc.obsids]
    for obsid in obsids:
        if obsid not in sc.checks:
            continue

        checks = sc.checks[obsid]
        for check in checks:
            if check['name'] == 'CheckObsreqTargetFromPcad':
                ok = check['ok']
                all_ok &= ok
                if check.get('skip'):
                    message = 'SKIPPED: {}'.format(check['message'])
                else:
                    message = 'OK' if ok else check['message']
                line = '{:5d}: {}'.format(obsid, message)
                lines.append(line)

    if out is not None:
        with open(out, 'w') as fh:
            fh.writelines("\n".join(lines))

    return all_ok
예제 #4
0
def make_pcad_attitude_check_report(backstop_file, or_list_file=None, attitude_file=None,
                                    simtrans_file=None, simfocus_file=None,
                                    ofls_characteristics_file=None, out=None,
                                    dynamic_offsets_file=None,
                                    ):
    """
    Make a report for checking PCAD attitudes

    """
    all_ok = True
    lines = []  # output report lines

    bs = read_backstop(backstop_file)

    # Get initial state attitude and sim position from history
    att_time, q1, q2, q3, q4 = recent_attitude_history(DateTime(bs[0]['date']).secs,
                                            attitude_file)
    q = Quaternion.normalize([q1, q2, q3, q4])
    simfa_time, simfa = recent_sim_history(DateTime(bs[0]['date']).secs,
                                           simfocus_file)
    simpos_time, simpos = recent_sim_history(DateTime(bs[0]['date']).secs,
                                             simtrans_file)

    initial_state = {'q1': q[0],
                     'q2': q[1],
                     'q3': q[2],
                     'q4': q[3],
                     'simpos': simpos,
                     'simfa_pos': simfa}

    or_list = None if or_list_file is None else read_or_list(or_list_file)
    if or_list is None:
        lines.append('ERROR: No OR list provided, cannot check attitudes')
        all_ok = False

    # If dynamical offsets file is available then load was planned using
    # Matlab tools 2016_210 later, which implements the "Cycle 18 aimpoint
    # transition plan".  This code injects new OR list attributes for the
    # dynamical offset.
    if dynamic_offsets_file is not None and or_list is not None:
        # Existing OFLS characteristics file is not relevant for post 2016_210.
        # Products are planned using the Matlab tools SI align which matches the
        # baseline mission align matrix from pre-November 2015.
        ofls_characteristics_file = None

        lines.append('INFO: using dynamic offsets file {}'.format(dynamic_offsets_file))
        or_map = {or_['obsid']: or_ for or_ in or_list}

        doffs = Table.read(dynamic_offsets_file, format='ascii.basic', guess=False)
        for doff in doffs:
            obsid = doff['obsid']
            if obsid in or_map:
                or_map[obsid]['aca_offset_y'] = doff['aca_offset_y'] / 3600.
                or_map[obsid]['aca_offset_z'] = doff['aca_offset_z'] / 3600.

        # Check that obsids in dynamic offsets table are all in OR list
        if not set(doffs['obsid']).issubset(set(or_map)):
            all_ok = False
            obsid_mismatch = set(doffs['obsid']) - set(or_map)
            lines.append('WARNING: Obsid in dynamic offsets table but missing in OR list {}'
                         .format(list(obsid_mismatch)))

    # Run the commands and populate attributes in `sc`, the spacecraft state.
    # In particular sc.checks is a dict of checks by obsid.
    # Any state value (e.g. obsid or q_att) has a corresponding plural that
    # gives the history of updates as a dict with a `value` and `date` key.
    sc = hopper.run_cmds(backstop_file, or_list, ofls_characteristics_file,
                         initial_state=initial_state, starcheck=True)
    # Iterate through checks by obsid to print status
    checks = sc.get_checks_by_obsid()
    for obsid in sc.obsids:
        for check in checks[obsid]:
            if check.name == 'attitude_consistent_with_obsreq':
                ok = check.success
                all_ok &= ok
                if check.not_applicable:
                    message = 'SKIPPED: {}'.format(":".join(check.infos))
                else:
                    message = 'OK' if ok else "ERROR: {}".format(":".join(check.errors))
                    line = '{:5d}: {}'.format(obsid, message)
                lines.append(line)

    if out is not None:
        with open(out, 'w') as fh:
            fh.writelines("\n".join(lines))

    return all_ok