Source code for pyrad.io.timeseries

"""
pyrad.io.timeseries
===================

TimeSeries class implementation for holding timeseries data.

.. autosummary::
    :toctree: generated/

    TimeSeries

"""

from datetime import datetime

import numpy as np

from ..graph.plots import plot_histogram
from ..graph.plots_timeseries import plot_timeseries
from ..util.radar_utils import compute_histogram
from ..io.io_aux import get_fieldname_pyart


[docs] class TimeSeries(object): """ Holding timeseries data and metadata. Attributes ---------- description : array of str Description of the data of the time series. time_vector : array of datetime objects timeformat : how to print the time (default: 'Date, UTC [seconds since midnight]' dataseries : List of _dataSeries object holding the data Methods: -------- add_dataseries : Add a data series to the object write : Write time series to a file plot : Plot a figure of a time series """ def __init__( self, desc, timevec=None, timeformat=None, maxlength=None, datatype="" ): """ Initalize the object. Parameters ---------- desc : array of str timevec : array of datetime timeformat : specifies time format maxlength : Maximal length of the time series num_el : Number of values in the time series """ self.description = desc if timevec is None: if maxlength is None: raise Exception( "ERROR: Either 'timevec' or 'maxlength'" " must be defined" ) self.maxlength = maxlength self.time_vector = np.empty(maxlength, dtype=datetime) self.num_el = 0 else: self.time_vector = timevec self.maxlength = timevec.size self.num_el = timevec.size self.timeformat = timeformat self.dataseries = [] self.datatype = datatype
[docs] def add_dataseries( self, label, unit_name, unit, dataseries=None, plot=True, color=None, linestyle=None, ): """ Add a new data series to the timeseries object. The length of the data vector must be the same as the length of the time vector. """ if dataseries is not None: if len(dataseries) != self.num_el: raise Exception( "ERROR: Number of data series sample do " "not correspond to time vector ('%s')" % label ) else: dataseries = np.ma.empty(self.maxlength) ds = _DataSeries( label, unit_name, unit, dataseries, plot=plot, color=color, linestyle=linestyle, ) self.dataseries.append(ds)
[docs] def add_timesample(self, dt, values): """ Add a new sample to the time series. """ if self.num_el + 1 > self.maxlength: # jgr changed from >= raise Exception( "ERROR: Cannot add time series sample. Max" " length reached." ) self.time_vector[self.num_el] = dt for val, ds in zip(values, self.dataseries): ds.set_value(self.num_el, val) self.num_el += 1
[docs] def write(self, fname): """ Write time series output """ print("----- write to '%s'" % fname) try: tsfile = open(fname, "w") except Exception: raise Exception("ERROR: Could not create file '%s'" % fname) print("# Weather radar timeseries data file", file=tsfile) print("# Project: MALSplus", file=tsfile) print( "# Start : %s UTC" % self.time_vector[0].strftime("%Y-%m-%d %H:%M:%S"), file=tsfile, ) print( "# End : %s UTC" % self.time_vector[self.num_el - 1].strftime("%Y-%m-%d %H:%M:%S"), file=tsfile, ) print("# Header lines with comments are preceded by '#'", file=tsfile) for line in self.description: print("# %s" % line, file=tsfile) print("#", file=tsfile) # Make raw header if self.timeformat is None: print("# Date, UTC [seconds since midnight]", end="", file=tsfile) else: print("# Date [%s]" % self.timeformat, end="", file=tsfile) for ds in self.dataseries: print(", %s [%s]" % (ds.label, ds.unit), end="", file=tsfile) print("", file=tsfile) # Store the data for i in range(self.num_el): if self.timeformat is None: dt = self.time_vector[i] daystr = dt.strftime("%d-%b-%Y") secs = ( dt.hour * 3600.0 + dt.minute * 60.0 + dt.second + dt.microsecond / 1000000.0 ) print("%s, %14.4f" % (daystr, secs), end="", file=tsfile) else: print( self.time_vector[i].strftime(self.timeformat), end="", file=tsfile ) for ds in self.dataseries: print( ", %14.4f" % (np.ma.filled(ds.data, fill_value=np.nan)[i]), end="", file=tsfile, ) print("", file=tsfile) tsfile.close()
[docs] def plot(self, fname, ymin=None, ymax=None): """ Make a figure of a time series """ found = False labely = None ds_list = [] color_list = [] lstyle_list = [] for ds in self.dataseries: if ds.plot: found = True ds_list.append(ds.data[: self.num_el]) color_list.append(ds.color) lstyle_list.append(ds.linestyle) if labely is None: labely = "%s [%s]" % (ds.unit_name, ds.unit) if not found: raise Exception("ERROR: Undefined time series '%s'" % ds.label) print("----- plot to '%s'" % fname) title = "Trajectory Time Series %s" % self.time_vector[0].strftime("%Y-%m-%d") plot_timeseries( self.time_vector[: self.num_el], ds_list, [fname], title=title, labels=None, labely=labely, timeformat="%H:%M", colors=color_list, linestyles=lstyle_list, ymin=ymin, ymax=ymax, )
[docs] def plot_hist(self, fname, step=None): """ Make histograms of time series """ for ds in self.dataseries: if ds.plot: bins, values = compute_histogram( ds.data[: self.num_el], get_fieldname_pyart(self.datatype), step=step, ) fname2 = fname.replace(".", "_" + ds.label + ".") plot_histogram( bins, values, [fname2], labelx="%s [%s]" % (ds.unit_name, ds.unit), titl=( "Trajectory Histogram %s" % self.time_vector[0].strftime("%Y-%m-%d") ), ) print("----- plot to '%s'" % fname2)
class _DataSeries(object): """ Hold a data vector and some meta information. """ def __init__( self, label, unit_name, unit, data, plot=True, color=None, linestyle=None ): """ Initalize the object. """ self.label = label self.unit_name = unit_name self.unit = unit self.data = data self.plot = plot self.color = color self.linestyle = linestyle def set_value(self, i, val): """ Append value to array """ self.data[i] = val