def test_get_aca_offsets(): """ Test that ACA offsets are reasonable, and regression test particular values corresponding to cycle 17 zero-offset aimpoints used below for chip_x, chip_y inputs. The output reference values here have been validated as being "reasonable" for the given inputs. """ offsets = drift.get_aca_offsets('ACIS-I', 3, 930.2, 1009.6, '2016:180', -15.0) assert np.allclose(offsets, (11.83637884563926, 2.6860740140775334), atol=0.1) offsets = drift.get_aca_offsets('ACIS-S', 7, 200.7, 476.9, '2016:180', -15.0) assert np.allclose(offsets, (13.360706170615167, 3.8670874955935481), atol=0.1) offsets = drift.get_aca_offsets('HRC-I', 0, 7591, 7936, '2016:180', -15.0) assert np.allclose(offsets, (14.728718419826098, 0.7925650626134555), atol=0.1) offsets = drift.get_aca_offsets('HRC-S', 2, 2041, 9062, '2016:180', -15.0) assert np.allclose(offsets, (17.269560057119545, 3.4474216529603225), atol=0.1)
def test_get_aca_offsets(): """ Test that ACA offsets are reasonable, and regression test particular values corresponding to cycle 17 zero-offset aimpoints used below for chip_x, chip_y inputs. The output reference values here have been validated as being "reasonable" for the given inputs. """ offsets = drift.get_aca_offsets('ACIS-I', 3, 930.2, 1009.6, '2016:180:12:00:00', -15.0) assert np.allclose(offsets, (11.45, 2.34), atol=0.1, rtol=0) offsets = drift.get_aca_offsets('ACIS-S', 7, 200.7, 476.9, '2016:180:12:00:00', -15.0) assert np.allclose(offsets, (12.98, 3.52), atol=0.1, rtol=0) offsets = drift.get_aca_offsets('HRC-I', 0, 7591, 7936, '2016:180:12:00:00', -15.0) assert np.allclose(offsets, (14.35, 0.45), atol=0.1, rtol=0) offsets = drift.get_aca_offsets('HRC-S', 2, 2041, 9062, '2016:180:12:00:00', -15.0) assert np.allclose(offsets, (16.89, 3.10), atol=0.1, rtol=0)
def get_interval_data(intervals, times, ccd_temp, obsreqs=None): """ Determine the max temperature and mean offsets over each interval. If the OR list is supplied (in the obsreqs dictionary) the ACA offsets will also be calculated for each interval and included in the returned data. :param intervals: list of dictionaries describing obsid/catalog intervals :param times: times of the temperature samples :param ccd_temp: ccd temperature values :param obsreqs: optional dictionary of OR list from parse_cm.or_list :returns: dictionary (keyed by obsid) of intervals with max ccd_temps """ obstemps = {} for interval in intervals: # treat the model samples as temperature intervals # and find the max during each obsid npnt interval obs = {'ccd_temp': None} obs.update(interval) stop_idx = 1 + np.searchsorted(times, interval['tstop']) start_idx = -1 + np.searchsorted(times, interval['tstart']) ok_temps = ccd_temp[start_idx:stop_idx] ok_times = times[start_idx:stop_idx] # If there are no good samples, put the times in the output dict and go to the next interval if len(ok_temps) == 0: obstemps[str(interval['obsid'])] = obs continue obs['ccd_temp'] = np.max(ok_temps) obs['ccd_temp_acq'] = np.max(ok_temps[:2]) obs['n100_warm_frac'] = dark_model.get_warm_fracs( 100, interval['tstart'], np.max(ok_temps)) # If we have an OR list, the obsid is in that list, and the OR list has zero-offset keys if (obsreqs is not None and interval['obsid'] in obsreqs and 'chip_id' in obsreqs[interval['obsid']]): obsreq = obsreqs[interval['obsid']] ddy, ddz = get_aca_offsets(obsreq['detector'], obsreq['chip_id'], obsreq['chipx'], obsreq['chipy'], time=ok_times, t_ccd=ok_temps) obs['aca_offset_y'] = np.mean(ddy) obs['aca_offset_z'] = np.mean(ddz) obstemps[str(interval['obsid'])] = obs return obstemps
def run_one_yoshi(*, obsid, detector, chipx, chipy, chip_id, ra_targ, dec_targ, roll_targ, offset_y, offset_z, sim_offset, focus_offset, dither_y, dither_z, obs_date, t_ccd, man_angle): """ Run proseco and sparkles for an observation request in a roll/temperature/man_angle scenario. :param obsid: obsid :param detector: detector (ACIS-I|ACIS-S|HRC-I|HRC-S) :param chipx: chipx from zero-offset aimpoint table entry for obsid :param chipy: chipy from zero-offset aimpoint table entry for obsid :param chip_id: chip_id from zero-offset aimpoint table entry for obsid :param ra_targ: target RA (degrees) :param dec_targ: target Dec (degrees) :param roll_targ: target Roll (degrees) :param offset_y: target offset_y (arcmin) :param offset_z: target offset_z (arcmin) :param sim_offset: SIM Z offset (steps) :param focus_offset: SIM focus offset (steps) :param dither_y: Y amplitude dither (arcsec) :param dither_z: Z amplitude dither (arcsec) :param obs_date: observation date (for proper motion and ACA offset projection) :param t_ccd: ACA CCD temperature (degrees C) :param man_angle: maneuver angle (degrees) :returns: dictionary of (ra_aca, dec_aca, roll_aca, n_critical, n_warning, n_caution, n_info, P2, guide_count) """ # Calculate dynamic offsets using the supplied temperature. aca_offset_y, aca_offset_z = get_aca_offsets(detector, chip_id, chipx, chipy, obs_date, t_ccd) # Get the ACA quaternion using target offsets and dynamic offsets. # Note that calc_aca_from_targ expects target offsets in degrees and obs is now in arcmin q_aca = calc_aca_from_targ((ra_targ, dec_targ, roll_targ), (offset_y / 60.) + (aca_offset_y / 3600.), (offset_z / 60.) + (aca_offset_z / 3600.)) # Run proseco and sparkles aca = proseco.get_aca_catalog(obsid=obsid, att=q_aca, man_angle=man_angle, date=obs_date, t_ccd=t_ccd, dither=(dither_y, dither_z), detector=detector, sim_offset=sim_offset, focus_offset=focus_offset, n_acq=8, n_guide=5, n_fid=3) acar = aca.get_review_table() acar.run_aca_review() # Get values for report report = {'ra_aca': q_aca.ra, 'dec_aca': q_aca.dec, 'roll_aca': q_aca.roll, 'n_critical': len(acar.messages == 'critical'), 'n_warning': len(acar.messages == 'warning'), 'n_caution': len(acar.messages == 'caution'), 'n_info': len(acar.messages == 'info'), 'P2': -np.log10(acar.acqs.calc_p_safe()), 'guide_count': acar.guide_count} return report