def plot_both(x, title_str): for msid, color in (('aosares1', 'b'), ('pitch_fss', 'r')): plot_cxctime(x[msid].times, x[msid].vals, '-o' + color) bads = x[msid].bads if bads is not None and len(np.flatnonzero(bads)) > 0: plot_cxctime(x[msid].times[bads], x[msid].vals[bads], 'kx', ms=10., mew=2.5) plt.title(title_str)
def plot_warm_frac(): """ Plot the warm pixel fraction from the 2013 baseline dark current model vs. observed fractions from dark current calibrations. Note that the N=1000 prediction doesn't match observation that well (off by a scale factor). This is indicative that the pure powerlaw doesn't hold out that far, but it's not a big issue here. """ warm_thresholds = [50., 100., 200.] dates, pred_warm_fracs, obs_warm_fracs = get_warm_frac(warm_thresholds=warm_thresholds) plt.close(1) plt.figure(1, figsize=(6, 4)) for color, warm_threshold in zip(['b', 'g', 'r', 'k', 'c', 'm', 'y'], warm_thresholds): plot_cxctime(dates, obs_warm_fracs[warm_threshold], color + '.') plot_cxctime(dates, pred_warm_fracs[warm_threshold], color + '-', label='N > {:.0f} e-/sec'.format(warm_threshold)) x0, x1 = plt.xlim() dx = (x1 - x0) * 0.03 plt.xlim(x0 - dx, x1 + dx) plt.grid() plt.legend(loc='best', fontsize=12) plt.title('Warm pixel fraction: model (line), observed (dots) vs. time', fontsize=12) plt.ylabel('Warm pixel fraction') plt.tight_layout() plt.savefig('warm_frac_model.png')
def att_err_time_plots(ref_data, msd_data, min_dwell_time=1000, outdir='.'): ref_data = ref_data[(ref_data['timestop'] - ref_data['time']) >= min_dwell_time] msd_data = msd_data[(msd_data['timestop'] - msd_data['time']) >= min_dwell_time] for i, ax in enumerate(['roll', 'point'], 1): default_ylims = [0, 1.4] if ax == 'roll': default_ylims = [0, 12] fig = plt.figure(figsize=(5, 3.5)) ax1 = fig.add_axes([.15, .55, .8, .37]) plot_cxctime(ref_data['time'], ref_data['{}_err'.format(ax)], 'b+', markersize=5, alpha=.5, label='MSF ENAB') plt.ylabel('MSF Enabled\n{} err (arcsec)'.format(ax)) plt.grid() plt.margins(x=.1, y=.25) ax2 = fig.add_axes([.15, .1, .8, .37]) plot_cxctime(msd_data['time'], msd_data['{}_err'.format(ax)], 'rx', markersize=5, label='MSF DISA') plt.suptitle('99th percentile {} error magnitude (per obs)'.format(ax, i), fontsize=12) plt.grid() plt.ylabel('MSF Disabled\n{} err (arcsec)'.format(ax)) plt.margins(x=.1, y=.25) ylims = plt.ylim() setlims = plt.ylim(np.min([ylims[0], default_ylims[0]]), np.max([ylims[1], default_ylims[1]])) ax1.set_ylim(setlims) plt.setp(ax1.get_xticklabels(), visible=True) plt.setp(ax1.get_xticklabels(), fontsize=7) plt.setp(ax2.get_xticklabels(), fontsize=7) plt.setp(ax1.get_yticklabels(), fontsize=7) plt.setp(ax2.get_yticklabels(), fontsize=7) plt.setp(ax1.get_xticklabels(), rotation=0) plt.setp(ax1.get_xticklabels(), horizontalalignment='center') plt.savefig(os.path.join(outdir, '{}_err_vs_time.png'.format(ax)))
def plot_both(x, title_str): for msid, color in (('aosares1', 'b'), ('pitch_fss', 'r')): plot_cxctime(x[msid].times, x[msid].vals, '-o' + color) bads = x[msid].bads if bads is not None and len(np.flatnonzero(bads)) > 0: plot_cxctime(x[msid].times[bads], x[msid].vals[bads], 'kx', ms=10., mew=3) title(title_str)
def plot_n_kalman(obsid, plot_dir, save=False): """ Fetch and plot number of Kalman stars as function of time for the requested obsid. """ d = events.dwells.filter(obsid=obsid)[0] start = d.start stop = d.stop n_kalman = get_n_kalman(start, stop) plt.figure(figsize=(8, 2.5)) t0 = n_kalman.times[0] # The Kalman vals are strings, so these can be out of order on y axis # if not handled as ints. plot_cxctime(n_kalman.times, n_kalman.vals.astype(int), color='k') plot_cxctime([t0, t0 + 1000], [0.5, 0.5], lw=3, color='orange') plt.text(DateTime(t0).plotdate, 0.7, "1 ksec") plt.ylabel('# Kalman stars') ylims = plt.ylim() plt.ylim(-0.2, ylims[1] + 0.2) plt.grid(ls=':') plt.subplots_adjust(left=0.1, right=0.95, bottom=0.25, top=0.95) if save: outroot = os.path.join(plot_dir, f'n_kalman_{obsid}') logger.info(f'Writing plot file {outroot}.png') plt.savefig(outroot + '.png') plt.close()
def plot_pitches_any_kalman(out, angle_err_lim=8.0, savefig=False): """Plot pitch for all points where alpha_err > angle_err_lim. Cyan points are with no sun presence, red are with sun presence. Unlike plot_pitches() below there is no distinction made based on the kalman state. """ times = out['times'] pitch = out['pitch'] alpha_err = out['alpha'] - out['roll'] sun = out['alpha_sun'] & out['beta_sun'] bad = abs(alpha_err) > angle_err_lim zipvals = zip((~sun, sun), ('c.', 'r.'), ('c', 'r'), ('No Sun Presence', 'Sun Presence')) plt.figure() for filt, mark, mec, label in zipvals: plot_cxctime(times[bad & filt], pitch[bad & filt], mark, mec=mec, label=label) plt.legend(loc='lower left') plt.grid('on') plt.title("Pitch for alpha error > {} deg".format(angle_err_lim)) plt.ylabel('Pitch (deg)') x0, x1 = plt.xlim() dx = (x1 - x0) / 20 plt.xlim(x0 - dx, x1 + dx) y0, y1 = plt.ylim() y0 = min(y0, 133.5) dy = (y1 - y0) / 20 plt.ylim(y0 - dy, y1 + dy) if savefig: plt.savefig('pitch_bad_alpha.png')
def plot_limiting_mag(): """ Plot the future limiting magnitude for three cases of max T_ccd (-14, -11, -7). """ warm_threshold = 100. plt.close(1) plt.figure(1, figsize=(6, 4)) color = 'g' for t_ccd_max, offset, color in izip((-14, -11, -7), (0, 0.0025, 0.005), ('r', 'g', 'b')): dates, t_ccds = dark_models.ccd_temperature_model(t_ccd_max, start='2014:001', stop='2018:001', n=20) warm_fracs = [] for time, t_ccd in izip(dates.secs, t_ccds): warm_frac = dark_models.get_warm_fracs(warm_threshold, date=time, T_ccd=t_ccd) warm_fracs.append(warm_frac + offset) n100 = np.array(warm_fracs) mag_limit = np.log10(0.5 / n100) / 1.18 + 10.09 plot_cxctime(dates.secs, mag_limit, color + '-', label='T_ccd < {} C'.format(t_ccd_max), linewidth=1.5) x0, x1 = plt.xlim() dx = (x1 - x0) * 0.03 plt.xlim(x0 - dx, x1 + dx) plt.grid() plt.legend(loc='best', fontsize=12) plt.title('ACA Limiting magnitude vs. time') plt.ylabel('ACA Mag') plt.tight_layout() plt.savefig('limiting_mag.png')
def plot_both(x, title_str): for msid, color in (("aosares1", "b"), ("pitch_fss", "r")): plot_cxctime(x[msid].times, x[msid].vals, "-o" + color) bads = x[msid].bads if bads is not None and len(np.flatnonzero(bads)) > 0: plot_cxctime(x[msid].times[bads], x[msid].vals[bads], "kx", ms=10.0, mew=3) title(title_str)
def plotfids(detstats, det, tstart): fidcolor = " bgrcmkbgrcbgrc" fig = plt.figure(1, figsize=(6, 4.0)) plt.clf() ax1 = plt.subplot(1, 1, 1) plt.title(det + " Fid Drift") plt.grid() plt.ylabel("Y offset (arcsec)") plt.grid() for fid in FIDSET[det]: fidstats = detstats[detstats["id_num"] == fid] year = fidstats["tstart"] / 86400.0 / 365.25 + 1998.0 normmask = np.logical_and(year > 2002.0, year < 2003.0) fidstatsnorm = fidstats[normmask] if len(fidstatsnorm) < 3: print "Fid %s %d: Not enough readouts for the median" % (det, fid) continue y0 = np.median(fidstatsnorm["ang_y_med"]) ok = fidstats["tstart"] > tstart if sum(ok) > 0: plot_cxctime( fidstats["tstart"][ok], fidstats["ang_y_med"][ok] - y0, "o", markerfacecolor=fidcolor[fid], scaley=False, scalex=False, ) return fig, ax1
def main(): plt.figure() plt.clf() pitchs = range(110, 170, 2) # only consider tail sun for this plot model_spec = json.load(open('dpa_model_spec.json', 'r')) colors = {5: 'r', 6: 'b'} for n_ccd in range(5, 7): settle_temps = [] times = DateTime(np.arange(2012, 2015, 0.1), format='frac_year').secs for tstart in times: pitch_temps = [] for pitch in pitchs: model = calc_model(tstart, pitch, n_ccd, model_spec) pitch_temps.append(model.comp['1dpamzt'].mvals[-1]) settle_temp = np.max(pitch_temps) settle_temps.append(settle_temp) print n_ccd, DateTime(tstart).date, settle_temp plot_cxctime(times, settle_temps, label='CCDs={}'.format(n_ccd), color=colors[n_ccd]) x0, x1 = plt.xlim() plt.plot([x0, x1], [32.5, 32.5], '--b') plt.plot([x0, x1], [35, 35], '--g') plt.plot([x0, x1], [40, 40], '--r') plt.ylabel('1DPAMZT (degC)') plt.title('Max 1DPAMZT at any pitch') plt.grid() plt.tight_layout() plt.legend(loc='best') plt.savefig('max_settling_temp.png')
def plot_data__time(self, fig, ax): lines = ax.get_lines() if not lines: plot_cxctime(self.model.times, self.dvals, '-b', fig=fig, ax=ax) ax.grid() ax.set_title('{}: data'.format(self.name)) else: lines[0].set_data(self.model_plotdate, self.dvals)
def plot_data__time(self, fig, ax): lines = ax.get_lines() if lines: lines[0].set_data(self.model_plotdate, self.dvals) else: plot_cxctime(self.model.times, self.dvals, '-b', fig=fig, ax=ax) ax.grid() ax.set_title('{}: data (blue)'.format(self.name)) ax.set_ylabel('Power (W)')
def make_fish_2(): plt.close(1) plt.figure(1) plot_cxctime(dat.times, dat['roll'].vals) plt.close(2) plt.figure(2) plot_cxctime(dat.times, dat['pitch'].vals) plt.show()
def plot_data__time(self, fig, ax): lines = ax.get_lines() y = np.where(self.mask, 1, 0) if lines: lines[0].set_data(self.model_plotdate, y) else: plot_cxctime(self.model.times, y, '-b', fig=fig, ax=ax) ax.grid() ax.set_ylim(-0.1, 1.1) ax.set_title('{}: data'.format(self.name))
def plot_data__time(self, fig, ax): lines = ax.get_lines() if not lines: plot_cxctime(self.model.times, self.dvals, '-b', fig=fig, ax=ax) plot_cxctime(self.model.times, self.mvals, '-r', fig=fig, ax=ax) ax.grid() ax.set_title('{}: model (red) and data (blue)'.format(self.name)) ax.set_ylabel('Temperature (degC)') else: lines[0].set_ydata(self.dvals) lines[1].set_ydata(self.mvals)
def plot_axis(label, times, dy, filt, title=''): plt.figure(figsize=(6, 4)) plt.clf() plot_cxctime(times, dy, 'r.', markersize=0.3) if len(np.flatnonzero(filt)) > 0: plot_cxctime(times[filt], dy[filt], 'k.', markersize=2) plt.ylabel('Delta %s (arcsec)' % label) plt.title(title) plt.ylim(-10, 10) plt.subplots_adjust(bottom=0.05, top=0.85) plt.tight_layout()
def plot_data__time(self, fig, ax): powers = self.mvals * 100. / self.mult + self.bias lines = ax.get_lines() if lines: lines[0].set_data(self.model_plotdate, self.dvals) lines[1].set_data(self.model_plotdate, powers) else: plot_cxctime(self.model.times, self.dvals, '-r', fig=fig, ax=ax) plot_cxctime(self.model.times, powers, '-b', fig=fig, ax=ax) ax.grid() ax.set_title('{}: data (blue)'.format(self.name)) ax.set_ylabel('Power (W)')
def plot_aca_ccd_mission(): plt.close(1) fig = plt.figure(1, figsize=(6, 4)) dat = fetch.Msid('aacccdpt', '2000:001', stat='daily') dat.remove_intervals(bad_intervals) plot_cxctime(dat.times, dat.mins, '-b', fig=fig) plot_cxctime(dat.times, dat.maxes, '-b', fig=fig) plt.grid() plt.legend(loc='upper right', fontsize=12) plt.ylabel('Temperature (C)') plt.title('ACA CCD temperature') plt.tight_layout() plt.savefig('aca_ccd_mission.png')
def plot_model_dwell_stats(model, dwell_stats): import matplotlib.pyplot as plt from Ska.Matplotlib import plot_cxctime plt.close(1) plt.figure(1) plot_cxctime(model.times, model.comp['aacccdpt'].dvals, '-b') plot_cxctime(model.times, model.comp['aacccdpt'].mvals, '-r') y0, y1 = plt.ylim() plt.vlines(DateTime([dwell['start'] for dwell in dwell_stats]).plotdate, y0, y1) plt.show()
def plot_resid__time(self, fig, ax): lines = ax.get_lines() resids = self.dvals - self.mvals if self.mask: resids[~self.mask.mask] = np.nan if not lines: plot_cxctime(self.model.times, resids, '-b', fig=fig, ax=ax) ax.grid() ax.set_title('{}: residuals (data - model)'.format(self.name)) ax.set_ylabel('Temperature (degC)') else: lines[0].set_ydata(resids)
def test_check_many_sizes(dt): """ Run through a multiplicative series of x-axis lengths and visually confirm that chosen axes are OK. """ plt.close(0) plt.figure(0) t0 = np.random.uniform(3e7 * 10) times = np.linspace(t0, t0 + dt, 20) y = np.random.normal(size=len(times)) plot_cxctime(times, y) plt.savefig('test-{:09d}.png'.format(dt))
def mups_tank(stop): x=fetch.Msidset(['pmtank1t', 'pmtank2t', 'pmtank3t', 'pmfp01t', 'pmtankp', 'aosares1', 'aosares2'], '2009:100:00:00:00.000', stop, stat='5min') pmtankt = np.mean([x['pmtank1t'].means, x['pmtank2t'].means, x['pmtank3t'].means], axis=0) aosares = np.mean([x['aosares1'].means, x['aosares2'].means], axis=0) pp.figure() pp.subplot(4,1,1) plot_cxctime(x['pmtank1t'].times,pmtankt) pp.title('Average Tank Temperature') pp.ylabel('deg F') pp.subplot(4,1,2) plot_cxctime(x['pmfp01t'].times,x['pmfp01t'].vals) pp.title('MUPS Fill Panel Temperature') pp.ylabel('deg F') pp.subplot(4,1,3) plot_cxctime(x['pmtankp'].times,x['pmtankp'].vals) pp.title('MUPS Tank Pressure') pp.ylabel('psia') pp.subplot(4,1,4) plot_cxctime(x['aosares1'].times,aosares) pp.title('Average Solar Array Angle') pp.ylabel('deg') pp.tight_layout() pp.savefig('TankPressureUpdate.png')
def therm_dropouts(stop): vars=['plaev2bt','pm1thv1t','pm1thv2t','pm2thv1t','pm2thv2t','pr1tv01t'] col = ['b','g','r','c','m', '#CCCC00'] ys=np.array([[40,220],[80,200],[80,200],[80,200],[80,200],[80,180]]) x = fetch.Msidset(vars,'2004:001', stop, stat='daily') pp.figure(figsize=(8,12)) for i in range(len(vars)): pp.subplot(len(vars),1,i+1) plot_cxctime(x[vars[i]].times, x[vars[i]].maxes, col[i]) pp.title(x[vars[i]].msid.upper() + ' Maximum Daily Temperature') pp.ylabel(x[vars[i]].unit) pp.ylim(ys[i]) pp.tight_layout() pp.savefig('DropoutThermistorTemps.png')
def plot_data__time(self, fig, ax): lines = ax.get_lines() if not lines: plot_cxctime(self.model.times, self.dvals, ls='-', color='#386cb0', fig=fig, ax=ax) ax.grid() ax.set_title('{}: data'.format(self.name)) ylabel = '%s' % self.name if self.units is not None: ylabel += ' (%s)' % self.units ax.set_ylabel(ylabel) ax.margins(0.05) else: lines[0].set_data(self.model_plotdate, self.dvals)
def main(args=None): args = parse_args(args) tstart = DateTime().secs - args.n_days * 86400.0 db = Ska.DBI.DBI(dbi="sybase", server="sybase", user="******") detstats = get_fid_stats(db, "ACIS") db.conn.close() fig, ax1 = plotfids(detstats, "ACIS", tstart) dat = fetch.MSID("aach1t", tstart, stat="5min") yoff = -2.5 dat0 = 294.6 adjtemps = -13 - (dat.vals - dat0) * 4 + yoff ok = dat.times < DateTime("2011:186").secs if sum(ok) > 0: plot_cxctime(dat.times[ok], adjtemps[ok], "-r", ax=ax1, fig=fig) if sum(~ok) > 0: plot_cxctime(dat.times[~ok], adjtemps[~ok], "-r", ax=ax1, fig=fig, alpha=0.3, label="Pre-safemode (2011)") adjtemps = -6.5 - (dat.vals - dat0) * 4 + yoff ok = dat.times > DateTime("2011:193").secs if sum(ok) > 0: plot_cxctime(dat.times[ok], adjtemps[ok], "-b", ax=ax1, fig=fig, label="Post-safemode (2011)") if sum(~ok) > 0: plot_cxctime(dat.times[~ok], adjtemps[~ok], "-b", ax=ax1, fig=fig, alpha=0.3) plt.grid() plt.legend(loc="upper left") plt.tight_layout() plt.savefig(os.path.join(args.data_dir, "drift_model_y.png"))
def plot_time_table(t_ccd_table): fig = plt.figure(figsize=(6, 5)) day_secs = DateTime(t_ccd_table['day']).secs nom_t_ccd = t_ccd_table['nom_t_ccd'] best_t_ccd = t_ccd_table['best_t_ccd'] plot_cxctime(day_secs, nom_t_ccd, 'r') plot_cxctime(day_secs, best_t_ccd, 'b') plot_cxctime(day_secs, nom_t_ccd, 'r.', label='nom roll t ccd') plot_cxctime(day_secs, best_t_ccd, 'b.', label='best roll t ccd') plt.grid() plt.ylim(ymin=COLD_T_CCD, ymax=WARM_T_CCD + 3.0) plt.xlim(xmin=cxctime2plotdate([day_secs[0]]), xmax=cxctime2plotdate([day_secs[-1]])) plt.legend(loc='upper left', title="", numpoints=1, handlelength=.5) plt.ylabel('Max ACA CCD Temp (degC)') plt.tight_layout() return fig
def plot_2008246_event(id='a', savefig=False): if id == 'a': start = '2008:246:02:00:00' stop = '2008:246:03:00:00' else: start = '2008:246:13:20:00' stop = '2008:246:13:45:00' dat = fetch.MSIDset(['aoalpang', 'aosunprs', 'pitch'], start, stop) dat.interpolate(1.025, filter_bad=True) plt.figure(6) plt.clf() plt.subplot(2, 1, 1) plot_cxctime(dat['aoalpang'].times, dat['aoalpang'].vals, '.', label='Sun not present') plot_cxctime(dat['aoalpang'].times, dat['aoalpang'].vals) ok = dat['aosunprs'].vals == 'SUN ' plot_cxctime(dat['aoalpang'].times[ok], dat['aoalpang'].vals[ok], '.r', ms=12, mec='r', label='Sun present') plt.title('Bad Alpha angles with sun presence on 2008:246') plt.ylabel('AOALPANG (deg)') plt.legend(loc='upper left') plt.grid() plt.subplot(2, 1, 2) plot_cxctime(dat['pitch'].times, dat['pitch'].vals, '.') plt.title('Pitch angle') plt.ylabel('pitch (deg)') plt.grid() plt.tight_layout() if savefig: plt.savefig('event_2008246{}.png'.format(id))
def manvr(evt, figsize=(8, 10), fig=None): """ Plot a Manvr event """ ms = evt.msidset if fig is None: fig = plt.figure(figsize=figsize) fig.clf() tstarts = [evt.tstart, evt.tstart] tstops = [evt.tstop, evt.tstop] colors = ['r', 'b', 'g', 'm'] # AOATTQT estimated quaternion ax1 = fig.add_subplot(3, 1, 1) for i, color in zip(range(1, 5), colors): msid = 'aoattqt{}'.format(i) plot_cxctime(ms[msid].times, ms[msid].vals, fig=fig, ax=ax1, color=color, linestyle='-', label=msid, interactive=False) ax1.set_ylim(-1.05, 1.05) ax1.set_title('Maneuver at {}'.format(evt.start[:-4])) # AOATTER attitude error (arcsec) ax2 = fig.add_subplot(3, 1, 2, sharex=ax1) msids = ['aoatter{}'.format(i) for i in range(1, 4)] + ['one_shot'] scales = [R2A, R2A, R2A, 1.0] for color, msid, scale in zip(colors, msids, scales): plot_cxctime(ms[msid].times, ms[msid].vals * scale, fig=fig, ax=ax2, color=color, linestyle='-', label=msid, interactive=False) ax2.set_ylabel('Attitude error (arcsec)') fix_ylim(ax2, 10) # ACA sequence ax3 = fig.add_subplot(3, 1, 3, sharex=ax1) msid = ms['aoacaseq'] plot_cxctime(msid.times, msid.raw_vals, state_codes=msid.state_codes, fig=fig, ax=ax3, interactive=False, label='aoacaseq') fix_ylim(ax3, 2.2) for ax in [ax1, ax2, ax3]: ax.callbacks.connect('xlim_changed', remake_ticks) plot_cxctime(tstarts, ax.get_ylim(), '--r', fig=fig, ax=ax, interactive=False) plot_cxctime(tstops, ax.get_ylim(), '--r', fig=fig, ax=ax, interactive=False) ax.grid() leg = ax.legend(loc='upper left', fontsize='small', fancybox=True) if leg is not None: leg.get_frame().set_alpha(0.7) fig.canvas.draw()
def plot_axis(label, times, dy, ok, dp, ir, ms, sp, flags, filename=None): plt.figure(figsize=(6, 4)) plt.clf() filt = (ok & (flags['dp'] == dp) & (flags['ir'] == ir) & (flags['ms'] == ms) & (flags['sp'] == sp)) plot_cxctime(times[ok], dy[ok], 'r.', markersize=0.3) if len(np.flatnonzero(filt)) > 0: plot_cxctime(times[filt], dy[filt], 'k.', markersize=2) plt.ylabel('Delta %s (arcsec)' % label) plt.title('DP={0} IR={1} MS={2} SP={3}'.format(dp, ir, ms, sp)) plt.ylim(-10, 10) plt.subplots_adjust(bottom=0.05, top=0.85) if filename is not None: ext = str(dp)[0] + str(ir)[0] + str(ms)[0] + str(sp)[0] plt.savefig(filename + ext + '.png')
def plot_resid__time(self, fig, ax): lines = ax.get_lines() resids = self.resids if self.mask: resids[~self.mask.mask] = np.nan if not lines: plot_cxctime(self.model.times, resids, ls='-', color='#386cb0', fig=fig, ax=ax) # Overplot bad time regions in cyan for i0, i1 in self.model.bad_times_indices: plot_cxctime(self.model.times[i0:i1], resids[i0:i1], '-c', fig=fig, ax=ax, linewidth=5, alpha=0.5) ax.grid() ax.set_title('{}: residuals (data - model)'.format(self.name)) ax.set_ylabel('Temperature (%s)' % self.units) else: lines[0].set_ydata(resids)
def plot_resid__time(self, fig, ax): lines = ax.get_lines() resids = self.resids if self.mask: resids[~self.mask.mask] = np.nan if not lines: plot_cxctime(self.model.times, resids, '-b', fig=fig, ax=ax) # Overplot bad time regions in cyan if hasattr(self.model, 'bad_times_indices'): for i0, i1 in self.model.bad_times_indices: plot_cxctime(self.model.times[i0:i1], resids[i0:i1], '-c', fig=fig, ax=ax, linewidth=5, alpha=0.5) ax.grid() ax.set_title('{}: residuals (data - model)'.format(self.name)) ax.set_ylabel('Temperature (degC)') else: lines[0].set_ydata(resids)
def pointing_stab(error_axis, start, stop, savefig=True): #NOT DONE YET! Doesn't match expected results # Identify msid corresponding to attitude error in selected axis i = ['roll', 'pitch','yaw'].index(error_axis.lower()) msid = 'aoatter' + str(i + 1) # Fetch data and interpolate to 10 second samples data = fetch.Msidset([msid, 'aopcadmd', 'aofunlst', 'aoacaseq'], start, stop) data.interpolate(dt=1.0) t = data[msid].times err = data[msid].vals * 180 / np.pi * 3600 # conv rad to arcsec # Reshape with a new column for each 10.0 sec period err_by_10sec = reshape_array(err, 10) # Compute a standard deviation for each period stdev = np.std(err_by_10sec, axis=0) # Reshape with a new column for each day stdev_by_day = reshape_array(stdev, 8640) # Create filter for NPM, Kalman (+180 sec), and no momentum dumps (+900 sec) npm = (data['aopcadmd'].vals == 'NPNT') kalm = (data['aoacaseq'].vals == 'KALM') kalm_3min = np.append(np.zeros(180, dtype=bool), kalm[180:]) no_dump = (data['aofunlst'].vals == 'NONE') no_dump_15min = np.append(np.zeros(900, dtype=bool), no_dump[900:]) ok = npm & kalm & kalm_3min & no_dump & no_dump_15min # Reshape with a new column for each 10.0 sec period ok_by_10sec = reshape_array(ok, 10) # Compute a filter for each 10.0 sec period ok_10sec = multiply.reduce(ok_by_10sec, axis=0) # Reshape with a new column for each day ok_by_day = reshape_array(ok_10sec, 8640) # Compute 95th percentile for each daily set of standard deviations, only including "ok" points point_stab = [np.percentile(stdev_by_day[:,i][ok_by_day[:,i]], 95) for i in range(ok_by_day.shape[1])] # Select a timestamp in the middle of the 24 hour period to represent the day t_rep = t[4319::8640][:ok_by_day.shape[1]] # Plot results plot_cxctime(t_rep, point_stab) pp.title(error_axis.upper() + ' POINTING STABILITY') pp.ylabel('arcsec') if savefig == True: pp.savefig(error_axis.lower() + '_pointing_stab.png') pp.close()
def main(): mstate_file = 'states.txt' mtemp_file = '1pdeaat.txt' mstates = Ska.Table.read_ascii_table(mstate_file) marray = [] for state in mstates: state_list = list( state ) state_list.append(DateTime(state['tstart']).secs) state_list.append(DateTime(state['tstop']).secs) marray.append(state_list) matlab_states = np.core.records.fromrecords( marray, names ='datestart,datestop,obsid,simpos,ccd_count,fep_count,vid_board,clocking,power,pitch,tstart,tstop') matlab_pred = Ska.Table.read_ascii_table( mtemp_file ) dates = matlab_pred['Time'] state0 = matlab_states[0] msid_string = { '1pdeaat' : '1PDEAAT Prediction (degC)', '1pin1at' : '1PIN1AT Prediction' } dea0 = matlab_pred[0][msid_string['1pdeaat']] pin0 = matlab_pred[0][msid_string['1pin1at']] times = DateTime( dates ).secs ( T_pin, T_dea ) = twodof.calc_twodof_model( matlab_states, pin0, dea0, times, characteristics.model_par) preds = np.core.records.fromarrays([ times, T_pin, T_dea], names='time,1pin1at,1pdeaat') pyt_file = open('python_temps.csv', 'w') pyt_file.write("Time\t%s\t%s\n" % ( msid_string['1pdeaat'], msid_string['1pin1at'] )) for pred in preds: pyt_file.write("%s\t%s\t%s\n" % ( DateTime(pred['time']).date, pred['1pdeaat'], pred['1pin1at'])) for msid in ('1pdeaat', '1pin1at'): figure(1,figsize=(5,3.75)) plot_cxctime( times, matlab_pred[msid_string[msid]], fmt='r.') plot_cxctime( times, preds[msid], fmt='b.') xlabel('CXC Time') ylabel('%s (Deg C)' % msid ) savefig('%s.png' % msid ) clf() hist( matlab_pred[msid_string[msid]] - preds[msid], bins=20) xlabel('Diff (Deg C)') title("matlab - python") savefig('%s_hist.png' % msid ) clf()
def plot_fss_temp(out, tfss=None, angle_err_lim=8.0, savefig=False): times = out['times'] alpha_err = out['alpha'] - out['roll'] alpha_sun = out['alpha_sun'] beta_sun = out['beta_sun'] bad = alpha_sun & beta_sun & (abs(alpha_err) > angle_err_lim) if tfss is None: tfss = fetch.Msidset(['tfssbkt1'], times[0], times[-1]) tfss.interpolate(out['times'][1] - out['times'][0]) idxs = np.searchsorted(tfss.times, times[bad]) idxs = idxs[idxs < len(tfss.times)] plt.figure(11) plt.clf() tfssbkt1 = tfss['tfssbkt1'].vals plot_cxctime(tfss.times, tfssbkt1, ',', color='c', mec='c') plot_cxctime(tfss.times[idxs], tfssbkt1[idxs], '.', color='b', mec='b', ms=3) plt.title('FSS temperature for bad FSS data') plt.ylabel('Temperature (degF)') if savefig: plt.savefig('fss_temp_bad_fss.png') plt.figure(12) plt.clf() plt.subplot(2, 1, 1) n, bins, p = plt.hist(tfssbkt1, bins=30) plt.title('Histogram of all TFSSBKT1 values (2011:001 - 2012:150)') plt.grid() plt.subplot(2, 1, 2) plt.hist(tfssbkt1[idxs], bins=bins) plt.title('Histogram of TFSSBKT1 values for bad FSS data') plt.grid() plt.xlabel('TFSSBKT1 temperature (degF)') plt.tight_layout() if savefig: plt.savefig('fss_temp_hist.png') import scipy.stats print scipy.stats.ks_2samp(tfssbkt1, tfssbkt1[idxs]) return tfss
def plot_bgd(e, edir): """ Make a plot of BGDAVG over an event and save to `edir`. Presently plots over range from 100 seconds before high threshold crossing to 300 seconds after high threshold crossing. :param e: dictionary with times of background event :param edir: directory for plots """ slots = [int(s) for s in e['slots_for_sum'].split(',')] plt.figure(figsize=(4, 4.5)) max_bgd = 0 for slot in slots: l0_telem = aca_l0.get_slot_data(e['cross_time'] - 100, e['cross_time'] + 300, imgsize=[4, 6, 8], slot=slot) if len(l0_telem['TIME']) == 0: raise ValueError ok = (l0_telem['QUALITY'] == 0) & (l0_telem['IMGFUNC1'] == 1) if np.count_nonzero(ok) > 0: plot_cxctime(l0_telem['TIME'][ok], l0_telem['BGDAVG'][ok], '.', label=f'slot {slot}') max_bgd = max([max_bgd, np.max(l0_telem['BGDAVG'][ok])]) plt.title("Hi BGD obsid {}\n start {}".format( e['obsid'], DateTime(e['event_tstart']).date), fontsize='small') plt.legend(numpoints=1, fontsize='x-small') plt.tight_layout() plt.margins(.05) plt.ylim([-20, 1100]) plt.grid() filename = "bgdavg_{}.png".format(e['event_datestart']) plt.savefig(os.path.join(edir, filename)) plt.close() return filename, max_bgd
def main(): mainbus_voltage_msid = "2PRBSVL" #bus24_voltage_msid = "2P24VAVL" mainbus_current_msid = "2PRBSCR" #mainbus_voltage_msid = "1DP28BVO" #mainbus_current_msid = "1DP28BCU" #mainbus_current_msid = "2PRBSCR" missiondays = 6200 # Go back roughly 18 years now = Chandra.Time.DateTime().secs start = now - missiondays * 24.0 * 3600.0 mainbus_voltage_telemetry = fetchTelemetry(mainbus_voltage_msid, start, now) mainbus_current_telemetry = fetchTelemetry(mainbus_current_msid, start, now) #bus24_voltage_telemetry = fetchTelemetry(bus24_voltage_msid, start, now) mainbus_voltage_volts, mainbus_current_amps = scaleTelemetry( mainbus_voltage_telemetry, mainbus_current_telemetry) watts = mainbus_voltage_telemetry.vals * mainbus_current_telemetry.vals plot_cxctime(mainbus_voltage_telemetry.times, mainbus_voltage_telemetry.vals, fmt='') plot_cxctime(mainbus_current_telemetry.times, mainbus_current_amps, fmt='') #plot_cxctime(mainbus_current_telemetry.times, bus24_voltage_telemetry.vals, fmt='') plot_cxctime(mainbus_current_telemetry.times, watts, fmt='')
def plot_data__time(self, fig, ax): lines = ax.get_lines() if not lines: plot_cxctime(self.model.times, self.mvals, ls='-', color='#d92121', fig=fig, ax=ax) plot_cxctime(self.model.times, self.dvals, ls='-', color='#386cb0', fig=fig, ax=ax) # Overplot bad time regions in cyan for i0, i1 in self.model.bad_times_indices: plot_cxctime(self.model.times[i0:i1], self.dvals[i0:i1], '-c', fig=fig, ax=ax, linewidth=5, alpha=0.5) ax.grid() ax.set_title('{}: model (red) and data (blue)'.format(self.name)) ax.set_ylabel('Temperature (%s)' % self.units) else: lines[0].set_ydata(self.mvals)
def tlm_event(evt, figsize=None, fig=None): """ Generic plot for a telemetry event """ plt.ioff() ms = evt.msidset n_axes = len(evt.fetch_event_msids) if fig is None: figsizes = {1: (8, 5), 2: (8, 6.5), 3: (8, 8), 4: (8, 10)} fig = plt.figure(figsize=figsizes.get(n_axes, (8, 12))) fig.clf() for i, msid in enumerate(evt.fetch_event_msids): if i == 0: ax1 = fig.add_subplot(n_axes, 1, 1) ax = ax1 else: ax = fig.add_subplot(n_axes, 1, i + 1, sharex=ax1) # Skip if no telemetry was found if len(ms[msid].times) == 0: continue ax.set_ymargin(0.15) plot_cxctime(ms[msid].times, ms[msid].raw_vals, state_codes=ms[msid].state_codes, label=msid, ax=ax) ax.set_ymargin(0) plot_cxctime([evt.tstart, evt.tstart], ax.get_ylim(), 'm--', ax=ax) plot_cxctime([evt.tstop, evt.tstop], ax.get_ylim(), 'm--', ax=ax) ax.grid() leg = ax.legend(loc='upper left', fontsize='small', fancybox=True) if leg is not None: leg.get_frame().set_alpha(0.7) fig.tight_layout() plt.draw() plt.show() plt.ion()
import os import sys from matplotlib.pyplot import * import Ska.engarchive.fetch_sci as fetch from Ska.Matplotlib import plot_cxctime print 'Fetch file is', fetch.__file__ print 'ENG_ARCHIVE is', os.environ['ENG_ARCHIVE'] msids = ('1crat', 'fptemp_11', 'orbitephem0_x', 'sim_z', 'tephin') rootdir = os.path.dirname(__file__) for ifig, msid in enumerate(msids): figure(ifig + 1) clf() dat = fetch.MSID(msid, '2010:250', '2011:100', filter_bad=True) dat5 = fetch.MSID(msid, '2010:250', '2011:100', stat='5min') datday = fetch.MSID(msid, '2010:250', '2011:100', stat='daily') subplot(3, 1, 1) plot_cxctime(dat.times, dat.vals, '-b') grid() subplot(3, 1, 2) plot_cxctime(dat5.times, dat5.means, '-r') grid() subplot(3, 1, 3) plot_cxctime(datday.times, datday.means, '-c') grid() savefig(os.path.join(rootdir, 'plot_{0}.png'.format(msid)))
fit, modpars = fit_pix_values(t_ccd, y, id=i_col) fits[y.name] = {'fit': fit, 'modpars': modpars} fitmod = ui.get_model_plot(i_col) #plot_cxctime(DateTime(dat['time'][0]).secs + x, fitmod.y, color='red', ax=ax) #plt.tight_layout() plot2 = plot_two(fig_id='overplots', x2=dat['time'], y2=y, x=dat['time'], y=t_ccd, color='blue', color2='black') plot_cxctime(DateTime(dat['time'][0]).secs + x, fitmod.y, color='red', ax=plot2['ax2'], linewidth=6, alpha=.5, label="Dark current model") plot2['ax2'].legend(loc='upper left', fontsize=10) plot2['ax'].yaxis.label.set_color('blue') plot2['ax'].tick_params(axis='y', colors='blue') plot2['ax2'].set_ylabel('Dark Current (e-/sec)') plot2['ax'].set_ylabel('CCD Temp (DegC)') plot2['ax'].tick_params(axis='x', which='major', labelsize=10) #plot2['fig'].suptitle('Dark Current, CCD Temp, and Fit vs Time') onefig.tight_layout() print_info_block(fits, dat[-1]) plt.draw() onefig.savefig("annealing.png")
def plot_observed_aimpoints(obs_aimpoints): """ Make png plot of data in the ``obs_aimpoints`` table. """ dates = DateTime(obs_aimpoints['mean_date']) years = dates.frac_year times = dates.secs ok = years > np.max(years) - float(opt.lookback) / 365.25 obs_aimpoints = obs_aimpoints[ok] times = times[ok] lolims = {} uplims = {} for axis in ('dx', 'dy'): lolims[axis] = obs_aimpoints[axis] > 15 uplims[axis] = obs_aimpoints[axis] < -15 obs_aimpoints[axis] = obs_aimpoints[axis].clip(-15, 15) for idx, axis, label in zip([1, 2], ['dx', 'dy'], ['CHIPX', 'CHIPY']): plt.close(idx) fig = plt.figure(idx, figsize=(8, 4)) for det, c in zip(['HRC-I', 'HRC-S', 'ACIS-I', 'ACIS-S'], ['cyan', 'magenta', 'red', 'blue']): offset_ok = ((np.abs(obs_aimpoints['target_offset_y']) < 100) & (np.abs(obs_aimpoints['target_offset_z']) < 100)) det_ok = obs_aimpoints['detector'] == det ok = offset_ok & det_ok nok = ~offset_ok & det_ok kwargs = dict(markeredgecolor='k', markeredgewidth=0.5, linestyle='') if np.count_nonzero(ok): plot_cxctime(times[ok], obs_aimpoints[axis][ok], marker='o', markerfacecolor=c, alpha=0.5, label=det, **kwargs) if np.count_nonzero(nok): plot_cxctime(times[nok], obs_aimpoints[axis][nok], marker='*', markerfacecolor=c, **kwargs) if np.any(lolims[axis]): plt.errorbar(DateTime(times[lolims[axis]]).plotdate, obs_aimpoints[axis][lolims[axis]], marker='.', markerfacecolor=c, yerr=1.5, lolims=True, **kwargs) if np.any(uplims[axis]): plt.errorbar(DateTime(times[uplims[axis]]).plotdate, obs_aimpoints[axis][uplims[axis]], marker='.', markerfacecolor=c, yerr=1.5, uplims=True, **kwargs) plt.grid() plt.ylim(-17, 17) plt.ylabel('Offset (arcsec)') plt.title('Observed aimpoint offsets {}'.format(label)) plt.legend(loc='upper left', fontsize='x-small', title='', framealpha=0.5, numpoints=1) ax = plt.gca() plt.plot([0.5], [0.9], marker='*', markerfacecolor='none', transform=ax.transAxes, **kwargs) plt.text(0.52, 0.9, 'Target offset > 100 arcsec', horizontalalignment='left', verticalalignment='center', transform=ax.transAxes, fontsize='small') outroot = os.path.join(opt.data_root, 'observed_aimpoints_{}'.format(axis)) logger.info('Writing plot files {}.png'.format(outroot)) fig.patch.set_visible(False) plt.savefig(outroot + '.png', facecolor="none")
# Ephemeris values: position (meters) of Chandra relative to Earth center in # ECI coordinate frame. model.comp['orbitephem0_x'].set_data(25000e3) # 25000 km model.comp['orbitephem0_y'].set_data(25000e3) # 25000 km model.comp['orbitephem0_z'].set_data(25000e3) # 25000 km # Normalized attitude quaternions model.comp['aoattqt1'].set_data(0.0) model.comp['aoattqt2'].set_data(0.0) model.comp['aoattqt3'].set_data(0.0) model.comp['aoattqt4'].set_data(1.0) # All the usual values here model.comp['pitch'].set_data(130) model.comp['eclipse'].set_data(False) model.comp['sim_z'].set_data(75000) model.comp['ccd_count'].set_data(6) model.comp['fep_count'].set_data(6) model.comp['vid_board'].set_data(1) model.comp['clocking'].set_data(1) model.comp['dpa_power'].set_data(0.0) model.make() model.calc() # Note the telemetry MSID is fptemp_11 but the Node name is fptemp fptemp_11 = fetch_eng.Msid('fptemp_11', start, stop) # DEGC plot_cxctime(model.times, model.comp['fptemp'].mvals, 'r-') plot_cxctime(fptemp_11.times, fptemp_11.vals, 'b-')
## scp ccosmos.cfa.harvard.edu:biases.zip ./ ## unzip biases.zip # <demo> --- stop --- ## **Plotting time data** ## Even though seconds since 1998.0 is convenient for computations it isn't so ## natural for humans. As mentioned the ``Chandra.Time`` module can help with ## converting between formats but for making plots we use the ## `plot_cxctime() <http://cxc.harvard.edu/mta/ASPECT/tool_doc/pydocs/Ska.Matplotlib.html#Ska.Matplotlib.plot_cxctime>`_ ## function of the ``Ska.Matplotlib`` module:: from Ska.Matplotlib import plot_cxctime clf() out = plot_cxctime(tephin.times, tephin.vals) # <demo> --- stop --- ## **Bad data** ## At this point we've glossed over the important point of possible bad data. For ## various reasons (typically a VCDU drop) the data value associated with a particular ## readout may be bad. To handle this the engineering archive provides a boolean array ## called ``bads`` that is ``True`` for bad samples. This array corresponds to the ## respective ``times`` and ``vals`` arrays. To remove the bad values one can use numpy ## boolean masking:: ok = ~tephin.bads # numpy mask requires the "good" values to be True vals_ok = tephin.vals[ok] times_ok = tephin.times[ok]
def main(opt): opt, args = get_options() if not os.path.exists(opt.outdir): os.mkdir(opt.outdir) config_logging(opt.outdir, opt.verbose) # Store info relevant to processing for use in outputs proc = dict( run_user=os.environ['USER'], run_time=time.ctime(), errors=[], ) logger.info( '#####################################################################' ) logger.info( '# %s run at %s by %s' % (os.path.dirname(__file__), proc['run_time'], proc['run_user'])) logger.info('# version = %s' % VERSION) logger.info('# characteristics version = %s' % characteristics.VERSION) logger.info( '#####################################################################\n' ) logger.info('Command line options:\n%s\n' % pformat(opt.__dict__)) # Connect to database (NEED TO USE aca_read) tnow = DateTime(opt.run_start_time).secs tstart = tnow # Get temperature telemetry for 3 weeks prior to min(tstart, NOW) tlm = get_telem_values(tstart, [ 'sim_z', 'dp_pitch', 'aoacaseq', 'aodithen', 'cacalsta', 'cobsrqid', 'aofunlst', 'aopcadmd', '4ootgsel', '4ootgmtn', 'aocmdqt1', 'aocmdqt2', 'aocmdqt3', '1de28avo', '1deicacu', '1dp28avo', '1dpicacu', '1dp28bvo', '1dpicbcu' ], days=opt.days, name_map={ 'sim_z': 'tscpos', 'cobsrqid': 'obsid' }) tlm['tscpos'] = tlm['tscpos'] * -397.7225924607 outdir = opt.outdir states = get_states(tlm[0].date, tlm[-1].date) write_states(opt, states) tlm = Ska.Numpy.add_column(tlm, 'power', smoothed_power(tlm)) # Get bad time intervals bad_time_mask = get_bad_mask(tlm) # Interpolate states onto the tlm.date grid state_vals = cmd_states.interpolate_states(states, tlm['date']) # "Forgive" dither intervals with dark current replicas # This will also exclude dither disables that are in cmd states for standard dark cals dark_mask = np.zeros(len(tlm), dtype='bool') dark_times = [] # Find dither "disable" states from tlm dith_disa_states = logical_intervals(tlm['date'], tlm['aodithen'] == 'DISA') for state in dith_disa_states: # Index back into telemetry for each of these constant dither disable states idx0 = np.searchsorted(tlm['date'], state['tstart'], side='left') idx1 = np.searchsorted(tlm['date'], state['tstop'], side='right') # If any samples have aca calibration flag, mark interval for exclusion. if np.any(tlm['cacalsta'][idx0:idx1] != 'OFF '): dark_mask[idx0:idx1] = True dark_times.append({ 'start': state['datestart'], 'stop': state['datestop'] }) # Calculate the 4th term of the commanded quaternions cmd_q4 = np.sqrt( np.abs(1.0 - tlm['aocmdqt1']**2 - tlm['aocmdqt2']**2 - tlm['aocmdqt3']**2)) raw_tlm_q = np.vstack( [tlm['aocmdqt1'], tlm['aocmdqt2'], tlm['aocmdqt3'], cmd_q4]).transpose() # Calculate angle/roll differences in state cmd vs tlm cmd quaternions raw_state_q = np.vstack([state_vals[n] for n in ['q1', 'q2', 'q3', 'q4']]).transpose() tlm_q = normalize(raw_tlm_q) # only use values that aren't NaNs good = np.isnan(np.sum(tlm_q, axis=-1)) == False # and are in NPNT npnt = tlm['aopcadmd'] == 'NPNT' # and are in KALM after the first 2 sample of the transition not_kalm = tlm['aoacaseq'] != 'KALM' kalm = (not_kalm | np.hstack([[False, False], not_kalm[:-2]])) == False # and aren't during momentum unloads or in the first 2 samples after unloads unload = tlm['aofunlst'] != 'NONE' no_unload = (unload | np.hstack([[False, False], unload[:-2]])) == False ok = good & npnt & kalm & no_unload & ~bad_time_mask state_q = normalize(raw_state_q) dot_q = np.sum(tlm_q[ok] * state_q[ok], axis=-1) dot_q[dot_q > 1] = 1 angle_diff = np.degrees(2 * np.arccos(dot_q)) angle_diff = np.min([angle_diff, 360 - angle_diff], axis=0) roll_diff = Quat(tlm_q[ok]).roll - Quat(state_q[ok]).roll roll_diff = np.min([roll_diff, 360 - roll_diff], axis=0) for msid in MODE_SOURCE: tlm_col = np.zeros(len(tlm)) state_col = np.zeros(len(tlm)) for mode, idx in zip(MODE_MSIDS[msid], count()): tlm_col[tlm[MODE_SOURCE[msid]] == mode] = idx state_col[state_vals[msid] == mode] = idx tlm = Ska.Numpy.add_column(tlm, msid, tlm_col) state_vals = Ska.Numpy.add_column(state_vals, "{}_pred".format(msid), state_col) for msid in ['letg', 'hetg']: txt = np.repeat('RETR', len(tlm)) # use a combination of the select telemetry and the insertion telem to # approximate the state_vals values txt[(tlm['4ootgsel'] == msid.upper()) & (tlm['4ootgmtn'] == 'INSE')] = 'INSE' tlm_col = np.zeros(len(tlm)) state_col = np.zeros(len(tlm)) for mode, idx in zip(MODE_MSIDS[msid], count()): tlm_col[txt == mode] = idx state_col[state_vals[msid] == mode] = idx tlm = Ska.Numpy.add_column(tlm, msid, tlm_col) state_vals = Ska.Numpy.add_column(state_vals, "{}_pred".format(msid), state_col) diff_only = { 'pointing': { 'diff': angle_diff * 3600, 'date': tlm['date'][ok] }, 'roll': { 'diff': roll_diff * 3600, 'date': tlm['date'][ok] } } pred = { 'dp_pitch': state_vals.pitch, 'obsid': state_vals.obsid, 'dither': state_vals['dither_pred'], 'pcad_mode': state_vals['pcad_mode_pred'], 'letg': state_vals['letg_pred'], 'hetg': state_vals['hetg_pred'], 'tscpos': state_vals.simpos, 'power': state_vals.power, 'pointing': 1, 'roll': 1 } plots_validation = [] valid_viols = [] logger.info('Making validation plots and quantile table') quantiles = (1, 5, 16, 50, 84, 95, 99) # store lines of quantile table in a string and write out later quant_table = '' quant_head = ",".join(['MSID'] + ["quant%d" % x for x in quantiles]) quant_table += quant_head + "\n" for fig_id, msid in enumerate(sorted(pred)): plot = dict(msid=msid.upper()) fig = plt.figure(10 + fig_id, figsize=(7, 3.5)) fig.clf() scale = SCALES.get(msid, 1.0) ax = None if msid not in diff_only: if msid in MODE_MSIDS: state_msid = np.zeros(len(tlm)) for mode, idx in zip(MODE_MSIDS[msid], count()): state_msid[state_vals[msid] == mode] = idx ticklocs, fig, ax = plot_cxctime(tlm['date'], tlm[msid], fig=fig, fmt='-r') ticklocs, fig, ax = plot_cxctime(tlm['date'], state_msid, fig=fig, fmt='-b') plt.yticks(range(len(MODE_MSIDS[msid])), MODE_MSIDS[msid]) else: ticklocs, fig, ax = plot_cxctime(tlm['date'], tlm[msid] / scale, fig=fig, fmt='-r') ticklocs, fig, ax = plot_cxctime(tlm['date'], pred[msid] / scale, fig=fig, fmt='-b') else: ticklocs, fig, ax = plot_cxctime(diff_only[msid]['date'], diff_only[msid]['diff'] / scale, fig=fig, fmt='-k') plot['diff_only'] = msid in diff_only ax.set_title(TITLE[msid]) ax.set_ylabel(LABELS[msid]) xlims = ax.get_xlim() ylims = ax.get_ylim() bad_times = list(characteristics.bad_times) # Add the time intervals of dark current calibrations that have been excluded from # the diffs to the "bad_times" for validation so they also can be marked with grey # rectangles in the plot. This is only really visible with interactive/zoomed plot. if msid in ['dither', 'pcad_mode']: bad_times.extend(dark_times) # Add "background" grey rectangles for excluded time regions to vs-time plot for bad in bad_times: bad_start = cxc2pd([DateTime(bad['start']).secs])[0] bad_stop = cxc2pd([DateTime(bad['stop']).secs])[0] if not ((bad_stop >= xlims[0]) & (bad_start <= xlims[1])): continue rect = matplotlib.patches.Rectangle((bad_start, ylims[0]), bad_stop - bad_start, ylims[1] - ylims[0], alpha=.2, facecolor='black', edgecolor='none') ax.add_patch(rect) filename = msid + '_valid.png' outfile = os.path.join(outdir, filename) logger.info('Writing plot file %s' % outfile) plt.tight_layout() plt.margins(0.05) fig.savefig(outfile) plot['lines'] = filename if msid not in diff_only: ok = ~bad_time_mask if msid in ['dither', 'pcad_mode']: # For these two validations also ignore intervals during a dark current calibration ok &= ~dark_mask diff = tlm[msid][ok] - pred[msid][ok] else: diff = diff_only[msid]['diff'] # Sort the diffs in-place because we're just using them in aggregate diff = np.sort(diff) # if there are only a few residuals, don't bother with histograms if msid.upper() in validation_scale_count: plot['samples'] = len(diff) plot['diff_count'] = np.count_nonzero(diff) plot['n_changes'] = 1 + np.count_nonzero(pred[msid][1:] - pred[msid][0:-1]) if (plot['diff_count'] < (plot['n_changes'] * validation_scale_count[msid.upper()])): plots_validation.append(plot) continue # if the msid exceeds the diff count, add a validation violation else: viol = { 'msid': "{}_diff_count".format(msid), 'value': plot['diff_count'], 'limit': plot['n_changes'] * validation_scale_count[msid.upper()], 'quant': None, } valid_viols.append(viol) logger.info( 'WARNING: %s %d discrete diffs exceed limit of %d' % (msid, plot['diff_count'], plot['n_changes'] * validation_scale_count[msid.upper()])) # Make quantiles if (msid != 'obsid'): quant_line = "%s" % msid for quant in quantiles: quant_val = diff[(len(diff) * quant) // 100] plot['quant%02d' % quant] = FMTS[msid] % quant_val quant_line += (',' + FMTS[msid] % quant_val) quant_table += quant_line + "\n" for histscale in ('lin', 'log'): fig = plt.figure(20 + fig_id, figsize=(4, 3)) fig.clf() ax = fig.gca() ax.hist(diff / scale, bins=50, log=(histscale == 'log')) ax.set_title(msid.upper() + ' residuals: telem - cmd states', fontsize=11) ax.set_xlabel(LABELS[msid]) fig.subplots_adjust(bottom=0.18) plt.tight_layout() filename = '%s_valid_hist_%s.png' % (msid, histscale) outfile = os.path.join(outdir, filename) logger.info('Writing plot file %s' % outfile) fig.savefig(outfile) plot['hist' + histscale] = filename plots_validation.append(plot) filename = os.path.join(outdir, 'validation_quant.csv') logger.info('Writing quantile table %s' % filename) f = open(filename, 'w') f.write(quant_table) f.close() # If run_start_time is specified this is likely for regression testing # or other debugging. In this case write out the full predicted and # telemetered dataset as a pickle. if opt.run_start_time: filename = os.path.join(outdir, 'validation_data.pkl') logger.info('Writing validation data %s' % filename) f = open(filename, 'w') pickle.dump({'pred': pred, 'tlm': tlm}, f, protocol=-1) f.close() valid_viols.extend(make_validation_viols(plots_validation)) if len(valid_viols) > 0: # generate daily plot url if outdir in expected year/day format daymatch = re.match('.*(\d{4})/(\d{3})', opt.outdir) if daymatch: url = os.path.join(URL, daymatch.group(1), daymatch.group(2)) logger.info('validation warning(s) at %s' % url) else: logger.info('validation warning(s) in output at %s' % opt.outdir) write_index_rst(opt, proc, plots_validation, valid_viols) rst_to_html(opt, proc)
plt.tight_layout() #plt.subplots_adjust(left=0.16, bottom=0.14) plt.grid(linestyle='--') plt.show() plt.savefig(os.path.join(opt.outdir, label + '_hist_%s.png' % opt.root)) if 1: plt.figure(2, figsize=(8, 2.75)) for label, rates in (('roll', roll_rates), ('pitch', pitch_rates), ('yaw', yaw_rates)): print('Making', label, 'time plots') plt.clf() plot_cxctime(times, rates, '.', markersize=2, mew=0, color='blue', alpha=.20) plt.ylim(-4, 4) plt.yticks(np.arange(-4, 5)) plt.title(label.capitalize() + ' rates {0}'.format(time_range)) plt.ylabel('Rate (arcsec/sec)') ax = plt.gca() ax.set_axisbelow(False) plt.grid(linestyle='--') plt.show() plt.savefig(os.path.join(opt.outdir, label + '_time_%s.png' % opt.root))
P_vals=P_vals) heat = mdl.add(xija.HeatSink, pin1at, T=T_e, tau=tau_e) # pow = mdl.add(xija.AcisPsmcPower, pdeaat, k=k) fep_count = mdl.add(xija.CmdStatesData, u'fep_count') ccd_count = mdl.add(xija.CmdStatesData, u'ccd_count') vid_board = mdl.add(xija.CmdStatesData, u'vid_board') clocking = mdl.add(xija.CmdStatesData, u'clocking') pow = mdl.add(xija.AcisDpaStatePower, pdeaat, fep_count=fep_count, ccd_count=ccd_count, vid_board=vid_board, clocking=clocking) mdl.make() mdl.calc() mdl.write('psmc_classic.json') psmc = asciitable.read('models_dev/psmc/out_2010103_2010124/temperatures.dat') figure(1) clf() plot_cxctime(pdeaat.times, pdeaat.mvals, 'b') plot_cxctime(pdeaat.times, pdeaat.dvals, 'r') plot_cxctime(psmc['time'], psmc['1pdeaat'], 'g') figure(2) plot_cxctime(pin1at.times, pin1at.mvals, 'b') plot_cxctime(pin1at.times, pin1at.dvals, 'r') plot_cxctime(psmc['time'], psmc['1pin1at'], 'g')
gyr['aogyrct1'].vals, gyr['aogyrct2'].vals, gyr['aogyrct3'].vals, gyr['aogyrct4'].vals ]) raw_times = (gyr['aogyrct1'].times[1:] + gyr['aogyrct1'].times[:-1]) / 2 delta_times = gyr['aogyrct1'].times[1:] - gyr['aogyrct1'].times[:-1] delta_cts = cts[:, 1:] - cts[:, :-1] raw_rates = np.dot(cts2rate, delta_cts) * 0.02 / delta_times # Plot the OBC rates figure(1, figsize=(8, 6)) clf() for frame, msid, label in ((1, 'aorate1', 'roll'), (2, 'aorate2', 'pitch'), (3, 'aorate3', 'yaw')): subplot(3, 1, frame) obc_rates = obc[msid].vals * 206254. plot_cxctime(obc[msid].times, obc_rates, '-') plot_cxctime(obc[msid].times, Ska.Numpy.smooth(obc_rates, window_len=20), '-r') ylim(average(obc_rates) + array([-1.5, 1.5])) title(label.capitalize() + ' rate (arcsec/sec)') subplots_adjust(bottom=0.12, top=0.90) # savefig('obc_rates_' + dur + '.png') # Plot the S/C rates from raw gyro data figure(2, figsize=(8, 6)) clf() for axis, label in ((0, 'roll'), (1, 'pitch'), (2, 'yaw')): subplot(3, 1, 1 + axis) raw_rate = raw_rates[axis, :] plot_cxctime(raw_times, raw_rate, '-')
dat = dat[dat['r2_c0'] != 410.0] dat = dat[dat['r0_c6'] != 235.0] dat = dat[dat['r0_c7'] != 217.0] dat = dat[dat['time'] > start.secs] dat['dt'] = dat['time'] - dat['time'][0] integ = dat['INTEG'] ccdfig = plt.figure("ccdplot") ccdax = plt.gca() if ccdax.lines: ccdline = ccdax.lines[0] ccdline.set_data(cxctime2plotdate(dat['time']), dat['TEMPCD']) ccdax.relim() ccdax.autoscale_view() else: plot_cxctime(dat['time'], dat['TEMPCD'], 'b.', ax=ccdax) #for colname in colnames: # dat[colname] = median_filter(dat[colname], 5) maxes = [np.max(median_filter(dat[colname], 5)) for colname in colnames] i_brightest = np.argsort(maxes)[-opt.n_brightest:] cols = [] for i, colname in enumerate(colnames): if i in i_brightest: cols.append(dat[colname]) i_col = 0 fits = {} for r in range(N): for c in range(N):
def draw_plot(self): msid = self.msid for _ in range(len(self.ax.lines)): self.ax.lines.pop() # Force manual y scaling scaley = self.scaley if scaley: ymin = None ymax = None ok = ((msid.times >= self.tstart) & (msid.times <= self.tstop)) try: self.ax.callbacks.disconnect(self.xlim_callback) except AttributeError: pass if self.plot_mins and hasattr(self.msid, 'mins'): plot_cxctime(msid.times, msid.mins, self.fmt_minmax, ax=self.ax, fig=self.fig, **self.plot_kwargs) plot_cxctime(msid.times, msid.maxes, self.fmt_minmax, ax=self.ax, fig=self.fig, **self.plot_kwargs) if scaley: ymin = np.min(msid.mins[ok]) ymax = np.max(msid.maxes[ok]) vals = msid.raw_vals if msid.state_codes else msid.vals plot_cxctime(msid.times, vals, self.fmt, ax=self.ax, fig=self.fig, state_codes=msid.state_codes, **self.plot_kwargs) if scaley: plotvals = vals[ok] if ymin is None: ymin = np.min(plotvals) if ymax is None: ymax = np.max(plotvals) dy = (ymax - ymin) * 0.05 if dy == 0.0: dy = min(ymin + ymax, 1e-12) * 0.05 self.ax.set_ylim(ymin - dy, ymax + dy) self.ax.set_title('{} {}'.format(msid.MSID, msid.stat or '')) if msid.unit: self.ax.set_ylabel(msid.unit) # Update the image object with our new data and extent self.ax.figure.canvas.draw_idle() self.xlim_callback = self.ax.callbacks.connect('xlim_changed', self.xlim_changed)
# Use MSID values from telemetry to initialize if available model.comp['1pdeaat'].set_data(20.0) model.comp['pin1at'].set_data(20.0) ## INPUT DATA COMPONENTS # These initializations are used needed for predicting into the future. # For analyzing back-orbit data, do not set any of these and let xija # grab the right values from telemetry. # All the usual values here model.comp['pitch'].set_data(130) model.comp['sim_z'].set_data(75000) model.comp['ccd_count'].set_data(6) model.comp['fep_count'].set_data(6) model.comp['vid_board'].set_data(1) model.comp['clocking'].set_data(1) model.comp['dpa_power'].set_data(0.0) # Detector housing heater. Set to True for heater ON, False for heater OFF. model.comp['dh_heater'].set_data(True) model.make() model.calc() # Note the telemetry MSID is fptemp_11 but the Node name is fptemp pdeaat = fetch_eng.Msid('1pdeaat', start, stop) # DEGC plot_cxctime(model.times, model.comp['1pdeaat'].mvals, 'r-') plot_cxctime(pdeaat.times, pdeaat.vals, 'b-')
def main(): global opt opt, args = get_options() tstart = DateTime(opt.tstart).secs tstop = DateTime(opt.tstop).secs # Get orbital ephemeris in requested time range print('Fetching ephemeris') ephem_x = fetch.MSID('orbitephem0_x', opt.tstart, opt.tstop) ephem_y = fetch.MSID('orbitephem0_y', opt.tstart, opt.tstop) ephem_z = fetch.MSID('orbitephem0_z', opt.tstart, opt.tstop) ephem_times = ephem_x.times.copy() # Get spacecraft attitude in requested time range at the same sampling as ephemeris print('Fetching attitude telemetry between {0} and {1}'.format( opt.tstart, opt.tstop)) qatts = fetch.MSIDset(['aoattqt1', 'aoattqt2', 'aoattqt3', 'aoattqt4'], opt.tstart, opt.tstop) #cols, atts = fetch(start=ephem.Time[0], stop=ephem.Time[-1], dt=dt, time_format='secs', # colspecs=) # atts = np.rec.fromrecords(atts, names=cols) q1s = qatts['aoattqt1'].vals[::opt.sample] q2s = qatts['aoattqt2'].vals[::opt.sample] q3s = qatts['aoattqt3'].vals[::opt.sample] q4s = qatts['aoattqt4'].vals[::opt.sample] q_times = qatts['aoattqt1'].times[::opt.sample] ephem_x_vals = Ska.Numpy.interpolate(ephem_x.vals, ephem_times, q_times) ephem_y_vals = Ska.Numpy.interpolate(ephem_y.vals, ephem_times, q_times) ephem_z_vals = Ska.Numpy.interpolate(ephem_z.vals, ephem_times, q_times) chandra_ecis = np.array([ephem_x_vals, ephem_y_vals, ephem_z_vals]).copy().transpose() if opt.movie: if len(atts) > 250: print "Error: movie option will produce more than 250 images. Change code if needed." sys.exit(0) if not os.path.exists(opt.out): os.makedirs(opt.out) # Divy up calculations amongst the n-processors i0s = range(0, len(q1s), len(q1s) // opt.nproc + 1) i1s = i0s[1:] + [len(q1s)] t0 = time.time() # Calculate illumination in a separate process over each sub-interval queues = [] procs = [] for iproc, i0, i1 in zip(itertools.count(), i0s, i1s): queue = Queue() proc = Process(target=calc_vis_values, args=(queue, iproc, q_times[i0:i1], chandra_ecis[i0:i1], q1s[i0:i1], q2s[i0:i1], q3s[i0:i1], q4s[i0:i1])) proc.start() procs.append(proc) queues.append(queue) # Join the results from each processor at the end outvals = [] for proc, queue in zip(procs, queues): outvals.extend(queue.get()) proc.join() print print 'calc_esa:', time.time() - t0 t0 = time.time() esa_directs = np.ndarray(len(q_times)) esa_refls = np.ndarray(len(q_times)) for i, t, q1, q2, q3, q4, x, y, z in zip(itertools.count(), q_times, q1s, q2s, q3s, q4s, ephem_x_vals, ephem_y_vals, ephem_z_vals): direct, refl, total = Chandra.acis_esa.earth_solid_angle( Quaternion.Quat([q1, q2, q3, q4]), np.array([x, y, z])) esa_directs[i] = direct esa_refls[i] = refl print 'calc_esa:', time.time() - t0 # Plot illumination versus date fig = plt.figure(1, figsize=(6, 4)) plt.clf() illum = np.rec.fromrecords( outvals, names=['time', 'direct', 'reflect', 'alt', 'q1', 'q2', 'q3', 'q4']) ticklocs, fig, ax = plot_cxctime(illum.time, illum.direct + illum.reflect, '-b') # plot_cxctime(illum.time, illum.reflect, '-r') # plot_cxctime(illum.time, illum.direct, '-r') # plot_cxctime(q_times, esa_directs, '-c') # plot_cxctime(q_times, esa_refls, '-m') plot_cxctime(q_times, esa_directs + esa_refls, '-r') ax.set_title('ACIS radiator illumination') ax.set_ylabel('Illumination (steradians)') filename = opt.out + '.png' fig.savefig(filename) print 'Create image file', filename # Write results to FITS table filename = opt.out + '.fits' Ska.Table.write_fits_table(opt.out + '.fits', illum) print 'Created FITS table', filename if opt.movie: print 'To make a movie run the following command:' print 'convert -delay 30 %s/*.png -loop 0 %s.gif' % (opt.out, opt.out)