def wind_ts(rq_wind): """ setup a wind timeseries - uses the rq_wind fixture to get the wind values used for conversions - returns a dict with the expected datetime_rq, datetime_uv and time_value_pair objects """ date_times = ([sec_to_date(zero_time())] * len(rq_wind['rq'])) dtv_rq = (np.array(zip(date_times, rq_wind['rq']), dtype=datetime_value_2d).view(dtype=np.recarray)) date_times = ([sec_to_date(zero_time())] * len(rq_wind['uv'])) dtv_uv = (np.array(zip(date_times, rq_wind['uv']), dtype=datetime_value_2d).view(dtype=np.recarray)) date_times = ([zero_time()] * len(rq_wind['uv'])) tv = (np.array(zip(date_times, rq_wind['uv']), dtype=time_value_pair).view(dtype=np.recarray)) print 'Test Case - actual values:' print 'datetime_value_2d: datetime, (r, theta):' print dtv_rq.time print dtv_rq.value print '----------' print 'datetime_value_2d: datetime, (u, v):' print dtv_uv.time print dtv_uv.value print '----------' print 'time_value_pair: time, (u, v):' print tv.time print tv.value.reshape(len(tv.value), -1) return {'dtv_rq': dtv_rq, 'dtv_uv': dtv_uv, 'tv': tv}
def wind_ts(rq_wind): """ setup a wind timeseries - uses the rq_wind fixture to get the wind values used for conversions - returns a dict with the expected datetime_rq, datetime_uv and time_value_pair objects """ date_times = ([sec_to_date(zero_time())] * len(rq_wind['rq'])) dtv_rq = (np.array(zip(date_times, rq_wind['rq']), dtype=datetime_value_2d) .view(dtype=np.recarray)) date_times = ([sec_to_date(zero_time())] * len(rq_wind['uv'])) dtv_uv = (np.array(zip(date_times, rq_wind['uv']), dtype=datetime_value_2d) .view(dtype=np.recarray)) date_times = ([zero_time()] * len(rq_wind['uv'])) tv = (np.array(zip(date_times, rq_wind['uv']), dtype=time_value_pair) .view(dtype=np.recarray)) print 'Test Case - actual values:' print 'datetime_value_2d: datetime, (r, theta):' print dtv_rq.time print dtv_rq.value print '----------' print 'datetime_value_2d: datetime, (u, v):' print dtv_uv.time print dtv_uv.value print '----------' print 'time_value_pair: time, (u, v):' print tv.time print tv.value.reshape(len(tv.value), -1) return {'dtv_rq': dtv_rq, 'dtv_uv': dtv_uv, 'tv': tv}
def test_default_init(): wind = Wind() assert wind.timeseries == np.array([(sec_to_date(zero_time()), [0.0, 0.0])], dtype=datetime_value_2d) assert wind.units == 'mps'
def test_exceptions(wind_ts, invalid_rq): """ test exceptions """ with pytest.raises(ValueError): # incorrect dtype to_time_value_pair(wind_ts['tv'], ts_format.magnitude_direction) with pytest.raises(ValueError): # incorrect format to_time_value_pair(wind_ts['dtv_rq'], -1) to_datetime_value_2d(wind_ts['tv'], -1) with pytest.raises(ValueError): # string input can only be 'r-theta' or 'uv' to_time_value_pair(wind_ts['dtv_rq'], 'magnitude') to_datetime_value_2d(wind_ts['tv'], 'magnitude') # following also raises ValueError. This gives invalid (r,theta) inputs # which are rejected by the transforms.r_theta_to_uv_wind method. # It tests the inner exception is correct with pytest.raises(ValueError): length_of_dim1 = len(invalid_rq['rq']) zero_times = [zero_time()] * length_of_dim1 invalid_dtv_rq = np.array(zip(zero_times, invalid_rq['rq']), dtype=datetime_value_2d) invalid_dtv_rq['value'] = invalid_rq['rq'] to_time_value_pair(invalid_dtv_rq, ts_format.magnitude_direction)
def test_default_init(): wind = Wind() assert wind.timeseries == np.array( [(sec_to_date(zero_time()), [0.0, 0.0])], dtype=datetime_value_2d) assert wind.units == 'mps'
def test_numpy_array(): """ time_utils works for numpy datetime object """ x = np.array([datetime.utcfromtimestamp(time_utils.zero_time())] * 3, dtype="datetime64[s]") xn = _convert(x) assert np.all(x == xn)
def test_datetime_array(): """ test time_utils conversion works for python datetime object """ x = np.array([datetime.utcfromtimestamp(time_utils.zero_time())] * 3, dtype=datetime) xn = _convert(x) assert np.all(time_utils.round_time(x, roundTo=1) == xn)
def test_to_time_value_pair_from_1d(): length_of_dim1 = 4 zero_times = [sec_to_date(zero_time())] * length_of_dim1 rand_data = np.random.uniform(1, 10, length_of_dim1) data = np.array(zip(zero_times, rand_data), dtype=datetime_value_1d) out_tv = to_time_value_pair(data) assert np.all(out_tv['value']['v'] == 0.0) assert np.all(out_tv['value']['u'] == data['value'])
def test_numpy_array(): """ time_utils works for numpy datetime object """ x = np.array([datetime.utcfromtimestamp(zero_time())] * 3, dtype='datetime64[s]') xn = _convert(x) assert np.all(x == xn)
def test_datetime_array(): """ test time_utils conversion works for python datetime object """ x = np.array([datetime.utcfromtimestamp(zero_time())] * 3, dtype=datetime) xn = _convert(x) assert np.all(round_time(x, roundTo=1) == xn)
def __init__(self, wind=None, timeseries=None, past_hours_to_average=3, **kwargs): """ Initializes a running average object from a wind and past hours to average If no wind is given, timeseries gets initialized as: timeseries = np.zeros((1,), dtype=basic_types.datetime_value_2d) units = 'mps' (note: probably should be an error) All other keywords are optional. Optional parameters (kwargs): :param past_hours_to_average: default is 3 """ self.units = 'mps' self.format = 'uv' self._past_hours_to_average = past_hours_to_average self.wind = wind if (wind is None and timeseries is None): mvg_timeseries = np.array([(sec_to_date(zero_time()), [0.0, 0.0])], dtype=basic_types.datetime_value_2d) moving_timeseries = self._convert_to_time_value_pair(mvg_timeseries) else: if wind is not None: moving_timeseries = wind.ossm.create_running_average(self._past_hours_to_average) else: self.wind = Wind(timeseries, units='mps', format='uv') moving_timeseries = self.wind.ossm.create_running_average(self._past_hours_to_average) # print "moving_timeseries" # print moving_timeseries self.ossm = CyTimeseries(timeseries=moving_timeseries) super(RunningAverage, self).__init__(**kwargs)
def __init__(self, wind=None, timeseries=None, past_hours_to_average=3, **kwargs): """ Initializes a running average object from a wind and past hours to average If no wind is given, timeseries gets initialized as: timeseries = np.zeros((1,), dtype=basic_types.datetime_value_2d) units = 'mps' (note: probably should be an error) All other keywords are optional. Optional parameters (kwargs): :param past_hours_to_average: default is 3 """ self.units = 'mps' self.format = 'uv' self._past_hours_to_average = past_hours_to_average self.wind = wind if (wind is None and timeseries is None): mvg_timeseries = np.array([(sec_to_date(zero_time()), [0.0, 0.0])], dtype=basic_types.datetime_value_2d) moving_ts = self._convert_to_time_value_pair(mvg_timeseries) elif wind is not None: moving_ts = (wind.ossm .create_running_average(self._past_hours_to_average)) else: self.wind = Wind(timeseries, units='mps', coord_sys='uv') moving_ts = (self.wind.ossm .create_running_average(self._past_hours_to_average)) self.ossm = CyTimeseries(timeseries=moving_ts) super(RunningAverage, self).__init__(**kwargs)
def __init__(self, timeseries=None, filename=None, format='uv'): """ Initializes a timeseries object from either a timeseries or datafile containing the timeseries. If both timeseries and file are given, it will read data from the file If neither are given, timeseries gets initialized as: timeseries = np.zeros((1,), dtype=basic_types.datetime_value_2d) If user provides timeseries, the default format is 'uv'. The C++ stores the data in 'uv' format - transformations are done in this Python code (set_timeseries(), get_timeseries()). C++ code only transforms the data from 'r-theta' to 'uv' format if data is read from file. And this happens during initialization because C++ stores data in 'uv' format internally. Units option are not included - let derived classes manage units since the units for CyTimeseries (OSSMTimeValue_c) are limited. No unit conversion is performed when get_timeseries, set_timeseries is invoked. It does, however convert between 'uv' and 'r-theta' depending on format specified. Choose format='uv' if no transformation is desired. .. note:: For the Wind datafiles, the units will get read from the file. These are stored in ossm.user_units. It would be ideal to remove units and unit conversion from here, but can't completely do away with it since C++ file reading uses/sets it. But, managing units is responsibility of derived objects. All other keywords are optional :param timeseries: numpy array containing time_value_pair :type timeseries: numpy.ndarray containing basic_types.datetime_value_2d or basic_types.datetime_value_1d. It gets converted to an array containging basic_types.time_value_pair datatype since that's what the C++ code expects :param filename: path to a timeseries file from which to read data. Datafile must contain either a 3 line or a 5 line header with following info: 1. Station Name: name of the station as a string 2. (long, lat, z): station location as tuple containing floats 3. units: for wind this is knots, meteres per second or miles per hour. For datafile containing something other than velocity, this should be 'undefined' Optional parameters (kwargs): :param format: (Optional) default timeseries format is magnitude direction: 'r-theta' :type format: string 'r-theta' or 'uv'. Default is 'r-theta'. Converts string to integer defined by gnome.basic_types.ts_format.* TODO: 'format' is a python builtin keyword. We should not use it as an argument name """ if (timeseries is None and filename is None): timeseries = np.array([(sec_to_date(zero_time()), [0.0, 0.0])], dtype=basic_types.datetime_value_2d) self._filename = filename if filename is None: # will raise an Exception if it fails self._check_timeseries(timeseries) datetime_value_2d = self._xform_input_timeseries(timeseries) time_value_pair = to_time_value_pair(datetime_value_2d, format) self.ossm = CyTimeseries(timeseries=time_value_pair) else: ts_format = tsformat(format) self.ossm = CyTimeseries(filename=self._filename, file_format=ts_format)
def __init__(self, timeseries=None, filename=None, format='uv'): """ Initializes a timeseries object from either a timeseries or datafile containing the timeseries. If both timeseries and file are given, it will read data from the file If neither are given, timeseries gets initialized as: timeseries = np.zeros((1,), dtype=basic_types.datetime_value_2d) If user provides timeseries, the default format is 'uv'. The C++ stores the data in 'uv' format - transformations are done in this Python code (set_timeseries(), get_timeseries()). C++ code only transforms the data from 'r-theta' to 'uv' format if data is read from file. And this happens during initialization because C++ stores data in 'uv' format internally. Units option are not included - let derived classes manage units since the units for CyTimeseries (OSSMTimeValue_c) are limited. No unit conversion is performed when get_timeseries, set_timeseries is invoked. It does, however convert between 'uv' and 'r-theta' depending on format specified. Choose format='uv' if no transformation is desired. .. note:: For the Wind datafiles, the units will get read from the file. These are stored in ossm.user_units. It would be ideal to remove units and unit conversion from here, but can't completely do away with it since C++ file reading uses/sets it. But, managing units is responsibility of derived objects. All other keywords are optional :param timeseries: numpy array containing time_value_pair :type timeseries: numpy.ndarray containing basic_types.datetime_value_2d or basic_types.datetime_value_1d. It gets converted to an array containging basic_types.time_value_pair datatype since that's what the C++ code expects :param filename: path to a timeseries file from which to read data. Datafile must contain either a 3 line or a 5 line header with following info: 1. Station Name: name of the station as a string 2. (long, lat, z): station location as tuple containing floats 3. units: for wind this is knots, meteres per second or miles per hour. For datafile containing something other than velocity, this should be 'undefined' Optional parameters (kwargs): :param format: (Optional) default timeseries format is magnitude direction: 'r-theta' :type format: string 'r-theta' or 'uv'. Default is 'r-theta'. Converts string to integer defined by gnome.basic_types.ts_format.* TODO: 'format' is a python builtin keyword. We should not use it as an argument name """ if (timeseries is None and filename is None): timeseries = np.array([(sec_to_date(zero_time()), [0.0, 0.0])], dtype=basic_types.datetime_value_2d) self._filename = filename if filename is None: if self._check_timeseries(timeseries): datetime_value_2d = self._xform_input_timeseries(timeseries) time_value_pair = to_time_value_pair(datetime_value_2d, format) self.ossm = CyTimeseries(timeseries=time_value_pair) else: raise ValueError('Bad timeseries as input') else: ts_format = tsformat(format) self.ossm = CyTimeseries(filename=self._filename, file_format=ts_format)
def __init__(self, timeseries=None, units=None, filename=None, coord_sys='r-theta', latitude=None, longitude=None, speed_uncertainty_scale=0.0, extrapolation_is_allowed=False, **kwargs): """ todo: update docstrings! """ self._timeseries = np.array([(sec_to_date(zero_time()), [0.0, 0.0])], dtype=datetime_value_2d) self.updated_at = kwargs.pop('updated_at', None) self.source_id = kwargs.pop('source_id', 'undefined') self.longitude = longitude self.latitude = latitude self.description = kwargs.pop('description', 'Wind Object') self.speed_uncertainty_scale = speed_uncertainty_scale # TODO: the way we are doing this, super() is not being used # effectively. We should tailor kwargs in a way that we can # just pass it into the base __init__() function. # As it is, we are losing arguments that we then need to # explicitly handle. if filename is not None: self.source_type = kwargs.pop('source_type', 'file') super(Wind, self).__init__(filename=filename, coord_sys=coord_sys, **kwargs) self.name = kwargs.pop('name', os.path.split(self.filename)[1]) # set _user_units attribute to match user_units read from file. self._user_units = self.ossm.user_units self._timeseries = self.get_wind_data(units=self._user_units) if units is not None: self.units = units else: if kwargs.get('source_type') in wind_datasources._attr: self.source_type = kwargs.pop('source_type') else: self.source_type = 'undefined' # either timeseries is given or nothing is given # create an empty default object super(Wind, self).__init__(coord_sys=coord_sys, **kwargs) self.units = 'mps' # units for default object if timeseries is not None: if units is None: raise TypeError('Units must be provided with timeseries') self.units = units self.new_set_timeseries(timeseries, coord_sys) self.extrapolation_is_allowed = extrapolation_is_allowed self.time = kwargs.pop('time', None)
def test_default_init(): av = RunningAverage() assert av.timeseries == np.array([(sec_to_date(zero_time()), [0.0, 0.0])], dtype=datetime_value_2d) assert av.units == 'mps'