def test_lineid(): """Minimal test of plotting line IDs. Note the test of duplicate line labels""" plt.figure() plot_line_ids(np.arange(100), np.random.uniform(size=100), np.linspace(10, 90, 10), ['line{}'.format(ii) for ii in (0, 0, 0, 1, 1, 2, 3, 4, 5, 6)]) plt.savefig('test-lineid.png')
def make_check_plots(outdir, states, times, temps, tstart, tstop, char): """ Make output plots. :param opt: options :param states: commanded states :param times: time stamps (sec) for temperature arrays :param temps: dict of temperatures :param tstart: load start time :rtype: dict of review information including plot file names """ plots = {} # Start time of loads being reviewed expressed in units for plotdate() load_start = cxc2pd([tstart])[0] load_stop = cxc2pd([tstop])[0] # Add labels for obsids id_xs = [cxc2pd([states[0]['tstart']])[0]] id_labels = [str(states[0]['obsid'])] for s0, s1 in zip(states[:-1], states[1:]): if s0['obsid'] != s1['obsid']: id_xs.append(cxc2pd([s1['tstart']])[0]) id_labels.append(str(s1['obsid'])) logger.info('Making temperature check plots') for fig_id, msid in enumerate(('aca',)): temp_ymax = max(char['ccd_temp_red_limit'], np.max(temps)) temp_ymin = min(char['ccd_temp_yellow_limit'], np.min(temps)) plots[msid] = plot_two(fig_id=fig_id + 1, x=times, y=temps, x2=pointpair(states['tstart'], states['tstop']), y2=pointpair(states['pitch']), xlabel='Date', ylabel='Temperature (C)', ylabel2='Pitch (deg)', ylim=(temp_ymin - .05 * (temp_ymax - temp_ymin), temp_ymax + .05 * (temp_ymax - temp_ymin)), ylim2=(40, 180), figsize=(9, 5), ) ax = plots[msid]['ax'] plots[msid]['ax'].axhline(y=char['ccd_temp_yellow_limit'], linestyle='--', color='g', linewidth=2.0) plots[msid]['ax'].axhline(y=char['ccd_temp_red_limit'], linestyle='--', color='r', linewidth=2.0) plt.subplots_adjust(bottom=0.1) pad = 1 lineid_plot.plot_line_ids([cxc2pd([times[0]])[0] - pad, cxc2pd([times[-1]])[0] + pad], [ax.get_ylim()[0], ax.get_ylim()[0]], id_xs, id_labels, box_axes_space=0.12, ax=ax, label1_size=7) plt.tight_layout() plt.subplots_adjust(top=.85) xlims = ax.get_xlim() ylims = ax.get_ylim() pre_rect = matplotlib.patches.Rectangle((xlims[0], ylims[0]), load_start - xlims[0], ylims[1] - ylims[0], alpha=.1, facecolor='black', edgecolor='none') ax.add_patch(pre_rect) post_rect = matplotlib.patches.Rectangle((load_stop, ylims[0]), xlims[-1] - load_stop, ylims[1] - ylims[0], alpha=.1, facecolor='black', edgecolor='none') ax.add_patch(post_rect) filename = MSID_PLOT_NAME[msid] outfile = os.path.join(outdir, filename) logger.info('Writing plot file %s' % outfile) plots[msid]['fig'].savefig(outfile) plots[msid]['filename'] = filename return plots
def main(): """ Generate the Replan Central timeline plot. """ import matplotlib.patches import matplotlib.pyplot as plt from Ska.Matplotlib import plot_cxctime # TODO: refactor this into smaller functions where possible. # Basic setup. Set times and get input states, radzones and comms. now = DateTime('2012:249:00:35:00' if args.test else None) now = DateTime(now.date[:14] + ':00') # truncate to 0 secs start = now - 1.0 stop = start + args.hours / 24.0 states = fetch_states(start, stop, server='/proj/sot/ska/data/cmd_states/cmd_states.h5') radzones = get_radzones() comms = get_comms() # Get the ACIS ops fluence estimate and current 2hr avg flux fluence_date, fluence0 = get_fluence(ACIS_FLUENCE_FILE) if fluence_date.secs < now.secs: fluence_date = now avg_flux = get_avg_flux(ACE_RATES_FILE) # Get the realtime ACE P3 and HRC proxy values over the time range goes_x_times, goes_x_vals = get_goes_x(start.secs, now.secs) p3_times, p3_vals = get_ace_p3(start.secs, now.secs) hrc_times, hrc_vals = get_hrc(start.secs, now.secs) # For testing: inject predefined values for different scenarios if args.test_scenario: p3_vals, avg_flux, fluence0 = get_test_vals( args.test_scenario, p3_times, p3_vals, avg_flux, fluence0) # Compute the predicted fluence based on the current 2hr average flux. fluence_times = np.arange(fluence_date.secs, stop.secs, args.dt) rates = np.ones_like(fluence_times) * max(avg_flux, 0.0) * args.dt fluence = calc_fluence(fluence_times, fluence0, rates, states) zero_fluence_at_radzone(fluence_times, fluence, radzones) # Initialize the main plot figure plt.rc('legend', fontsize=10) fig = plt.figure(1, figsize=(9, 5)) fig.clf() fig.patch.set_alpha(0.0) ax = fig.add_axes(AXES_LOC, axis_bgcolor='w') ax.yaxis.tick_right() ax.yaxis.set_label_position('right') ax.yaxis.set_offset_position('right') ax.patch.set_alpha(1.0) # Plot lines at 1.0 and 2.0 (10^9) corresponding to fluence yellow # and red limits. Also plot the fluence=0 line in black. x0, x1 = cxc2pd([fluence_times[0], fluence_times[-1]]) plt.plot([x0, x1], [0.0, 0.0], '-k') plt.plot([x0, x1], [1.0, 1.0], '--b', lw=2.0) plt.plot([x0, x1], [2.0, 2.0], '--r', lw=2.0) # Draw dummy lines off the plot for the legend lx = [fluence_times[0], fluence_times[-1]] ly = [-1, -1] plot_cxctime(lx, ly, '-k', lw=3, label='None', fig=fig, ax=ax) plot_cxctime(lx, ly, '-r', lw=3, label='HETG', fig=fig, ax=ax) plot_cxctime(lx, ly, '-c', lw=3, label='LETG', fig=fig, ax=ax) # Make a z-valued curve where the z value corresponds to the grating state. x = cxc2pd(fluence_times) y = fluence z = np.zeros(len(fluence_times), dtype=np.int) for state in states: ok = ((state['tstart'] < fluence_times) & (fluence_times <= state['tstop'])) if state['hetg'] == 'INSR': z[ok] = 1 elif state['letg'] == 'INSR': z[ok] = 2 plot_multi_line(x, y, z, [0, 1, 2], ['k', 'r', 'c'], ax) # Plot 10, 50, 90 percentiles of fluence p3_slope = get_p3_slope(p3_times, p3_vals) if p3_slope is not None and avg_flux > 0: p3_fits, p3_samps, fluences = cfd.get_fluences( os.path.join(args.data_dir, 'ACE_hourly_avg.npy')) hrs, fl10, fl50, fl90 = cfd.get_fluence_percentiles( avg_flux, p3_slope, p3_fits, p3_samps, fluences, args.min_flux_samples, args.max_slope_samples) fluence_hours = (fluence_times - fluence_times[0]) / 3600.0 for fl_y, linecolor in zip((fl10, fl50, fl90), ('-g', '-b', '-r')): fl_y = Ska.Numpy.interpolate(fl_y, hrs, fluence_hours) rates = np.diff(fl_y) fl_y_atten = calc_fluence(fluence_times[:-1], fluence0, rates, states) zero_fluence_at_radzone(fluence_times[:-1], fl_y_atten, radzones) plt.plot(x0 + fluence_hours[:-1] / 24.0, fl_y_atten, linecolor) # Set x and y axis limits x0, x1 = cxc2pd([start.secs, stop.secs]) plt.xlim(x0, x1) y0 = -0.45 y1 = 2.55 plt.ylim(y0, y1) id_xs = [] id_labels = [] # Draw comm passes next_comm = None for comm in comms: t0 = DateTime(comm['bot_date']['value']).secs t1 = DateTime(comm['eot_date']['value']).secs pd0, pd1 = cxc2pd([t0, t1]) if pd1 >= x0 and pd0 <= x1: p = matplotlib.patches.Rectangle((pd0, y0), pd1 - pd0, y1 - y0, alpha=0.2, facecolor='r', edgecolor='none') ax.add_patch(p) id_xs.append((pd0 + pd1) / 2) id_labels.append('{}:{}'.format(comm['station']['value'][4:6], comm['track_local']['value'][:9])) if (next_comm is None and DateTime(comm['bot_date']['value']).secs > now.secs): next_comm = comm # Draw radiation zones for rad0, rad1 in radzones: t0 = DateTime(rad0).secs t1 = DateTime(rad1).secs if t0 < stop.secs and t1 > start.secs: if t0 < start.secs: t0 = start.secs if t1 > stop.secs: t1 = stop.secs pd0, pd1 = cxc2pd([t0, t1]) p = matplotlib.patches.Rectangle((pd0, y0), pd1 - pd0, y1 - y0, alpha=0.2, facecolor='b', edgecolor='none') ax.add_patch(p) # Draw now line plt.plot(cxc2pd([now.secs, now.secs]), [y0, y1], '-g', lw=4) id_xs.extend(cxc2pd([now.secs])) id_labels.append('NOW') # Add labels for obsids id_xs.extend(cxc2pd([start.secs])) id_labels.append(str(states[0]['obsid'])) for s0, s1 in zip(states[:-1], states[1:]): if s0['obsid'] != s1['obsid']: id_xs.append(cxc2pd([s1['tstart']])[0]) id_labels.append(str(s1['obsid'])) plt.grid() plt.ylabel('Attenuated fluence / 1e9') plt.legend(loc='upper center', labelspacing=0.15) lineid_plot.plot_line_ids(cxc2pd([start.secs, stop.secs]), [y1, y1], id_xs, id_labels, ax=ax, box_axes_space=0.14, label1_size=10) # Plot observed GOES X-ray rates and limits pd = cxc2pd(goes_x_times) lgoesx = log_scale(goes_x_vals * 1e8) plt.plot(pd, lgoesx, '-m', alpha=0.3, lw=1.5) plt.plot(pd, lgoesx, '.m', mec='m', ms=3) # Plot observed ACE P3 rates and limits lp3 = log_scale(p3_vals) pd = cxc2pd(p3_times) ox = cxc2pd([start.secs, now.secs]) oy1 = log_scale(12000.) plt.plot(ox, [oy1, oy1], '--b', lw=2) oy1 = log_scale(55000.) plt.plot(ox, [oy1, oy1], '--r', lw=2) plt.plot(pd, lp3, '-k', alpha=0.3, lw=3) plt.plot(pd, lp3, '.k', mec='k', ms=3) # Plot observed HRC shield proxy rates and limits pd = cxc2pd(hrc_times) lhrc = log_scale(hrc_vals) plt.plot(pd, lhrc, '-c', alpha=0.3, lw=3) plt.plot(pd, lhrc, '.c', mec='c', ms=3) # Draw SI state times = np.arange(start.secs, stop.secs, 300) state_vals = interpolate_states(states, times) y_si = -0.23 x = cxc2pd(times) y = np.zeros_like(times) + y_si z = np.zeros_like(times, dtype=np.float) # 0 => ACIS z[state_vals['simpos'] < 0] = 1.0 # HRC plot_multi_line(x, y, z, [0, 1], ['c', 'r'], ax) dx = (x1 - x0) * 0.01 plt.text(x1 + dx, y_si, 'HRC/ACIS', ha='left', va='center', size='small') # Draw log scale y-axis on left ax2 = fig.add_axes(AXES_LOC, axis_bgcolor='w', frameon=False) ax2.set_autoscale_on(False) ax2.xaxis.set_visible(False) ax2.set_xlim(0, 1) ax2.set_yscale('log') ax2.set_ylim(np.power(10.0, np.array([y0, y1]) * 2 + 1)) ax2.set_ylabel('ACE flux / HRC proxy / GOES X-ray') ax2.text(-0.015, 2.5e3, 'M', ha='right', color='m', weight='demibold') ax2.text(-0.015, 2.5e4, 'X', ha='right', color='m', weight='semibold') # Draw dummy lines off the plot for the legend lx = [0, 1] ly = [1, 1] ax2.plot(lx, ly, '-k', lw=3, label='ACE') ax2.plot(lx, ly, '-c', lw=3, label='HRC') ax2.plot(lx, ly, '-m', lw=3, label='GOES-X') ax2.legend(loc='upper left', labelspacing=0.15) plt.draw() plt.savefig(os.path.join(args.data_dir, 'timeline.png')) write_states_json(os.path.join(args.data_dir, 'timeline_states.js'), fig, ax, states, start, stop, now, next_comm, fluence, fluence_times, p3_vals, p3_times, avg_flux, hrc_vals, hrc_times)