Beispiel #1
0
 def get_updated_dsn_comms(self):
     dsnfile = "/data/acis/dsn_summary.dat"
     if os.path.getsize(dsnfile) == 0:
         mylog.warning("DSN summary file is empty. Ignoring.")
         return
     tstart = date2secs(self.first_time)
     tstop = date2secs(self.last_time)
     bots = []
     eots = []
     new_durations = []
     with open(dsnfile) as f:
         for line in f.readlines()[2:]:
             words = line.strip().split()
             bot = datetime.strptime(
                 "%s:%s:00:00:00" % (words[-4], words[-3].split(".")[0]),
                 "%Y:%j:%H:%M:%S")
             eot = datetime.strptime(
                 "%s:%s:00:00:00" % (words[-2], words[-1].split(".")[0]),
                 "%Y:%j:%H:%M:%S")
             time_bot = date2secs(bot.strftime(
                 "%Y:%j:%H:%M:%S")) + 86400.0 * (float(words[-3]) % 1)
             time_eot = date2secs(eot.strftime(
                 "%Y:%j:%H:%M:%S")) + 86400.0 * (float(words[-1]) % 1)
             new_durations.append((time_eot - time_bot) / 60.0)
             if tstart <= time_bot <= tstop:
                 bots.append(time_bot)
             if tstart <= time_eot <= tstop:
                 eots.append(time_eot)
     self.events["comm_begins"]["times"] = secs2date(bots)
     self.events["comm_ends"]["times"] = secs2date(eots)
     self.lines, self.line_times = self._fix_comm_times(
         self.lines, self.line_times, new_durations)
Beispiel #2
0
 def argmin(self, dates=False):
     idx = np.argmin(self.value)
     times = self.times[idx]
     if dates:
         return secs2date(times)
     else:
         return times
Beispiel #3
0
    def write_temps(self, outdir, times, temps):
        """
        Write the states record array to the file "temperatures.dat"
        and the Earth solid angles to "earth_solid_angles.dat".

        Parameters
        ----------
        outdir : string
            The directory the file will be written to.
        times : NumPy array
            Times in seconds from the start of the mission
        temps : NumPy array
            Temperatures in Celsius
        """
        super(ACISFPCheck, self).write_temps(outdir, times, temps)
        outfile = os.path.join(outdir, 'earth_solid_angles.dat')
        mylog.info('Writing Earth solid angles to %s' % outfile)
        e = self.predict_model.comp['earthheat__fptemp'].dvals
        efov_table = Table([times, secs2date(times), e],
                           names=['time', 'date', 'earth_solid_angle'],
                           copy=False)
        efov_table['time'].format = '%.2f'
        efov_table['earth_solid_angle'].format = '%.3e'
        efov_table.write(outfile,
                         format='ascii',
                         delimiter='\t',
                         overwrite=True)
Beispiel #4
0
 def _get_msids(self, model, comps, tl_file):
     comps = [comp.lower() for comp in comps]
     times = model[comps[0]].times.value
     tstart = secs2date(times[0] - 700.0)
     tstop = secs2date(times[-1] + 700.0)
     if tl_file is not None:
         msids = MSIDs.from_tracelog(tl_file, tbegin=tstart, tend=tstop)
     else:
         if "earth_solid_angle" in comps:
             comps.remove("earth_solid_angle")
         comps.append("ccsdstmf")
         msids = MSIDs.from_database(comps, tstart, tstop=tstop, filter_bad=True,
                                     interpolate='nearest', interpolate_times=times)
         if msids[comps[0]].times.size != times.size:
             raise RuntimeError("Lengths of time arrays for model data and MSIDs "
                                "do not match. You probably ran a model past the "
                                "end date in the engineering archive!")
     return msids
Beispiel #5
0
 def write_prediction(self, filename, predict_times, predict_data):
     from astropy.table import Table
     temp_table = Table(
         [predict_times,
          secs2date(predict_times), predict_data],
         names=['time', 'date', self.msid.lower()],
         copy=False)
     temp_table['time'].format = '%.2f'
     temp_table[self.msid.lower()].format = '%.2f'
     temp_table.write(filename,
                      format='ascii',
                      delimiter='\t',
                      overwrite=True)
Beispiel #6
0
    def _add_annotations(self, plot, annotations, tbegin, tend):
        for i, line in enumerate(plot.ax.lines):
            line.set_zorder(100 - i)
        plot_comms = False
        plot_belts = False
        if "cti_runs" in annotations:
            annotations.append("start_cti")
            annotations.append("end_cti")
            annotations.remove("cti_runs")
        for key in annotations:
            if key == "comms":
                plot_comms = True
                continue
            if key == "belts":
                plot_belts = True
                continue
            color = colors[key]
            ls = styles[key]
            for i, t in enumerate(self.events[key]["times"]):
                tt = date2secs(t)
                if tt < tbegin or tt > tend:
                    continue
                plot.add_vline(t, color=color, ls=ls)
                if "state" in self.events[key] and key in offsets:
                    text = self.events[key]["state"][i]
                    if isinstance(text, tuple):
                        text = text[-1]
                    tdt = secs2date(tt + 1800.0)
                    ymin, ymax = plot.ax.get_ylim()
                    y = (1.0 - offsets[key]) * ymin + offsets[key] * ymax
                    plot.add_text(tdt,
                                  y,
                                  text,
                                  fontsize=15,
                                  rotation='vertical',
                                  color=color,
                                  zorder=100)

        if plot_belts:
            self._plot_bands(tbegin,
                             tend,
                             plot, ["radmon_disable", "radmon_enable"],
                             "mediumpurple",
                             alpha=0.333333)

        if plot_comms:
            self._plot_bands(tbegin,
                             tend,
                             plot, ["comm_begins", "comm_ends"],
                             "pink",
                             alpha=1.0)
Beispiel #7
0
    def write_temps(self, outdir, times, temps):
        """
        Write the states record array to the file "temperatures.dat".

        Parameters
        ----------
        outdir : string
            The directory the file will be written to.
        times : NumPy array
            Times in seconds from the start of the mission
        temps : NumPy array
            Temperatures in Celsius
        """
        outfile = os.path.join(outdir, 'temperatures.dat')
        mylog.info('Writing temperatures to %s' % outfile)
        T = temps[self.name]
        temp_table = Table([times, secs2date(times), T],
                           names=['time', 'date', self.msid],
                           copy=False)
        temp_table['time'].format = '%.2f'
        temp_table[self.msid].format = '%.2f'
        temp_table.write(outfile, format='ascii', delimiter='\t')
Beispiel #8
0
    def write_temps(self, outdir, times, temps):
        """
        Write the states record array to the file "temperatures.dat"
        and the Earth solid angles to "earth_solid_angles.dat".

        Parameters
        ----------
        outdir : string
            The directory the file will be written to.
        times : NumPy array
            Times in seconds from the start of the mission
        temps : NumPy array
            Temperatures in Celsius
        """
        super(ACISFPCheck, self).write_temps(outdir, times, temps)
        outfile = os.path.join(outdir, 'earth_solid_angles.dat')
        mylog.info('Writing Earth solid angles to %s' % outfile)
        e = self.predict_model.comp['earthheat__fptemp'].dvals
        efov_table = Table([times, secs2date(times), e],
                           names=['time', 'date', 'earth_solid_angle'],
                           copy=False)
        efov_table['time'].format = '%.2f'
        efov_table['earth_solid_angle'].format = '%.3e'
        efov_table.write(outfile, format='ascii', delimiter='\t')
Beispiel #9
0
    def plot(self,
             fields,
             field2=None,
             lw=1.5,
             fontsize=18,
             color=None,
             color2='magenta',
             figsize=(10, 8),
             plot=None,
             tbegin=None,
             tend=None,
             annotations=None,
             ymin=None,
             ymax=None,
             ymin2=None,
             ymax2=None):
        """
        Plot temperature and state data from a load review.

        Parameters
        ----------
        fields : tuple of strings or list of tuples of strings
            A single field or list of fields to plot on the left y-axis.
        field2 : tuple of strings, optional
            A single field to plot on the right y-axis. Default: None
        lw : float, optional
            The width of the lines in the plots. Default: 1.5 px.
        fontsize : integer, optional
            The font size for the labels in the plot. Default: 18 pt.
        color : list of strings, optional
            The color for the lines plotted on the left y-axis.
            Default: ["blue", "red", "green", "black"]
        color2 : string, optional
            The color for the line plotted on the right y-axis.
            Default: "magenta"
        figsize : tuple of integers, optional
            The size of the plot in (width, height) in inches. Default: (10, 8)
        plot : :class:`~acispy.plots.DatePlot` or :class:`~acispy.plots.CustomDatePlot`, optional
            An existing DatePlot to add this plot to. Default: None, one 
            will be created if not provided.
        tbegin : string, float, or DateTime object, optional
            The start time of the plot. Default is to plot from the
            beginning of the load. 
        tend : string, float, or DateTime object, optional
            The end time of the plot. Default is to plot to the
            ending of the load.
        annotations : list of strings, optional
            Additional annotations to add to the plot. Available options
            are "cti_runs", "comms", "belts", "perigee", "sim_trans",
            and "apogee". Default: None
        ymin : float, optional
            Set the minimum value of the y-axis on the left side of the 
            plot.
        ymax : float, optional
            Set the maximum value of the y-axis on the left side of the 
            plot.
        ymin2 : float, optional
            Set the minimum value of the y-axis on the right side of the 
            plot.
        ymax2 : float, optional
            Set the maximum value of the y-axis on the right side of the 
            plot.
        """
        dp = DatePlot(self.ds,
                      fields,
                      field2=field2,
                      lw=lw,
                      fontsize=fontsize,
                      color=color,
                      color2=color2,
                      figsize=figsize,
                      plot=plot)
        ylimits = dp.ax.get_ylim()
        if ymin is None:
            ymin = ylimits[0]
        if ymax is None:
            ymax = ylimits[1]
        dp.set_ylim(ymin, ymax)
        if field2 is not None:
            ylimits2 = dp.ax2.get_ylim()
            if ymin2 is None:
                ymin2 = ylimits2[0]
            if ymax2 is None:
                ymax2 = ylimits2[1]
            dp.set_ylim2(ymin2, ymax2)
        if tbegin is None:
            tbegin = self.first_time
        if tend is None:
            tend = self.last_time
        tbegin = get_time(tbegin, 'secs')
        tend = get_time(tend, 'secs')
        if annotations is not None:
            self._add_annotations(dp, annotations.copy(), tbegin, tend)
        dp.set_xlim(secs2date(tbegin), secs2date(tend))
        return dp
Beispiel #10
0
 def _populate_event_times(self):
     lines = []
     line_times = []
     time = self.first_time
     comm_durations = []
     with open(self.load_file, "r") as f:
         for i, line in enumerate(f.readlines()):
             words = line.strip().split()
             if len(words) > 0:
                 event = None
                 state = None
                 if line.startswith(self.load_year) or \
                     line.startswith(self.next_year):
                     time = words[0]
                 if "MP_OBSID" in line:
                     event = "obsid_change"
                     state = words[-1]
                 if "SIMTRANS" in line:
                     event = "sim_trans"
                     state = (int(words[-2]), words[-1].strip("()"))
                 if "HETGIN" in line:
                     event = "hetg_in"
                 if "HETGRE" in line:
                     event = "hetg_out"
                 if "LETGIN" in line:
                     event = "letg_in"
                 if "LETGRE" in line:
                     event = "letg_out"
                 if "CSELFMT" in line and "COMMAND_HW" in line:
                     event = "fmt_change"
                     state = int(words[-1][-1])
                 if "EPERIGEE" in line and "ORBPOINT" in line:
                     event = "perigee"
                 if "APOGEE" in line and "ORBPOINT" in line:
                     event = "apogee"
                 if "COMM BEGINS" in line:
                     event = "comm_begins"
                 if "COMM ENDS" in line:
                     event = "comm_ends"
                 if "EEF1000" in line and "ORBPOINT" in line:
                     event = "enter_belts"
                 if "XEF1000" in line and "ORBPOINT" in line:
                     event = "exit_belts"
                 if "OORMPDS" in line and "COMMAND_SW" in line:
                     event = "radmon_disable"
                 if "OORMPEN" in line and "COMMAND_SW" in line:
                     event = "radmon_enable"
                 if event is not None:
                     if event not in self.events:
                         self.events[event] = {"times": []}
                     if event == "comm_ends":
                         time = secs2date(date2secs(words[0]) - 1800.0)
                     self.events[event]["times"].append(time)
                     if state is not None:
                         if "state" not in self.events[event]:
                             self.events[event]["state"] = []
                         self.events[event]["state"].append(state)
                 if "REAL-TIME COMM" in line:
                     continue
                 if "COMM DURATION" in line:
                     comm_durations.append(float(words[-2]) - 30.0)
                     continue
                 if line.startswith(self.load_year) or \
                     line.startswith(self.next_year) or \
                     "WSPOW COMMAND LOADS" in line or \
                     "CHANDRA STATUS ARRAY" in line or \
                     "ACIS integration time" in line or \
                     "requested time" in line or \
                     "ObsID change" in line or \
                     "THERE IS A Z-SIM" in line or \
                     "==> DITHER" in line:
                     lines.append(line)
                     line_times.append(time)
     line_times = date2secs(line_times)
     if len(self.events["comm_begins"]) > 0:
         lines, line_times = self._fix_comm_times(lines, line_times,
                                                  comm_durations)
     return lines, line_times
Beispiel #11
0
 def test_secs2date(self):
     vals = DateTime(['2012:001', '2000:001'])
     self.assertTrue(np.all(secs2date(vals.secs) == vals.date))
Beispiel #12
0
 def test_secs2date(self):
     vals = DateTime(['2012:001', '2000:001'])
     self.assertTrue(np.all(secs2date(vals.secs) == vals.date))
Beispiel #13
0
 def dates(self):
     if self._dates is None:
         self._dates = secs2date(self.times.value)
     return self._dates
Beispiel #14
0
 def dates(self):
     return secs2date(self.times.value)
Beispiel #15
0
    def __init__(self, name, tstart, hours, T_init, pitch, ccd_count,
                 vehicle_load=None, simpos=-99616.0, off_nom_roll=0.0, 
                 dh_heater=0, fep_count=None, clocking=1, q=None, instrument=None,
                 model_spec=None, no_limit=False, no_earth_heat=False):
        if name in short_name_rev:
            name = short_name_rev[name]
        if name == "fptemp_11" and instrument is None:
            raise RuntimeError("Must specify either 'ACIS-I' or 'ACIS-S' in "
                               "'instrument' if you want to test a focal plane " 
                               "temperature prediction!")
        if fep_count is None:
            fep_count = ccd_count
        if q is None and name == "fptemp_11":
            raise RuntimeError("Please supply an attitude quaternion for the focal plane model!")
        self.vehicle_load = vehicle_load
        self.no_limit = no_limit
        tstart = get_time(tstart)
        datestart = tstart
        tstart = DateTime(tstart).secs
        tstop = tstart+hours*3600.0+10012.0
        datestop = secs2date(tstop)
        tend = tstop+0.5*(tstop-tstart)
        dateend = secs2date(tend)
        self.datestart = datestart
        self.datestop = datestop
        self.hours = hours
        self.tstart = Quantity(tstart, "s")
        self.tstop = Quantity(tstop, "s")
        self.dateend = dateend
        self.T_init = Quantity(T_init, "deg_C")
        self.instrument = instrument
        self.no_earth_heat = no_earth_heat
        if vehicle_load is None:
            states = {"ccd_count": np.array([ccd_count], dtype='int'),
                      "fep_count": np.array([fep_count], dtype='int'),
                      "clocking": np.array([clocking], dtype='int'),
                      'vid_board': np.array([ccd_count > 0], dtype='int'),
                      "pitch": np.array([pitch]),
                      "simpos": np.array([simpos]),
                      "datestart": np.array([self.datestart]),
                      "datestop": np.array([self.dateend]),
                      "tstart": np.array([self.tstart.value]),
                      "tstop": np.array([tend]),
                      "hetg": np.array(["RETR"]),
                      "letg": np.array(["RETR"]),
                      "off_nom_roll": np.array([off_nom_roll]),
                      "dh_heater": np.array([dh_heater], dtype='int')}
            # For the focal plane model we need a quaternion.
            if name == "fptemp_11":
                for i in range(4):
                    states["q%d" % (i+1)] = np.array([q[i]])
        else:
            mylog.info("Modeling a %d-chip observation concurrent with " % ccd_count +
                       "the %s vehicle loads." % vehicle_load)
            states = dict((k, state.value) for (k, state) in
                          States.from_load_page(vehicle_load).table.items())
            ecs_run_idxs = states["tstart"] < tstop
            states["ccd_count"][ecs_run_idxs] = ccd_count
            states["fep_count"][ecs_run_idxs] = fep_count
            states["clocking"][ecs_run_idxs] = clocking
            states["vid_board"][ecs_run_idxs] = ccd_count > 0
        super(SimulateSingleObs, self).__init__(name, datestart, dateend, states,
                                                T_init, model_spec=model_spec,
                                                get_msids=False, no_eclipse=True)

        mylog.info("Run Parameters")
        mylog.info("--------------")
        mylog.info("Start Datestring: %s" % datestart)
        mylog.info("Length of ECS run in hours: %s" % hours)
        mylog.info("Stop Datestring: %s" % datestop)
        mylog.info("Initial Temperature: %g degrees C" % T_init)
        mylog.info("CCD Count: %d" % ccd_count)
        mylog.info("FEP Count: %d" % fep_count)
        if vehicle_load is None:
            disp_pitch = pitch
            disp_roll = off_nom_roll
        else:
            pitches = states["pitch"][ecs_run_idxs]
            rolls = states["off_nom_roll"][ecs_run_idxs]
            disp_pitch = "Min: %g, Max: %g" % (pitches.min(), pitches.max())
            disp_roll = "Min: %g, Max: %g" % (rolls.min(), rolls.max())
        mylog.info("Pitch: %s" % disp_pitch)
        mylog.info("SIM Position: %g" % simpos)
        mylog.info("Off-nominal Roll: %s" % disp_roll)
        mylog.info("Detector Housing Heater: %s" % {0: "OFF", 1: "ON"}[dh_heater])

        mylog.info("Model Result")
        mylog.info("------------")

        if self.name == "fptemp_11":
            limit = limits[self.name][instrument]
            margin = 0.0
        else:
            limit = limits[self.name]
            margin = margins[self.name]
        if self.name in low_limits:
            self.low_limit = Quantity(low_limits[self.name], "deg_C")
        else:
            self.low_limit = None
        self.limit = Quantity(limit, "deg_C")
        self.margin = Quantity(margin, 'deg_C')
        self.limit_time = None
        self.limit_date = None
        self.duration = None
        self.violate = False
        if self.no_limit:
            return
        viols = self.mvals.value > self.limit.value
        if np.any(viols):
            idx = np.where(viols)[0][0]
            self.limit_time = self.times('model', self.name)[idx]
            self.limit_date = secs2date(self.limit_time)
            self.duration = Quantity((self.limit_time.value-tstart)*0.001, "ks")
            msg = "The limit of %g degrees C will be reached at %s, " % (self.limit.value, self.limit_date)
            msg += "after %g ksec." % self.duration.value
            mylog.info(msg)
            if self.limit_time < self.tstop:
                self.violate = True
                viol_time = "before"
            else:
                self.violate = False
                viol_time = "after"
            mylog.info("The limit is reached %s the end of the observation." % viol_time)
        else:
            mylog.info("The limit of %g degrees C is never reached." % self.limit.value)

        if self.violate:
            mylog.warning("This observation is NOT safe from a thermal perspective.")
        else:
            mylog.info("This observation is safe from a thermal perspective.")
Beispiel #16
0
def find_text_time(time, hours=1.0):
    return secs2date(date2secs(time)+hours*3600.0)