Example #1
0
 def get_fitting_data(self, start, stop):
     tstart = date2secs(start)
     tstop = date2secs(stop)
     times = self._eng_match_times(tstart, tstop, 328.0)
     msids = [self.msid] + [
         data_map[input] for input in self.inputs if input not in pwr_states
     ]
     msids += ['solarephem0_{}'.format(ax) for ax in "xyz"]
     data = fetch.MSIDset(msids, start, stop, stat='5min', filter_bad=True)
     data.interpolate(times=times)
     msid_vals = Ska.Numpy.smooth(data[self.msid].vals, 10)
     sun_eci = np.array([
         data['solarephem0_x'].vals, data['solarephem0_y'].vals,
         data['solarephem0_z'].vals
     ])
     d_sun = np.sqrt((sun_eci**2).sum(axis=0))
     states = self.get_cmd_states(data.datestart, data.datestop, times)
     combined_dict = {
         'msid_times': times,
         'msid_vals': msid_vals,
         'd_sun': d_sun
     }
     for input in self.inputs:
         if input in data_map:
             combined_dict[input] = data[data_map[input]].vals
         elif input in states.dtype.names:
             combined_dict[input] = states[input]
     return pd.DataFrame(combined_dict)
Example #2
0
 def _get_ephemeris(self, tstart, tstop, times):
     msids = ['orbitephem0_{}'.format(axis) for axis in "xyz"]
     msids += ['solarephem0_{}'.format(axis) for axis in "xyz"]
     ephem = {}
     if self.ephem_file is None:
         e = fetch.MSIDset(msids, tstart - 2000.0, tstop + 2000.0)
         for msid in msids:
             ephem[msid] = Ska.Numpy.interpolate(e[msid].vals, e[msid].times,
                                                 times)
     else:
         e = ascii.read(self.ephem_file)
         msids = ['orbitephem0_{}'.format(axis) for axis in "xyz"]
         idxs = np.logical_and(e["times"] >= tstart - 2000.0,
                               e["times"] <= tstop + 2000.0)
         for msid in msids:
             ephem[msid] = Ska.Numpy.interpolate(e[msid][idxs],
                                                 e["times"][idxs], times)
     return ephem
Example #3
0
 def from_database(cls, msids, tstart, tstop=None, filter_bad=False,
                   stat='5min', interpolate=None, interpolate_times=None):
     tstart = get_time(tstart)
     tstop = get_time(tstop)
     msids = ensure_list(msids)
     msids, derived_msids = check_depends(msids)
     msids = [msid.lower() for msid in msids]
     data = fetch.MSIDset(msids, tstart, stop=tstop, filter_bad=filter_bad,
                          stat=stat)
     table = {}
     times = {}
     state_codes = {}
     masks = {}
     if interpolate is not None:
         if interpolate_times is None:
             # Get the nominal tstart / tstop range
             max_fetch_tstart = max(msid.times[0] for msid in data.values())
             min_fetch_tstop = min(msid.times[-1] for msid in data.values())
             dt = 328.0
             start = DateTime(tstart).secs if tstart else data.tstart
             stop = DateTime(tstop).secs if tstop else data.tstop
             start = max(start, max_fetch_tstart)
             stop = min(stop, min_fetch_tstop)
             interpolate_times = np.arange((stop - start) // dt + 1) * dt + start
         else:
             interpolate_times = DateTime(interpolate_times).secs
     for k, msid in data.items():
         if interpolate is not None:
             indexes = Ska.Numpy.interpolate(np.arange(len(msid.times)),
                                             msid.times, interpolate_times,
                                             method=interpolate, sorted=True)
             times[k.lower()] = interpolate_times
         else:
             indexes = slice(None, None, None)
             times[k.lower()] = data[k].times
         if msid.state_codes:
             state_codes[k] = dict((k, v) for v, k in msid.state_codes)
         table[k.lower()] = msid.vals[indexes]
         if msid.bads is not None:
             masks[k.lower()] = (~msid.bads)[indexes]
     return cls(table, times, state_codes=state_codes, masks=masks,
                derived_msids=derived_msids)
Example #4
0
 def get_fitting_data(self, start, stop):
     msids = [self.msid] + [
         data_map[input]
         for input in self.inputs if input not in acis_states
     ]
     data = fetch.MSIDset(msids, start, stop, stat='5min', filter_bad=True)
     data.interpolate(times=data["DP_PITCH"].times)
     states = self.get_cmd_states(data.datestart, data.datestop,
                                  data[self.msid].times)
     combined_dict = {
         'msid_times': data[self.msid].times,
         'msid_vals': data[self.msid].vals,
         'phase': make_phase(data[self.msid].times)
     }
     for input in self.inputs:
         if input in data_map:
             combined_dict[input] = data[data_map[input]].vals
         elif input in states.dtype.names:
             combined_dict[input] = states[input]
     return combined_dict
Example #5
0
def calc_perigee_map(start='2010:114:20:00:00',
                     stop='2010:117:16:00:00',
                     ngrid=50):
    # Get orbital ephemeris in requested time range
    print('Fetching ephemeris')
    objs = ('orbit', 'lunar', 'solar')
    axes = ('x', 'y', 'z')
    msids = [
        '{0}ephem0_{1}'.format(obj, axis) for obj in objs for axis in axes
    ]
    ephems = fetch.MSIDset(msids, start, stop)
    times = ephems[msids[0]].times.copy()
    n_ephem = len(ephems[msids[0]].vals)
    if any(len(ephems[msid].vals) != n_ephem for msid in msids):
        raise ValueError('Unexpected mismatch in ephemeris telemetry sampling')

    ephem_xyzs = {}
    for obj in ('orbit', 'lunar', 'solar'):
        msids = ('{0}ephem0_{1}'.format(obj, axis) for axis in axes)
        ephem_xyzs[obj] = np.array([ephems[msid].vals for msid in msids])

    illum_maps = []
    illum_idxs = []
    antisun, xs, ys = get_antisun_grid(ngrid)
    antisun_pitches, phis = antisun.img2polar(xs, ys)

    for i_ephem, ephem_xyz in enumerate(ephem_xyzs['orbit'].transpose()):
        # Calculate a grid of attitude vectors centered on the anti-sun line and extending
        # from sun-pitch=180 (center) to sun-pitch=45 (edge).
        orbit_r = np.sqrt(np.sum(ephem_xyzs['orbit'][:, i_ephem]**2))
        if orbit_r > 50000e3:
            continue
        sun_eci = ephem_xyzs['solar'][:,
                                      i_ephem] - ephem_xyzs['orbit'][:,
                                                                     i_ephem]
        att_vecs = antisun.img2eci(xs, ys, sun_eci)
        ras, decs = Ska.quatutil.eci2radec(att_vecs)
        illum_map = np.zeros((ngrid, ngrid), dtype=np.float32)
        print(i_ephem, n_ephem, ephem_xyz)
        for iy in range(ngrid):
            for ix in range(ngrid):
                i_vec = iy * ngrid + ix
                if antisun_pitches[i_vec] < 135:
                    ra, dec = ras[i_vec], decs[i_vec]
                    roll = Ska.Sun.nominal_roll(ra, dec, times[i_ephem])
                    _, att_illums, _ = acis_taco.calc_earth_vis(
                        ephem_xyz, [ra, dec, roll], max_reflect=5)
                    illum = sum(att_illums)
                else:
                    illum = 0.0
                illum_map[iy, ix] = illum
        illum_idxs.append(i_ephem)
        illum_maps.append(illum_map)

    # debug_here()
    return dict(
        illums=np.array(illum_maps),
        illum_idxs=np.array(illum_idxs),
        times=times,
        antisun=antisun,
        ephem_xyzs=ephem_xyzs,
    )
Example #6
0
def make_thermal_plots(
        counter=None,
        fig_save_directory='/proj/web-icxc/htdocs/hrcops/hrcmonitor/plots/'):

    # Fetch all MSIDs
    msids_daily = fetch.Msidset(monitor_temperature_msids,
                                start='2001:001',
                                stat='daily',
                                filter_bad=True)
    msids_5min = fetch.MSIDset(monitor_temperature_msids,
                               start='2001:001',
                               stat='5min',
                               filter_bad=True)

    ave_table = Table(
    )  # Instantiate an empty AstroPy table that we can later sort

    daybin = 100  # The number of days over which we'll compute the rolling average

    all_names = []
    all_means = []
    all_stds = []

    for msid in monitor_temperature_msids:
        mean = np.mean(msids_daily[msid].means[-daybin:]).round(2)
        std = np.std(msids_daily[msid].stds[-daybin:]).round(2)

        all_names.append(msid)
        all_means.append(mean)
        all_stds.append(std)

    ave_table["MSID"] = all_names
    ave_table["{} Day Average".format(daybin)] = all_means
    ave_table["Standard Deviation"] = all_stds

    ave_table.sort("{} Day Average".format(daybin))

    ordered_msidlist = ave_table["MSID"]

    window = 365  # days, i.e. a year
    # Because this funtion will cut off the first 364 datapoints if your window is 365 days
    time_corrector = window - 1

    all_trends = {}

    for msid in ordered_msidlist:
        moving_aves = compute_yearly_average(msids_daily[msid].means, window)
        moving_stds = compute_yearly_average(msids_daily[msid].stds, window)
        all_trends["{}_trend".format(msid)] = moving_aves
        all_trends["{}_stds".format(msid)] = moving_stds

    # Make Figure 1

    # Make this True to ensure the file size is small. Otherwise you're plotting thousands of vector points.
    rasterized = True

    fig, ax = plt.subplots(figsize=(16, 8))

    n_lines = len(ordered_msidlist)
    color_idx = np.linspace(0, 1, n_lines)

    for i, msid in zip(color_idx, ordered_msidlist):

        print('Plotting daily thermals for {}'.format(msid),
              end='\r',
              flush=True)
        # Clear the command line manually
        sys.stdout.write("\033[K")
        ax.plot_date(convert_chandra_time(msids_daily[msid].times),
                     msids_daily[msid].means,
                     '.',
                     alpha=1.0,
                     markersize=2.5,
                     label='{}'.format(msid),
                     color=plt.cm.RdYlBu_r(i),
                     rasterized=rasterized)

        # Draw a large point line where the current data point is
        with fetch.data_source('maude'):
            latest_datapoint = fetch.Msid(msid, start='2020:340')
            ax.plot_date(convert_chandra_time(latest_datapoint.times)[-1],
                         latest_datapoint.vals[-1],
                         markersize=8,
                         color=plt.cm.RdYlBu_r(i),
                         rasterized=rasterized,
                         zorder=4)

    ax.set_ylabel("Temperature (C)", fontsize=10)
    ax.set_xlabel("Date", fontsize=10)
    plt.xticks(fontsize=10)
    plt.yticks(fontsize=10)
    ax.set_ylim(0, 40)

    # ax.set_xlim(dt.date(2018, 10, 6), dt.date(2018, 10, 30))

    if counter is not None:
        ax.set_title(
            'HRC Thermistor MSIDs (Daily Means) | Updated as of {} EST'.format(
                dt.datetime.now().strftime("%Y-%b-%d %H:%M:%S")),
            color='slategray',
            size=10)
    else:
        ax.set_title(
            "HRC Thermistor Temperatures (Daily Averages) Over the Mission Lifetime",
            color='slategray',
            size=6)
    # ax.legend()
    # ax.set_ylim(10, 40)
    ax.legend(prop={'size': 13}, loc='center left', bbox_to_anchor=(1, 0.5))

    # ax.legend(loc=2, prop={'size': 13})

    ax.axvline(dt.datetime.now(pytz.utc), color='gray', alpha=0.5)
    ax.text(dt.datetime.now(pytz.utc),
            ax.get_ylim()[1] + 0.3,
            'Now',
            fontsize=10,
            color='slategray')

    fig.savefig(fig_save_directory + 'thermals.png',
                dpi=300,
                bbox_inches='tight')
    fig.savefig(fig_save_directory + 'thermals.pdf',
                dpi=300,
                bbox_inches='tight')

    plt.close()

    # Make Figure 2

    fetch.data_source.set('cxc')

    fig, ax = plt.subplots(figsize=(17, 8))

    n_lines = len(ordered_msidlist)
    color_idx = np.linspace(0, 1, n_lines)

    for i, msid in zip(color_idx, ordered_msidlist):

        print('Plotting thermal trends for {}'.format(msid),
              end='\r',
              flush=True)
        # Clear the command line manually
        sys.stdout.write("\033[K")

        times = convert_chandra_time(msids_daily[msid].times)
        # ax.plot(all_trends["{}_trend".format(msidname)], lw=3.0, label=msidname, color=plt.cm.coolwarm(i))
        ax.plot_date(times[time_corrector:],
                     all_trends["{}_trend".format(msid)],
                     '-',
                     label='{}'.format(msid),
                     lw=3.0,
                     color=plt.cm.RdYlBu_r(i),
                     rasterized=rasterized)
        ax.fill_between(times[time_corrector:],
                        all_trends["{}_trend".format(msid)] +
                        all_trends["{}_stds".format(msid)],
                        all_trends["{}_trend".format(msid)] -
                        all_trends["{}_stds".format(msid)],
                        facecolor='gray',
                        alpha=0.4)

        # Draw a large point line where the current data point is
        with fetch.data_source('maude'):
            latest_datapoint = fetch.Msid(msid, start='2020:340')
            ax.plot_date(convert_chandra_time(latest_datapoint.times)[-1],
                         latest_datapoint.vals[-1],
                         markersize=8,
                         color=plt.cm.RdYlBu_r(i),
                         rasterized=rasterized,
                         zorder=4)

    ax.legend(prop={'size': 13}, loc='center left', bbox_to_anchor=(1, 0.5))
    # plt.legend(title='title', bbox_to_anchor=(1.05, 1), loc='upper left')

    if counter is not None:
        ax.set_title(
            'Moving Average Thermal Trends | Updated as of {} EST'.format(
                dt.datetime.now().strftime("%Y-%b-%d %H:%M:%S")),
            color='slategray',
            size=10)
    else:
        ax.set_title(
            "HRC Thermistor Temperatures (Moving Averages) Over the Mission Lifetime",
            color='slategray',
            size=6)

    ax.set_ylabel("Temperature (C)", fontsize=10)
    ax.set_xlabel("Date", fontsize=10)

    plt.xticks(fontsize=10)
    plt.yticks(fontsize=10)

    ax.axvline(dt.datetime.now(pytz.utc), color='gray', alpha=0.5)

    ax.text(dt.datetime.now(pytz.utc),
            ax.get_ylim()[1] + 0.3,
            'Now',
            fontsize=10,
            color='slategray')

    ax.set_xlim(dt.datetime(2001, 1, 1), dt.datetime(2022, 1, 1))

    fig.savefig(fig_save_directory + 'thermal_trends.png',
                dpi=300,
                bbox_inches='tight')
    fig.savefig(fig_save_directory + 'thermal_trends.pdf',
                dpi=300,
                bbox_inches='tight')

    plt.close()
Example #7
0
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)