Esempio n. 1
0
 def __init__(self, tstart, tstop, msids, recent_source="maude",
              filter_bad=False, stat='5min', user=None, password=None, 
              get_states=True, state_keys=None):
     msids = ensure_list(msids)
     tstart = get_time(tstart, fmt='secs')
     tstop = get_time(tstop, fmt='secs')
     tmid = 1.0e99
     for msid in msids:
         tm = fetch.get_time_range(msid, format="secs")[-1]
         tmid = min(tmid, tm)
     tmid = get_time(tmid, fmt='secs')
     if tmid < tstop:
         msids1 = MSIDs.from_database(msids, tstart, tstop=tmid,
                                      filter_bad=filter_bad, stat=stat)
         if recent_source == "maude":
             msids2 = MSIDs.from_maude(msids, tmid, tstop=tstop, user=user,
                                       password=password)
         elif recent_source == "tracelog":
             msids2 = _parse_tracelogs(tmid, tstop,
                                       ["/data/acis/eng_plots/acis_eng_10day.tl",
                                        "/data/acis/eng_plots/acis_dea_10day.tl"],
                                       None)
         msids = ConcatenatedMSIDs(msids1, msids2)
     else:
         msids = MSIDs.from_database(msids, tstart, tstop=tstop,
                                     filter_bad=filter_bad, stat=stat)
     if get_states:
         states = States.from_kadi_states(tstart, tstop,
                                          state_keys=state_keys)
     else:
         states = EmptyTimeSeries()
     model = EmptyTimeSeries()
     super(TelemData, self).__init__(msids, states, model)
Esempio n. 2
0
    def from_states_file(cls, name, states_file, T_init,
                         dt=328.0, model_spec=None, mask_bad_times=False, 
                         ephem_file=None, get_msids=True, no_eclipse=False):
        """
        Run a xija thermal model using a states.dat file. 

        Parameters
        ----------
        name : string
            The name of the model to simulate. Can be "dea", "dpa", "psmc", or "fep1mong".
        states_file : string
            A file containing commanded states, in the same format as "states.dat" which is
            outputted by ACIS thermal model runs for loads.
        T_init : float
            The starting temperature for the model in degrees C.
        model_spec : string, optional
            Path to the model spec JSON file for the model. Default: None, the
            standard model path will be used.
        mask_bad_times : boolean, optional
            If set, bad times from the data are included in the array masks
            and plots. Default: False
        """
        states = States.from_load_file(states_file)
        tstart = get_time(states['tstart'].value[0])
        tstop = get_time(states['tstop'].value[-1])
        return cls(name, tstart, tstop, states=states, T_init=T_init,
                   dt=dt, model_spec=model_spec, mask_bad_times=mask_bad_times,
                   ephem_file=ephem_file, get_msids=get_msids, no_eclipse=no_eclipse)
Esempio n. 3
0
 def from_database(cls, tstart, tstop, state_keys=None, server=None):
     from Chandra.cmd_states import fetch_states
     tstart = get_time(tstart)
     tstop = get_time(tstop)
     if state_keys is not None:
         state_keys = ensure_list(state_keys)
     t = fetch_states(tstart, tstop, vals=state_keys, server=server)
     return cls(t)
Esempio n. 4
0
 def from_kadi(cls, name, tstart, tstop, T_init, get_msids=True, dt=328.0,
               model_spec=None, mask_bad_times=False, ephem_file=None,
               no_eclipse=False, compute_model=None):
     tstart = get_time(tstart)
     tstop = get_time(tstop)
     states = States.from_kadi_states(tstart, tstop)
     return cls(name, tstart, tstop, states=states, T_init=T_init, dt=dt,
                model_spec=model_spec, mask_bad_times=mask_bad_times,
                ephem_file=ephem_file, get_msids=get_msids, no_eclipse=no_eclipse,
                compute_model=compute_model)
Esempio n. 5
0
 def from_kadi_states(cls, tstart, tstop, state_keys=None):
     from kadi.commands import states
     tstart = get_time(tstart)
     tstop = get_time(tstop)
     if state_keys is not None:
         state_keys = ensure_list(state_keys)
     t = states.get_states(tstart,
                           tstop,
                           state_keys=state_keys,
                           merge_identical=True).as_array()
     return cls(t)
Esempio n. 6
0
 def from_commands(cls, tstart, tstop, cmds=None, state_keys=None):
     from kadi import commands
     from kadi.commands import states
     tstart = get_time(tstart)
     tstop = get_time(tstop)
     if cmds is None:
         cmds = commands.get_cmds(tstart, tstop)
     continuity = states.get_continuity(tstart, state_keys)
     t = states.get_states(cmds=cmds,
                           continuity=continuity,
                           state_keys=state_keys,
                           merge_identical=True).as_array()
     return cls(t)
Esempio n. 7
0
 def __init__(self, tstart, tstop, msids, get_states=True, 
              filter_bad=False, stat='5min', state_keys=None, 
              interpolate=None, interpolate_times=None):
     tstart = get_time(tstart)
     tstop = get_time(tstop)
     msids = MSIDs.from_database(msids, tstart, tstop=tstop,
                                 filter_bad=filter_bad, stat=stat,
                                 interpolate=interpolate,
                                 interpolate_times=interpolate_times)
     if get_states:
         states = States.from_kadi_states(tstart, tstop, 
                                          state_keys=state_keys)
     else:
         states = EmptyTimeSeries()
     model = EmptyTimeSeries()
     super(EngArchiveData, self).__init__(msids, states, model)
Esempio n. 8
0
 def __init__(self, tstart, tstop, msids, get_states=True, 
              user=None, password=None, other_msids=None, 
              state_keys=None):
     tstart = get_time(tstart)
     tstop = get_time(tstop)
     msids = MSIDs.from_maude(msids, tstart, tstop=tstop, user=user,
                              password=password)
     if other_msids is not None:
         msids2 = MSIDs.from_database(other_msids, tstart, tstop)
         msids = CombinedMSIDs([msids, msids2])
     if get_states:
         states = States.from_kadi_states(tstart, tstop,
                                          state_keys=state_keys)
     else:
         states = EmptyTimeSeries()
     model = EmptyTimeSeries()
     super(MaudeData, self).__init__(msids, states, model)
Esempio n. 9
0
 def get_states(self, time):
     """
     Get the commanded states at a given *time*.
     """
     time = get_time(time, 'secs')
     state = {}
     for key in self.keys():
         state[key] = self[key][time]
     return state
Esempio n. 10
0
 def from_maude(cls, msids, tstart, tstop=None, user=None, password=None):
     import maude
     tstart = get_time(tstart)
     tstop = get_time(tstop)
     msids = ensure_list(msids)
     msids, derived_msids = check_depends(msids)
     table = {}
     times = {}
     state_codes = {}
     out = maude.get_msids(msids, start=tstart, stop=tstop, user=user,
                           password=password)
     for msid in out["data"]:
         k = msid["msid"].lower()
         table[k] = msid["values"]
         times[k] = msid['times']
         state_codes[k] = get_state_codes(k)
     return cls(table, times, state_codes=state_codes, 
                derived_msids=derived_msids)
Esempio n. 11
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)
Esempio n. 12
0
 def get_values(self, time):
     time = get_time(time, fmt='secs')
     t = Quantity(time, "s")
     values = {}
     for key in self.keys():
         v = Ska.Numpy.interpolate(self[key].value, 
                                   self[key].times.value,
                                   [time], method='linear')[0]
         unit = get_units("model", key)
         values[key] = APQuantity(v, t, unit=unit, dtype=v.dtype)
     return values
Esempio n. 13
0
def _parse_tracelogs(tbegin, tend, filenames, other_msids):
    filenames = ensure_list(filenames)
    if tbegin is not None:
        tbegin = get_time(tbegin)
    if tend is not None:
        tend = get_time(tend)
    msid_objs = []
    for filename in filenames:
        # Figure out what kind of file this is
        f = open(filename, "r")
        line = f.readline()
        f.close()
        if line.startswith("TIME"):
            msids = MSIDs.from_tracelog(filename, tbegin=tbegin, tend=tend)
        elif line.startswith("#YEAR") or line.startswith("YEAR"):
            msids = MSIDs.from_mit_file(filename, tbegin=tbegin, tend=tend)
        else:
            raise RuntimeError("I cannot parse this file!")
        msid_objs.append(msids)
    if other_msids is not None:
        msid_objs.append(MSIDs.from_database(other_msids, tbegin, tend))
    all_msids = CombinedMSIDs(msid_objs)
    return all_msids
Esempio n. 14
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
Esempio n. 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.")
Esempio n. 16
0
    def __init__(self, name, tstart, tstop, states=None, T_init=None,
                 get_msids=True, dt=328.0, model_spec=None,
                 mask_bad_times=False, ephem_file=None, evolve_method=None,
                 rk4=None, tl_file=None, no_eclipse=False, compute_model=None):

        self.name = name.lower()
        self.sname = short_name[name]
        if self.sname in short_name_rev:
            self.model_check = importlib.import_module(f"{self.sname}_check")
        else:
            self.model_check = None

        self.model_spec = find_json(name, model_spec)

        self.ephem_file = ephem_file
 
        tstart = get_time(tstart)
        tstop = get_time(tstop)

        tstart_secs = DateTime(tstart).secs

        self.no_earth_heat = getattr(self, "no_earth_heat", False)

        if states is not None:
            if isinstance(states, States):
                states_obj = states
                states = states.as_array()
            else:
                if "tstart" not in states:
                    states["tstart"] = DateTime(states["datestart"]).secs
                if "tstop" not in states:
                    states["tstop"] = DateTime(states["datestop"]).secs
                num_states = states["tstart"].size
                if "letg" not in states:
                    states["letg"] = np.array(["RETR"]*num_states)
                if "hetg" not in states:
                    states["hetg"] = np.array(["RETR"]*num_states)
                states_obj = States(states)
        else:
            states_obj = EmptyTimeSeries()

        if T_init is None:
            T_init = fetch.MSID(self.name, tstart_secs-700., tstart_secs+700.).vals.mean()

        if compute_model is not None:
            self.xija_model = compute_model(self.name, tstart, tstop, states,
                                            dt, T_init, model_spec, evolve_method, rk4)
        elif self.name in short_name and states is not None:
            self.xija_model = self._compute_acis_model(self.name, tstart, tstop,
                                                       states, dt, T_init, rk4=rk4,
                                                       no_eclipse=no_eclipse,
                                                       evolve_method=evolve_method)
        else:
            self.xija_model = self._compute_model(name, tstart, tstop, dt, T_init,
                                                  evolve_method=evolve_method, 
                                                  rk4=rk4)

        self.bad_times = getattr(self.xija_model, "bad_times", None)
        self.bad_times_indices = getattr(self.xija_model, "bad_times_indices", None)

        if isinstance(states, dict):
            states.pop("dh_heater", None)

        components = [self.name]
        if 'dpa_power' in self.xija_model.comp:
            components.append('dpa_power')
        if 'earthheat__fptemp' in self.xija_model.comp:
            components.append('earthheat__fptemp')
        if states is None:
            components += ["pitch", "roll", "fep_count", "vid_board", "clocking",
                           "ccd_count", "sim_z"]
        masks = {}
        if mask_bad_times and self.bad_times is not None:
            masks[self.name] = np.ones(self.xija_model.times.shape, dtype='bool')
            for (left, right) in self.bad_times_indices:
                masks[self.name][left:right] = False

        model_obj = Model.from_xija(self.xija_model, components, masks=masks)

        if get_msids:
            msids_obj = self._get_msids(model_obj, [self.name], tl_file)
        else:
            msids_obj = EmptyTimeSeries()
        super(ThermalModelRunner, self).__init__(msids_obj, states_obj, model_obj)