Example #1
0
def compare_obc_and_asol(atts, times, recs, ptol=2, ytol=2, rtol=50):
    """
    Check that obc solution and ground solution have relatively close quats.
    Note that because the ground aspect solution is not continuous (only run over science obsids
    in aspect intervals) that this method only checks those intervals.

    :param atts: attitudes from get_atts
    :param times: times from get_atts
    :param recs: list of dicts of header records from get_atts
    :param ptol: dq quaternion pitch tolerance in arcsecs
    :param ytol: dq quaternion yaw tolerance in arcsecs
    :param rtol: dq quaternion roll tolerance in arcsecs
    """
    for ai in recs:
        telem = fetch.Msidset(['aoattqt*'], ai['TSTART'], ai['TSTOP'])
        obc_atts = np.vstack([telem['aoattqt{}'.format(idx)].vals
                          for idx in [1, 2, 3, 4]]).transpose()
        obc_times = telem['aoattqt1'].times
        # Test that, at the obc times, the onboard solution and the ground solution
        # are reasonably close
        idxs = np.searchsorted(times[:-1], obc_times)
        dps = []
        dys = []
        drs = []
        for att, obc_att in zip(atts[idxs], obc_atts):
            dq = Quat(normalize(att)).dq(Quat(normalize(obc_att)))
            dps.append(dq.pitch * 3600)
            dys.append(dq.yaw * 3600)
            drs.append(dq.roll0 * 3600)
        dps = np.array(dps)
        dys = np.array(dys)
        drs = np.array(drs)
        assert np.all(np.abs(dys) < ytol)
        assert np.all(np.abs(dps) < ptol)
        assert np.all(np.abs(drs) < rtol)
def computeIMUMultiple(imuData):

    utmLoc = np.zeros((len(imuData['x134_Position']), 2))

    for i in range(len(imuData['x134_Position'])):
        u = utm.from_latlon(imuData['x134_Position'][i, 0],
                            imuData['x134_Position'][i, 1])
        utmLoc[i, 0] = u[0]
        utmLoc[i, 1] = u[1]

    qNorm = normalize(imuData['x131_Quaternion'][0, :])
    eulerAngles = np.zeros((len(imuData['x131_Quaternion']), 3))

    for i in range(len(imuData['x131_Quaternion'])):
        qNorm = normalize(imuData['x131_Quaternion'][i, :])
        Q = Quat(qNorm)
        eulerAngles[i, :] = [Q.ra, Q.dec, Q.roll]

    relPath = utmLoc - utmLoc[0, :]
    rotAngle = (180 - eulerAngles[0, 2]) * np.pi / 180.
    R2 = np.array([[cos(rotAngle), -1 * sin(rotAngle)],
                   [sin(rotAngle), cos(rotAngle)]])
    pathR = np.dot(R2, relPath.T)

    # else:
    #     utmLoc = np.full((5,2),np.NaN)
    #     eulerAngles = np.full((5,3),np.NaN)
    #     pathR = np.full((2,5),np.NaN)
    #     velocity = np.full((5,3),np.NaN)
    #     time = np.full((5,8),np.NaN)

    return utmLoc, eulerAngles, pathR
Example #3
0
def compare_obc_and_asol(atts, times, recs, ptol=2, ytol=2, rtol=65):
    """
    Check that obc solution and ground solution have relatively close quats.
    Note that because the ground aspect solution is not continuous (only run over science obsids
    in aspect intervals) that this method only checks those intervals.

    :param atts: attitudes from get_atts
    :param times: times from get_atts
    :param recs: list of dicts of header records from get_atts
    :param ptol: dq quaternion pitch tolerance in arcsecs
    :param ytol: dq quaternion yaw tolerance in arcsecs
    :param rtol: dq quaternion roll tolerance in arcsecs
    """
    for ai in recs:
        telem = fetch.Msidset(['aoattqt*'], ai['TSTART'], ai['TSTOP'])
        obc_atts = np.vstack([telem['aoattqt{}'.format(idx)].vals
                          for idx in [1, 2, 3, 4]]).transpose()
        obc_times = telem['aoattqt1'].times
        # Test that, at the obc times, the onboard solution and the ground solution
        # are reasonably close
        idxs = np.searchsorted(times[:-1], obc_times)
        dps = []
        dys = []
        drs = []
        for att, obc_att in zip(atts[idxs], obc_atts):
            dq = Quat(normalize(att)).dq(Quat(normalize(obc_att)))
            dps.append(dq.pitch * 3600)
            dys.append(dq.yaw * 3600)
            drs.append(dq.roll0 * 3600)
        dps = np.array(dps)
        dys = np.array(dys)
        drs = np.array(drs)
        assert np.all(np.abs(dys) < ytol)
        assert np.all(np.abs(dps) < ptol)
        assert np.all(np.abs(drs) < rtol)
Example #4
0
def ground_truth(model_ply, scene_ply, gt_pos):
    pos_i = gt_pos[os.path.basename(model_ply)]
    pos_j = gt_pos[os.path.basename(scene_ply)]
    q_i = Quat(normalize(numpy.array(pos_i[3::])))
    q_j = Quat(normalize(numpy.array(pos_j[3::])))
    q_ji = q_i / q_j
    q_ij = q_j / q_i
    return q_ij, q_ji
Example #5
0
def lookup_ground_truth(i, j):
    model_ply = PLY_FILES[i]
    scene_ply = PLY_FILES[j]
    pos_i = GT_POS[os.path.basename(model_ply)]
    pos_j = GT_POS[os.path.basename(scene_ply)]
    q_i = Quat(normalize(np.array(pos_i[3::])))
    q_j = Quat(normalize(np.array(pos_j[3::])))
    q_ji = q_i / q_j
    q_ij = q_j / q_i
    return q_ij, q_ji
def find_orient(theta,A,q1):
    
    qw= cos(radians(theta)/2.0)
    qi=A[0]*sin(radians(theta)/2.0)
    qj=A[1]*sin(radians(theta)/2.0)
    qk=A[2]*sin(radians(theta)/2.0)
    
    q=normalize([qw,qi,qj,qk])
    qInv=normalize(QuatInv(q))
    q2=QuatMult(q1,qInv)
    
    return q2   
Example #7
0
def compare_rotation(ply_files, reg_result, gt_pos):
    res = {}
    for i, j in reg_result:
        model_ply = ply_files[i]
        scene_ply = ply_files[j]
        q_ij, q_ji = ground_truth(model_ply, scene_ply, gt_pos)
        param = reg_result[(i,j)][0]
        q = Quat(normalize(param[0:4]))
        res[(i, j)] = abs(numpy.dot(q.q, q_ji.q))
    return res
Example #8
0
def get_cmd_quat(date):
    date = DateTime(date)
    cmd_quats = fetch.MSIDset(['AOCMDQT{}'.format(i) for i in [1, 2, 3]],
                              date.secs, date.secs + 120)
    cmd_q4 = np.sqrt(np.abs(1 - cmd_quats['AOCMDQT1'].vals[0]**2
                            - cmd_quats['AOCMDQT2'].vals[0]**2
                            - cmd_quats['AOCMDQT3'].vals[0]**2))
    return Quat(normalize([cmd_quats['AOCMDQT1'].vals[0],
                           cmd_quats['AOCMDQT2'].vals[0],
                           cmd_quats['AOCMDQT3'].vals[0],
                           cmd_q4]))
Example #9
0
def stars_test(dwells, dur_thres=7000):
    """
    Check that the appropriate stars are identified in agasc.
    For a given obsid, star id's and mags can be compared with those in starcheck.

    Example:
    =======

    >> from monwin import stars_test, get_dwells
    >> from parce_cm import read_dot_as_list
    >> dot = read_dot_as_list("/data/mpcrit1/mplogs/2017/JAN0917/scheduled_b/md007_2305.dot")
    >> dwells = get_dwells(dot)
    >> stars_test(dwells)
    Obsid = 0, duration = 0 sec, skipped
    Obsid = 50411, duration = 3258 sec, skipped
    Obsid = 50410, duration = 3270 sec, skipped
    Obsid = 50409, duration = 3248 sec, skipped
    Obsid = 50408, duration = 1242 sec, skipped
    Obsid = 50407, duration = 3243 sec, skipped
    Obsid = 50406, duration = 11594 sec
     agasc_id  color     mag  
    --------- -------- -------
    389949248  0.95285 7.53174
    389953880  0.12495 7.79542
    389954848 0.113901 8.71616
    389954920  0.54995 9.34569
    390865160   1.0302 8.71366
    390867952      1.5 8.68183
    390339464  0.48875 9.34993
    391254944   0.2176 7.91407
    Obsid = 18048, duration = 71020 sec, skipped
    ...
    ...
    ...
    """

    for dwell in dwells:
        obsid = dwell['obsid']
        duration = dwell['duration']
        if obsid < 60000 and obsid > 50000 and duration > dur_thres:
            strcat = dwell['strcat']
            q1 = dwell['q1']
            q2 = dwell['q2']
            q3 = dwell['q3']
            q4 = np.sqrt(1. - q1**2 - q2**2 - q3**2)
            quat = Quat(normalize([q1, q2, q3, q4]))
            stars = identify_stars(obsid, strcat, quat)
            print('Obsid = {}, duration = {:.0f} sec'.format(obsid, duration))
            print(Table(stars))
        else:
            print('Obsid = {}, duration = {:.0f} sec, skipped'.format(
                obsid, duration))

    return
def computeIMU(imuData):

    utmLoc = np.zeros(2)
    u = utm.from_latlon(imuData['x134_Position'][0],
                        imuData['x134_Position'][1])
    utmLoc[0] = u[0]
    utmLoc[1] = u[1]
    eulerAngles = np.zeros(3)
    qNorm = normalize(imuData['x131_Quaternion'][:])
    Q = Quat(qNorm)
    eulerAngles[:] = [Q.ra, Q.dec, Q.roll]
    return utmLoc, eulerAngles
Example #11
0
def compute_accuracy(reg_result):
    error = {}  # error in degrees.
    total_run_time = {}
    core_run_time = {}
    for i, j in reg_result:
        q_ij, q_ji = lookup_ground_truth(i, j)
        param = reg_result[(i, j)][0]
        q = Quat(normalize(param[0:4]))
        similarity = np.abs(np.dot(q.q, q_ji.q))
        error[(i, j)] = 2 * np.arccos(similarity) * 180 / np.pi
        total_run_time[(i, j)] = reg_result[(i, j)][-1]
        core_run_time[(i, j)] = reg_result[(i, j)][-2]
    return error, total_run_time, core_run_time
def normalise_quaternions(quat_dict):
    norm_quat_dict = OrderedDict()

    for k, v in quat_dict.items():
        if v.shape[1] == 4:
            norm_quats = []
            for r in v:
                q = np.array([r[1], r[2], r[3], r[0]])  # [x, y, z, w]
                nq = Quat(normalize(q))
                nq_v = nq._get_q()
                norm_quats.append([nq_v[3], nq_v[0], nq_v[1],
                                   nq_v[2]])  # [w, x, y, z]
            norm_quat_dict[k] = np.array(norm_quats)
        else:
            norm_quat_dict[k] = v

    return norm_quat_dict
Example #13
0
def get_trak_cat_from_telem(start, stop, cmd_quat):
    start = DateTime(start)
    stop = DateTime(stop)
    msids = ["{}{}".format(m, i) for m in ['AOACYAN', 'AOACZAN', 'AOACFID', 'AOIMAGE', 'AOACFCT']
             for i in range(0, 8)]
    telem = fetch.MSIDset(['AOACASEQ', 'CORADMEN', 'AOPCADMD', 'AONSTARS', 'AOKALSTR']
                          + msids, start, stop)
    att = fetch.MSIDset(['AOATTQT{}'.format(i) for i in [1, 2, 3, 4]], start, stop)
    cat = {}
    for slot in range(0, 8):
        track = telem['AOACFCT{}'.format(slot)].vals == 'TRAK'
        fid = telem['AOACFID{}'.format(slot)].vals == 'FID '
        star = telem['AOIMAGE{}'.format(slot)].vals == 'STAR'
        n = 30
        if np.count_nonzero(track) < n:
            continue
        if np.any(fid & track):
            cat[slot] = {'type': 'FID',
                         'yag': telem['AOACYAN{}'.format(slot)].vals[fid & track][0],
                         'zag': telem['AOACZAN{}'.format(slot)].vals[fid & track][0]}
        else:
            n_samples = np.count_nonzero(track & star)
            if n_samples < (n + 4):
                continue
            # If there is tracked data with a star, let's try to get our n samples from about
            # the middle of the range
            mid_point = int(n_samples / 2.)
            yags = []
            zags = []
            for sample in range(mid_point - int(n / 2.), mid_point + int(n / 2.)):
                qref = Quat(normalize([att['AOATTQT{}'.format(i)].vals[track & star][sample]
                                       for i in [1, 2, 3, 4]]))
                ra, dec = yagzag2radec(
                    telem['AOACYAN{}'.format(slot)].vals[track & star][sample] / 3600.,
                    telem['AOACZAN{}'.format(slot)].vals[track & star][sample] / 3600.,
                    qref)
                yag, zag = radec2yagzag(ra, dec, cmd_quat)
                yags.append(yag)
                zags.append(zag)
            # This doesn't detect MON just yet
            cat[slot] = {'type': 'STAR',
                         'yag': np.median(yags) * 3600.,
                         'zag': np.median(zags) * 3600.}
    return cat, telem
Example #14
0
def plot_centroid_resids_by_flag(start, stop, slot, plot=False):
    """
    Plot centroid residuals for a start/stop interval with color
    coding to indicate readouts corresponding to a particular
    combination of DP, IR, MS, and SP.  The specified interval
    must be a stable Kalman dwell at one attitude.

    :param start: start time (any Chandra DateTime format)
    :param stop: stop time
    :param slot: ACA image slot
    :param save: save images as png files
    """

    pcad_msids = ['aoacfct',
                  'aoacisp',
                  'aoacidp',
                  'aoaciir',
                  'aoacims',
                  'aoacyan',
                  'aoaczan']
    slot_msids = [msid + "%s" % slot for msid in pcad_msids]

    msids = ['aoattqt1',
             'aoattqt2',
             'aoattqt3',
             'aoattqt4',
             ]

    msids.extend(slot_msids)

    print('Fetching telemetry from {} to {}'.format(start, stop))
    telems = fetch.MSIDset(msids, start, stop)
    telems.interpolate(dt=2.05, filter_bad=False)

    bads = np.zeros(len(telems.times), dtype=bool)
    for msid in telems:
        bads |= telems[msid].bads
    bads |= telems['aoacfct{}'.format(slot)].vals != 'TRAK'

    telems.bads = bads
    for msid in telems:
        telems[msid].bads = bads
    telems.filter_bad()

    vals = ([telems['aoattqt%d' % i].vals for i in range(1, 5)]
            + [telems['aoacyan{}'.format(slot)].vals / 3600.,
               telems['aoaczan{}'.format(slot)].vals / 3600.])

    print('Interpolating quaternions')
    radecs = [yagzag2radec(yag, zag, Quat(normalize([q1, q2, q3, q4])))
              for q1, q2, q3, q4, yag, zag in zip(*vals)]
    coords = np.rec.fromrecords(radecs, names=('ra', 'dec'))

    # ok = telems['aoacfct{}'.format(slot)].vals == 'TRAK'

    flags = {'dp': telems['aoacidp%s' % slot].vals != 'OK ',
             'ir': telems['aoaciir%s' % slot].vals != 'OK ',
             'ms': telems['aoacims%s' % slot].vals != 'OK ',
             'sp': telems['aoacisp%s' % slot].vals != 'OK ',
             }

    times = telems['aoacyan%s' % slot].times
    dra = (coords['ra'] - np.mean(coords['ra'])) * 3600 * np.cos(np.radians(coords['dec']))
    ddec = (coords['dec'] - np.mean(coords['dec'])) * 3600
    dr = np.sqrt(dra ** 2 + ddec ** 2)

    # fileroot = 'flags_{}'.format(DateTime(start).date[:14]) if save else None

    # print('Making plots with output fileroot={}'.format(fileroot))

    filt = ((flags['dp'] == False) & (flags['ir'] == False)
            & (flags['ms'] == False) & (flags['sp'] == False))
    if plot:
        plot_axis('dR', times, dr, filt, title='No status flags')
    if np.sum(filt) > 20:
        clean_perc = np.percentile(dr[filt], [50, 84, 90, 95])
        if clean_perc[2] > 1.0:
            print '{} {} : {}'.format(start, stop, str(clean_perc))
    else:
        clean_perc = [-1, -1, -1, -1]
    clean_perc.append(np.sum(filt))

    filt = flags['dp'] == True
    if plot:
        plot_axis('dR', times, dr, filt, title='DP == True')
    if np.sum(filt) > 20:
        dp_perc = np.percentile(dr[filt], [50, 84, 90, 95])
    else:
        dp_perc = [-1, -1, -1, -1]
    dp_perc.append(np.sum(filt))

    return clean_perc, dp_perc
Example #15
0
def monitor_window_stats(dwells, dur_thres=7000, t_ccd=-11, prob_thres=0.1):
    """
    Get number of allowed monitor windows for each ER dwell with
    duration longer than dur_thres in sec.

    :dwells: list of dictionaries with dwells parsed from the DOT
    :dur_thres: duration threshold in sec for an ER dwell
    :t_ccd: temperature of the CCD in C
    :prob_thres: acquisition probability threshold to detect exactly n stars
                 (n=6 for 1 monitor window, n=7 for 2 monitor windows)
    :returns: list of dictionaries with dwell obsid and duration info
              and star acquisition and monitor window stats.
              This could be simplified so that only the numer of allowed
              monitor windows is returned. Current output is for testing
              purposes.
    """
    stats = []

    for dwell in dwells:
        obsid = dwell['obsid']
        if obsid < 60000 and obsid > 50000 and dwell['duration'] > dur_thres:
            q1 = dwell['q1']
            q2 = dwell['q2']
            q3 = dwell['q3']
            q4 = np.sqrt(1. - q1**2 - q2**2 - q3**2)
            quat = Quat(normalize([q1, q2, q3, q4]))
            strcat = dwell['strcat']
            date = strcat['TIME']
            duration = dwell['duration']

            stars = identify_stars(obsid, strcat, quat)

            t = Table(stars)
            t['probs'] = star_probs.acq_success_prob(date, t_ccd, t['mag'],
                                                     t['color'])
            t.sort('probs')

            dwell_stats = {
                'obsid': obsid,
                'duration': duration,
                'date': date,
                'quat': quat,
                'mon_windows_1': False,
                'mon_windows_2': False,
                'num_mon_windows': 0,
                'stars_dropped_1': [],
                'stars_dropped_2': []
            }

            for i in [6, 7]:
                p, c = star_probs.prob_n_acq(t['probs'][:i])
                if p[-1] > prob_thres:
                    num_mon_windows = 8 - i
                    dwell_stats['mon_windows_{}'.format(
                        num_mon_windows)] = True
                    if num_mon_windows > dwell_stats['num_mon_windows']:
                        dwell_stats['num_mon_windows'] = num_mon_windows
                    if num_mon_windows > 0:
                        # improve this: star probs could be equal to each other,
                        # and then it doesnt matter which star is dropped
                        stars_dropped = [
                            id for id in t['agasc_id'][-num_mon_windows:]
                        ]
                        dwell_stats['stars_dropped_{}'.format(
                            num_mon_windows)] = stars_dropped

                dwell_stats['prob_{}'.format(i)] = format(p[-1], '.3f')

            stats.append(dwell_stats)

    return stats