def __init__(self, wind=None, extrapolate=False, **kwargs): #def __init__(self, wind=None, **kwargs): """ Uses super to call CyMover base class __init__ :param wind: wind object -- provides the wind time series for the mover Remaining kwargs are passed onto WindMoversBase __init__ using super. See Mover documentation for remaining valid kwargs. .. note:: Can be initialized with wind=None; however, wind must be set before running. If wind is not None, toggle make_default_refs to False since user provided a valid Wind and does not wish to use the default from the Model. """ self.mover = CyWindMover() self._wind = None if wind is not None: self.wind = wind kwargs['make_default_refs'] = \ kwargs.pop('make_default_refs', False) kwargs['name'] = \ kwargs.pop('name', wind.name) self.extrapolate = extrapolate # set optional attributes super(WindMover, self).__init__(**kwargs) # this will have to be updated when wind is set or changed if self.wind is not None: self.real_data_start = time_utils.sec_to_datetime( self.wind.ossm.get_start_time()) self.real_data_stop = time_utils.sec_to_datetime( self.wind.ossm.get_end_time())
def test_LE_not_in_water(): """ Tests get_move returns 0 for LE's that have a status different from in_water """ wm = CyWindMover() cm = cy_fixtures.CyTestMove() delta = np.zeros((cm.num_le, ), dtype=world_point) cm.status[:] = 0 wm.prepare_for_model_step(cm.model_time, cm.time_step) wm.get_move( cm.model_time, cm.time_step, cm.ref, delta, cm.windage, cm.status, spill_type.forecast, ) assert np.all(delta['lat'] == 0) assert np.all(delta['long'] == 0) assert np.all(delta['z'] == 0)
def __init__(self, wind=None, **kwargs): """ Uses super to call CyMover base class __init__ :param wind: wind object -- provides the wind time series for the mover Remaining kwargs are passed onto WindMoversBase __init__ using super. See Mover documentation for remaining valid kwargs. .. note:: Can be initialized with wind=None; however, wind must be set before running. If wind is not None, toggle make_default_refs to False since user provided a valid Wind and does not wish to use the default from the Model. """ self.mover = CyWindMover() self._wind = None if wind is not None: self.wind = wind self.name = wind.name kwargs['make_default_refs'] = kwargs.pop('make_default_refs', False) kwargs['name'] = kwargs.pop('name', wind.name) # set optional attributes super(WindMover, self).__init__(**kwargs)
def test_properties(): wm = CyWindMover() wm.uncertain_duration = 1 wm.uncertain_time_delay = 2 wm.uncertain_speed_scale = 3 wm.uncertain_angle_scale = 4 assert wm.uncertain_duration == 1 assert wm.uncertain_time_delay == 2 assert wm.uncertain_speed_scale == 3 assert wm.uncertain_angle_scale == 4
class ConstantWindWithOSSM(cy_fixtures.CyTestMove): """ This defines the OSSMTimeValue_c object using the CyTimeseries class, then uses the set_ossm method of CyWindMover object to set the time_dep member of the underlying WindMover_c C++ object Used for test setup """ wm = CyWindMover() def __init__(self): super(ConstantWindWithOSSM, self).__init__() time_val = np.empty((1, ), dtype=time_value_pair) time_val['time'] = 0 # should not matter time_val['value'] = const_wind self.ossm = CyTimeseries(timeseries=time_val) self.wm.set_ossm(self.ossm) def test_move(self): """ invoke get_move (no uncertainty) """ self.wm.prepare_for_model_step(self.model_time, self.time_step) self.wm.get_move(self.model_time, self.time_step, self.ref, self.delta, self.windage, self.status, spill_type.forecast) def test_move_uncertain(self): """ invoke get_move (uncertain LEs) """ self.wm.prepare_for_model_step(self.model_time, self.time_step, len(self.spill_size), self.spill_size) self.wm.get_move(self.model_time, self.time_step, self.ref, self.u_delta, self.windage, self.status, spill_type.uncertainty)
def __init__(self, wind=None, **kwargs): """ Uses super to call CyMover base class __init__ :param wind: wind object -- provides the wind time series for the mover Remaining kwargs are passed onto WindMoversBase __init__ using super. See Mover documentation for remaining valid kwargs. .. note:: Can be initialized with wind=None; however, wind must be set before running. If wind is not None, toggle make_default_refs to False since user provided a valid Wind and does not wish to use the default from the Model. """ self.mover = CyWindMover() self._wind = None if wind is not None: self.wind = wind kwargs['make_default_refs'] = \ kwargs.pop('make_default_refs', False) kwargs['name'] = \ kwargs.pop('name', wind.name) # set optional attributes super(WindMover, self).__init__(**kwargs)
def __init__(self, wind=None, extrapolate=False, **kwargs): #def __init__(self, wind=None, **kwargs): """ Uses super to call CyMover base class __init__ :param wind: wind object -- provides the wind time series for the mover Remaining kwargs are passed onto WindMoversBase __init__ using super. See Mover documentation for remaining valid kwargs. .. note:: Can be initialized with wind=None; however, wind must be set before running. If wind is not None, toggle make_default_refs to False since user provided a valid Wind and does not wish to use the default from the Model. """ self.mover = CyWindMover() self._wind = None if wind is not None: self.wind = wind kwargs['make_default_refs'] = \ kwargs.pop('make_default_refs', False) kwargs['name'] = \ kwargs.pop('name', wind.name) self.extrapolate = extrapolate # set optional attributes super(WindMover, self).__init__(**kwargs) # this will have to be updated when wind is set or changed if self.wind is not None: self.real_data_start = time_utils.sec_to_datetime(self.wind.ossm.get_start_time()) self.real_data_stop = time_utils.sec_to_datetime(self.wind.ossm.get_end_time())
class ConstantWind(cy_fixtures.CyTestMove): """ Wind Mover object instantiated with a constant wind using member method set_constant_wind(...) Used for test setup """ wm = CyWindMover() def __init__(self): super(ConstantWind, self).__init__() self.const_wind = const_wind self.wm.set_constant_wind(const_wind['u'], const_wind['v']) def test_move(self): """ forecast move """ self.wm.prepare_for_model_step(self.model_time, self.time_step) self.wm.get_move(self.model_time, self.time_step, self.ref, self.delta, self.windage, self.status, spill_type.forecast) def test_move_uncertain(self): """ uncertain LEs """ self.wm.prepare_for_model_step(self.model_time, self.time_step, len(self.spill_size), self.spill_size) self.wm.get_move(self.model_time, self.time_step, self.ref, self.u_delta, self.windage, self.status, spill_type.uncertainty)
class TestObjectSerialization: ''' Test all the serialization and deserialization methods that are available to the CyTimeseries object. ''' ossmT = CyTimeseries(filename=testdata['timeseries']['wind_ts'], file_format=ts_format.magnitude_direction) wm = CyWindMover() wm.set_ossm(ossmT) def test_repr(self): ''' Test that the repr method produces a string capable of reproducing the object. ''' # This works, but in order to properly eval the repr string, we need # the top level gnome module, as well as the numpy 'array' type in the # global name space. # So before we try it, we first need to import like this: import gnome from numpy import array new_wm = eval(repr(self.wm)) assert new_wm == self.wm assert repr(new_wm) == repr(self.wm)
def test_init(): # can we create a wind_mover? wm = CyWindMover() assert wm.uncertain_duration == 10800 assert wm.uncertain_time_delay == 0 assert wm.uncertain_speed_scale == 2 assert wm.uncertain_angle_scale == 0.4
def __init__(self, wind, **kwargs): """ Uses super to call CyMover base class __init__ :param wind: wind object -- provides the wind time series for the mover Remaining kwargs are passed onto WindMoversBase __init__ using super. See Mover documentation for remaining valid kwargs. """ self.mover = CyWindMover() self.wind = wind # set optional attributes super(WindMover, self).__init__(**kwargs)
def test_eq(): wm = CyWindMover() other_wm = CyWindMover() assert wm == other_wm other_wm = CyWindMover() other_wm.uncertain_duration = 1 assert wm != other_wm other_wm = CyWindMover() other_wm.uncertain_time_delay = 2 assert wm != other_wm other_wm = CyWindMover() other_wm.uncertain_speed_scale = 3 assert wm != other_wm other_wm = CyWindMover() other_wm.uncertain_angle_scale = 4 assert wm != other_wm
def test_properties(): wm = CyWindMover() wm.uncertain_duration = 1 wm.uncertain_time_delay = 2 wm.uncertain_speed_scale = 3 wm.uncertain_angle_scale = 4 wm.extrapolate = True assert wm.uncertain_duration == 1 assert wm.uncertain_time_delay == 2 assert wm.uncertain_speed_scale == 3 assert wm.uncertain_angle_scale == 4 assert wm.extrapolate == True
class TestVariableWind: """ Uses OSSMTimeValue_c to define a variable wind - variable wind has 'v' component, so movement should only be in 'lat' direction of world point Leave as a class as we may add more methods to it for testing """ wm = CyWindMover() cm = cy_fixtures.CyTestMove() delta = np.zeros((cm.num_le, ), dtype=world_point) time_val = np.zeros((2, ), dtype=time_value_pair) (time_val['time'])[:] = np.add([0, 3600], cm.model_time) # after 1 hour (time_val['value']['v'])[:] = [100, 200] # CyTimeseries needs the same scope as CyWindMover because CyWindMover # uses the C++ pointer defined in CyTimeseries.time_dep. This must be defined # for the scope of CyWindMover ossm = CyTimeseries(timeseries=time_val) wm.set_ossm(ossm) def test_move(self): for x in range(0, 3): vary_time = x * 1800 self.wm.prepare_for_model_step(self.cm.model_time + vary_time, self.cm.time_step) self.wm.get_move(self.cm.model_time + vary_time, self.cm.time_step, self.cm.ref, self.delta, self.cm.windage, self.cm.status, spill_type.forecast) print self.delta assert np.all(self.delta['lat'] != 0) assert np.all(self.delta['long'] == 0) assert np.all(self.delta['z'] == 0)
def test_LE_not_in_water(): """ Tests get_move returns 0 for LE's that have a status different from in_water """ wm = CyWindMover() cm = cy_fixtures.CyTestMove() delta = np.zeros((cm.num_le, ), dtype=world_point) cm.status[:] = 0 wm.prepare_for_model_step(cm.model_time, cm.time_step) wm.get_move(cm.model_time, cm.time_step, cm.ref, delta, cm.windage, cm.status, spill_type.forecast) assert np.all(delta['lat'] == 0) assert np.all(delta['long'] == 0) assert np.all(delta['z'] == 0)
class TestVariableWind: """ Uses OSSMTimeValue_c to define a variable wind - variable wind has 'v' component, so movement should only be in 'lat' direction of world point Leave as a class as we may add more methods to it for testing """ wm = CyWindMover() cm = cy_fixtures.CyTestMove() delta = np.zeros((cm.num_le, ), dtype=world_point) time_val = np.zeros((2, ), dtype=time_value_pair) (time_val['time'])[:] = np.add([0, 3600], cm.model_time) # after 1 hour (time_val['value']['v'])[:] = [100, 200] # CyTimeseries needs the same scope as CyWindMover because CyWindMover # uses the C++ pointer defined in CyTimeseries.time_dep. # This must be defined for the scope of CyWindMover ossm = CyTimeseries(timeseries=time_val) wm.set_ossm(ossm) def test_move(self): for x in range(0, 3): vary_time = x * 1800 self.wm.prepare_for_model_step(self.cm.model_time + vary_time, self.cm.time_step) self.wm.get_move(self.cm.model_time + vary_time, self.cm.time_step, self.cm.ref, self.delta, self.cm.windage, self.cm.status, spill_type.forecast) print self.delta assert np.all(self.delta['lat'] != 0) assert np.all(self.delta['long'] == 0) assert np.all(self.delta['z'] == 0) def test_move_out_of_bounds(self): ''' Our wind mover should fail in the prepare_for_model_step() function if our wind time series is out of bounds with respect to the model time we are preparing for, unless our wind time series is configured to extrapolate wind values. ''' # setup a time series that's out of range of our model time time_val = np.zeros((2, ), dtype=time_value_pair) (time_val['time'])[:] = np.add([3600, 7200], self.cm.model_time) (time_val['value']['v'])[:] = [100, 200] # extrapolation should be off by default ossm = CyTimeseries(timeseries=time_val) self.wm.set_ossm(ossm) # this should fail because our time series is not set to extrapolate with raises(OSError): self.wm.prepare_for_model_step(self.cm.model_time, self.cm.time_step) ossm = CyTimeseries(timeseries=time_val, extrapolation_is_allowed=True) self.wm.set_ossm(ossm) # We set our time series to extrapolate, so this should pass self.wm.prepare_for_model_step(self.cm.model_time, self.cm.time_step) # clean up our time series self.wm.set_ossm(self.ossm)
class WindMover(WindMoversBase): """ Python wrapper around the Cython wind_mover module. This class inherits from CyMover and contains CyWindMover The real work is done by the CyWindMover object. CyMover sets everything up that is common to all movers. """ _schema = WindMoverSchema def __init__(self, wind=None, **kwargs): """ Uses super to call CyMover base class __init__ :param wind: wind object -- provides the wind time series for the mover Remaining kwargs are passed onto WindMoversBase __init__ using super. See Mover documentation for remaining valid kwargs. .. note:: Can be initialized with wind=None; however, wind must be set before running. If wind is not None, toggle make_default_refs to False since user provided a valid Wind and does not wish to use the default from the Model. """ self.mover = CyWindMover() self._wind = None if wind is not None: self.wind = wind self.name = wind.name kwargs['make_default_refs'] = kwargs.pop('make_default_refs', False) kwargs['name'] = kwargs.pop('name', wind.name) # set optional attributes super(WindMover, self).__init__(**kwargs) def __repr__(self): return ( '{0.__class__.__module__}.{0.__class__.__name__}(\n{1})'.format( self, self._state_as_str())) def __str__(self): return ('WindMover - current _state. ' 'See "wind" object for wind conditions:\n{0}'.format( self._state_as_str())) @property def wind(self): return self._wind @wind.setter def wind(self, value): if not isinstance(value, Wind): raise TypeError('wind must be of type environment.Wind') else: # update reference to underlying cython object self._wind = value self.mover.set_ossm(self._wind.ossm) @property def data_start(self): return self.wind.data_start @property def data_stop(self): return self.wind.data_stop def prepare_for_model_run(self): ''' if wind attribute is not set, raise ReferencedObjectNotSet excpetion ''' super(WindMover, self).prepare_for_model_run() if self.on and self.wind is None: msg = "wind object not defined for WindMover" raise ReferencedObjectNotSet(msg)
class WindMover(WindMoversBase, serializable.Serializable): """ Python wrapper around the Cython wind_mover module. This class inherits from CyMover and contains CyWindMover The real work is done by the CyWindMover object. CyMover sets everything up that is common to all movers. In addition to base class array_types.basic, also use the array_types.windage dict since WindMover requires a windage array """ _state = copy.deepcopy(WindMoversBase._state) #_state.add(read=['wind_id'], save=['wind_id']) # todo: probably need to make update=True for 'wind' as well _state.add_field(serializable.Field('wind', save=True, update=True, save_reference=True)) _schema = WindMoverSchema def __init__(self, wind, **kwargs): """ Uses super to call CyMover base class __init__ :param wind: wind object -- provides the wind time series for the mover Remaining kwargs are passed onto WindMoversBase __init__ using super. See Mover documentation for remaining valid kwargs. """ self.mover = CyWindMover() self.wind = wind self.name = wind.name # set optional attributes super(WindMover, self).__init__(**kwargs) def __repr__(self): """ .. todo:: We probably want to include more information. """ return ('{0.__class__.__module__}.{0.__class__.__name__}(\n' '{1}' ')'.format(self, self._state_as_str())) def __str__(self): info = ('WindMover - current _state. ' 'See "wind" object for wind conditions:\n' '{0}'.format(self._state_as_str())) return info @property def wind(self): return self._wind @wind.setter def wind(self, value): if not isinstance(value, environment.Wind): raise TypeError('wind must be of type environment.Wind') else: # update reference to underlying cython object self._wind = value self.mover.set_ossm(self.wind.ossm) def serialize(self, json_='webapi'): """ Since 'wind' property is saved as a reference when used in save file and 'save' option, need to add appropriate node to WindMover schema """ toserial = self.to_serialize(json_) schema = self.__class__._schema() if json_ == 'webapi': # add wind schema schema.add(environment.WindSchema()) serial = schema.serialize(toserial) return serial @classmethod def deserialize(cls, json_): """ append correct schema for wind object """ schema = cls._schema() if 'wind' in json_: schema.add(environment.WindSchema()) _to_dict = schema.deserialize(json_) return _to_dict
class WindMover(WindMoversBase, serializable.Serializable): """ Python wrapper around the Cython wind_mover module. This class inherits from CyMover and contains CyWindMover The real work is done by the CyWindMover object. CyMover sets everything up that is common to all movers. """ _state = copy.deepcopy(WindMoversBase._state) _state.add(update=['extrapolate'], save=['extrapolate']) _state.add_field( serializable.Field('wind', save=True, update=True, save_reference=True)) _schema = WindMoverSchema def __init__(self, wind=None, extrapolate=False, **kwargs): #def __init__(self, wind=None, **kwargs): """ Uses super to call CyMover base class __init__ :param wind: wind object -- provides the wind time series for the mover Remaining kwargs are passed onto WindMoversBase __init__ using super. See Mover documentation for remaining valid kwargs. .. note:: Can be initialized with wind=None; however, wind must be set before running. If wind is not None, toggle make_default_refs to False since user provided a valid Wind and does not wish to use the default from the Model. """ self.mover = CyWindMover() self._wind = None if wind is not None: self.wind = wind kwargs['make_default_refs'] = \ kwargs.pop('make_default_refs', False) kwargs['name'] = \ kwargs.pop('name', wind.name) self.extrapolate = extrapolate # set optional attributes super(WindMover, self).__init__(**kwargs) # this will have to be updated when wind is set or changed if self.wind is not None: self.real_data_start = time_utils.sec_to_datetime( self.wind.ossm.get_start_time()) self.real_data_stop = time_utils.sec_to_datetime( self.wind.ossm.get_end_time()) def __repr__(self): """ .. todo:: We probably want to include more information. """ return ('{0.__class__.__module__}.{0.__class__.__name__}(\n' '{1}' ')'.format(self, self._state_as_str())) def __str__(self): info = ('WindMover - current _state. ' 'See "wind" object for wind conditions:\n' '{0}'.format(self._state_as_str())) return info extrapolate = property( lambda self: self.mover.extrapolate, lambda self, val: setattr(self.mover, 'extrapolate', val)) @property def wind(self): return self._wind @wind.setter def wind(self, value): if not isinstance(value, environment.Wind): raise TypeError('wind must be of type environment.Wind') else: # update reference to underlying cython object self._wind = value self.mover.set_ossm(self.wind.ossm) def prepare_for_model_run(self): ''' if wind attribute is not set, raise ReferencedObjectNotSet excpetion ''' super(WindMover, self).prepare_for_model_run() if self.on and self.wind is None: msg = "wind object not defined for WindMover" raise ReferencedObjectNotSet(msg) def serialize(self, json_='webapi'): """ Since 'wind' property is saved as a reference when used in save file and 'save' option, need to add appropriate node to WindMover schema """ toserial = self.to_serialize(json_) schema = self.__class__._schema() if json_ == 'webapi': # add wind schema schema.add(environment.WindSchema(name='wind')) serial = schema.serialize(toserial) return serial @classmethod def deserialize(cls, json_): """ append correct schema for wind object """ schema = cls._schema() if 'wind' in json_: schema.add(environment.WindSchema()) _to_dict = schema.deserialize(json_) return _to_dict
class WindMover(WindMoversBase): """ Python wrapper around the Cython wind_mover module. This class inherits from CyMover and contains CyWindMover The real work is done by the CyWindMover object. CyMover sets everything up that is common to all movers. """ _schema = WindMoverSchema def __init__(self, wind=None, **kwargs): """ Uses super to call CyMover base class __init__ :param wind: wind object -- provides the wind time series for the mover Remaining kwargs are passed onto WindMoversBase __init__ using super. See Mover documentation for remaining valid kwargs. .. note:: Can be initialized with wind=None; however, wind must be set before running. If wind is not None, toggle make_default_refs to False since user provided a valid Wind and does not wish to use the default from the Model. """ self.mover = CyWindMover() self._wind = None if wind is not None: self.wind = wind self.name = wind.name kwargs['make_default_refs'] = kwargs.pop('make_default_refs', False) kwargs['name'] = kwargs.pop('name', wind.name) # set optional attributes super(WindMover, self).__init__(**kwargs) def __repr__(self): return ('{0.__class__.__module__}.{0.__class__.__name__}(\n{1})' .format(self, self._state_as_str())) def __str__(self): return ('WindMover - current _state. ' 'See "wind" object for wind conditions:\n{0}' .format(self._state_as_str())) @property def wind(self): return self._wind @wind.setter def wind(self, value): if not isinstance(value, Wind): raise TypeError('wind must be of type environment.Wind') else: # update reference to underlying cython object self._wind = value self.mover.set_ossm(self._wind.ossm) @property def data_start(self): return self.wind.data_start @property def data_stop(self): return self.wind.data_stop def prepare_for_model_run(self): ''' if wind attribute is not set, raise ReferencedObjectNotSet excpetion ''' super(WindMover, self).prepare_for_model_run() if self.on and self.wind is None: msg = "wind object not defined for WindMover" raise ReferencedObjectNotSet(msg)
class WindMover(WindMoversBase, serializable.Serializable): """ Python wrapper around the Cython wind_mover module. This class inherits from CyMover and contains CyWindMover The real work is done by the CyWindMover object. CyMover sets everything up that is common to all movers. """ _state = copy.deepcopy(WindMoversBase._state) _state.add(update=['extrapolate'], save=['extrapolate']) _state.add_field(serializable.Field('wind', save=True, update=True, save_reference=True)) _schema = WindMoverSchema def __init__(self, wind=None, extrapolate=False, **kwargs): #def __init__(self, wind=None, **kwargs): """ Uses super to call CyMover base class __init__ :param wind: wind object -- provides the wind time series for the mover Remaining kwargs are passed onto WindMoversBase __init__ using super. See Mover documentation for remaining valid kwargs. .. note:: Can be initialized with wind=None; however, wind must be set before running. If wind is not None, toggle make_default_refs to False since user provided a valid Wind and does not wish to use the default from the Model. """ self.mover = CyWindMover() self._wind = None if wind is not None: self.wind = wind kwargs['make_default_refs'] = \ kwargs.pop('make_default_refs', False) kwargs['name'] = \ kwargs.pop('name', wind.name) self.extrapolate = extrapolate # set optional attributes super(WindMover, self).__init__(**kwargs) # this will have to be updated when wind is set or changed if self.wind is not None: self.real_data_start = time_utils.sec_to_datetime(self.wind.ossm.get_start_time()) self.real_data_stop = time_utils.sec_to_datetime(self.wind.ossm.get_end_time()) def __repr__(self): """ .. todo:: We probably want to include more information. """ return ('{0.__class__.__module__}.{0.__class__.__name__}(\n' '{1}' ')'.format(self, self._state_as_str())) def __str__(self): info = ('WindMover - current _state. ' 'See "wind" object for wind conditions:\n' '{0}'.format(self._state_as_str())) return info extrapolate = property(lambda self: self.mover.extrapolate, lambda self, val: setattr(self.mover, 'extrapolate', val)) @property def wind(self): return self._wind @wind.setter def wind(self, value): if not isinstance(value, environment.Wind): raise TypeError('wind must be of type environment.Wind') else: # update reference to underlying cython object self._wind = value self.mover.set_ossm(self.wind.ossm) def prepare_for_model_run(self): ''' if wind attribute is not set, raise ReferencedObjectNotSet excpetion ''' super(WindMover, self).prepare_for_model_run() if self.on and self.wind is None: msg = "wind object not defined for WindMover" raise ReferencedObjectNotSet(msg) def serialize(self, json_='webapi'): """ Since 'wind' property is saved as a reference when used in save file and 'save' option, need to add appropriate node to WindMover schema """ toserial = self.to_serialize(json_) schema = self.__class__._schema() if json_ == 'webapi': # add wind schema schema.add(environment.WindSchema(name='wind')) serial = schema.serialize(toserial) return serial @classmethod def deserialize(cls, json_): """ append correct schema for wind object """ schema = cls._schema() if 'wind' in json_: schema.add(environment.WindSchema()) _to_dict = schema.deserialize(json_) return _to_dict
class WindMover(WindMoversBase, serializable.Serializable): """ Python wrapper around the Cython wind_mover module. This class inherits from CyMover and contains CyWindMover The real work is done by the CyWindMover object. CyMover sets everything up that is common to all movers. In addition to base class array_types.basic, also use the array_types.windage dict since WindMover requires a windage array """ state = copy.deepcopy(WindMoversBase.state) state.add(read=['wind_id'], create=['wind_id']) @classmethod def new_from_dict(cls, dict_): """ define in WindMover and check wind_id matches wind invokes: super(WindMover,cls).new_from_dict(dict\_) """ wind_id = dict_.pop('wind_id') if dict_.get('wind').id != wind_id: raise ValueError('id of wind object does not match the wind_id'\ ' parameter') return super(WindMover, cls).new_from_dict(dict_) def wind_id_to_dict(self): """ used only for storing state so no wind_id_from_dict is defined. This is not a read/write attribute. Only defined for serializable_state """ return self.wind.id def from_dict(self, dict_): """ For updating the object from dictionary 'wind' object is not part of the state since it is not serialized/ deserialized; however, user can still update the wind attribute with a new Wind object. That must be poped out of the dict() here, then call super to process the standard dict\_ """ self.wind = dict_.pop('wind', self.wind) super(WindMover, self).from_dict(dict_) def __init__(self, wind, **kwargs): """ Uses super to call CyMover base class __init__ :param wind: wind object -- provides the wind time series for the mover Remaining kwargs are passed onto WindMoversBase __init__ using super. See Mover documentation for remaining valid kwargs. """ self.mover = CyWindMover() self.wind = wind # set optional attributes super(WindMover, self).__init__(**kwargs) def __repr__(self): """ .. todo:: We probably want to include more information. """ info = 'WindMover(\n{0})'.format(self._state_as_str()) return info def __str__(self): info = \ "WindMover - current state." \ + " See 'wind' object for wind conditions:\n" \ + "{0}".format(self._state_as_str()) return info @property def wind(self): return self._wind @wind.setter def wind(self, value): if not isinstance(value, environment.Wind): raise TypeError('wind must be of type environment.Wind') else: # update reference to underlying cython object self._wind = value self.mover.set_ossm(self.wind.ossm)