def __init__(self, filename=None, topology_file=None, tide=None, **kwargs): """ Initialize a CurrentCycleMover :param filename: Absolute or relative path to the data file: could be netcdf or filelist :param topology_file=None: Absolute or relative path to topology file. If not given, the GridCurrentMover will compute the topology from the data file. :param tide: A gnome.environment.Tide object to be attached to CatsMover :param active_range: Range of datetimes for when the mover should be active :type active_range: 2-tuple of datetimes :param current_scale: Value to scale current data :param uncertain_duration: How often does a given uncertain element get reset :param uncertain_time_delay: when does the uncertainly kick in. :param uncertain_cross: Scale for uncertainty perpendicular to the flow :param uncertain_along: Scale for uncertainty parallel to the flow :param extrapolate: Allow current data to be extrapolated before and after file data :param time_offset: Time zone shift if data is in GMT uses super: super(CurrentCycleMover,self).__init__(**kwargs) """ # NOTE: will need to add uncertainty parameters # and other dialog fields. # use super with kwargs to invoke base class __init__ self.mover = CyCurrentCycleMover() self._tide = None if tide: self.tide = tide super(CurrentCycleMover, self).__init__(filename=filename, topology_file=topology_file, **kwargs)
class CurrentCycleMover(GridCurrentMover): _schema = CurrentCycleMoverSchema def __init__(self, filename=None, topology_file=None, tide=None, **kwargs): """ Initialize a CurrentCycleMover :param filename: Absolute or relative path to the data file: could be netcdf or filelist :param topology_file=None: Absolute or relative path to topology file. If not given, the GridCurrentMover will compute the topology from the data file. :param tide: A gnome.environment.Tide object to be attached to CatsMover :param active_range: Range of datetimes for when the mover should be active :type active_range: 2-tuple of datetimes :param current_scale: Value to scale current data :param uncertain_duration: How often does a given uncertain element get reset :param uncertain_time_delay: when does the uncertainly kick in. :param uncertain_cross: Scale for uncertainty perpendicular to the flow :param uncertain_along: Scale for uncertainty parallel to the flow :param extrapolate: Allow current data to be extrapolated before and after file data :param time_offset: Time zone shift if data is in GMT uses super: super(CurrentCycleMover,self).__init__(**kwargs) """ # NOTE: will need to add uncertainty parameters # and other dialog fields. # use super with kwargs to invoke base class __init__ self.mover = CyCurrentCycleMover() self._tide = None if tide: self.tide = tide super(CurrentCycleMover, self).__init__(filename=filename, topology_file=topology_file, **kwargs) def __repr__(self): return ( 'CurrentCycletMover(uncertain_duration={0.uncertain_duration}, ' 'uncertain_time_delay={0.uncertain_time_delay}, ' 'uncertain_cross={0.uncertain_cross}, ' 'uncertain_along={0.uncertain_along}, ' 'active_range={1.active_range}, ' 'on={1.on})'.format(self.mover, self)) def __str__(self): return ('CurrentCycleMover - current _state.\n' ' uncertain_duration={0.uncertain_duration}\n' ' uncertain_time_delay={0.uncertain_time_delay}\n' ' uncertain_cross={0.uncertain_cross}\n' ' uncertain_along={0.uncertain_along}' ' active_range time={1.active_range}' ' current on/off status={1.on}'.format(self.mover, self)) @property def tide(self): return self._tide @tide.setter def tide(self, tide_obj): if not isinstance(tide_obj, Tide): raise TypeError('tide must be of type environment.Tide') if isinstance(tide_obj.cy_obj, CyShioTime): self.mover.set_shio(tide_obj.cy_obj) elif isinstance(tide_obj.cy_obj, CyOSSMTime): self.mover.set_ossm(tide_obj.cy_obj) else: raise TypeError('Tide.cy_obj attribute must be either ' 'CyOSSMTime or CyShioTime type ' 'for CurrentCycleMover.') self._tide = tide_obj @property def data_start(self): if self.tide is not None: return self.tide.data_start else: return MinusInfTime() @property def data_stop(self): if self.tide is not None: return self.tide.data_stop else: return InfTime() @property def is_data_on_cells(self): return None
class CurrentCycleMover(GridCurrentMover, Serializable): _state = copy.deepcopy(GridCurrentMover._state) _state.add_field([Field('tide', save=True, update=True, save_reference=True)]) _schema = CurrentCycleMoverSchema def __init__(self, filename, topology_file=None, **kwargs): """ Initialize a CurrentCycleMover :param filename: Absolute or relative path to the data file: could be netcdf or filelist :param topology_file=None: Absolute or relative path to topology file. If not given, the GridCurrentMover will compute the topology from the data file. :param tide: A gnome.environment.Tide object to be attached to CatsMover :param active_start: datetime when the mover should be active :param active_stop: datetime after which the mover should be inactive :param current_scale: Value to scale current data :param uncertain_duration: How often does a given uncertain element get reset :param uncertain_time_delay: when does the uncertainly kick in. :param uncertain_cross: Scale for uncertainty perpendicular to the flow :param uncertain_along: Scale for uncertainty parallel to the flow :param extrapolate: Allow current data to be extrapolated before and after file data :param time_offset: Time zone shift if data is in GMT uses super: super(CurrentCycleMover,self).__init__(**kwargs) """ # NOTE: will need to add uncertainty parameters # and other dialog fields. # use super with kwargs to invoke base class __init__ self.mover = CyCurrentCycleMover() self._tide = None tide = kwargs.pop('tide', None) if tide is not None: self.tide = tide super(CurrentCycleMover, self).__init__(filename=filename, topology_file=topology_file, **kwargs) def __repr__(self): return ('GridCurrentMover(uncertain_duration={0.uncertain_duration}, ' 'uncertain_time_delay={0.uncertain_time_delay}, ' 'uncertain_cross={0.uncertain_cross}, ' 'uncertain_along={0.uncertain_along}, ' 'active_start={1.active_start}, ' 'active_stop={1.active_stop}, ' 'on={1.on})' .format(self.mover, self)) def __str__(self): return ('GridCurrentMover - current _state.\n' ' uncertain_duration={0.uncertain_duration}\n' ' uncertain_time_delay={0.uncertain_time_delay}\n' ' uncertain_cross={0.uncertain_cross}\n' ' uncertain_along={0.uncertain_along}' ' active_start time={1.active_start}' ' active_stop time={1.active_stop}' ' current on/off status={1.on}' .format(self.mover, self)) @property def tide(self): return self._tide @tide.setter def tide(self, tide_obj): if not isinstance(tide_obj, Tide): raise TypeError('tide must be of type environment.Tide') if isinstance(tide_obj.cy_obj, CyShioTime): self.mover.set_shio(tide_obj.cy_obj) elif isinstance(tide_obj.cy_obj, CyOSSMTime): self.mover.set_ossm(tide_obj.cy_obj) else: raise TypeError('Tide.cy_obj attribute must be either ' 'CyOSSMTime or CyShioTime type ' 'for CurrentCycleMover.') self._tide = tide_obj @property def is_data_on_cells(self): return None def serialize(self, json_='webapi'): """ Since 'tide' property is saved as a reference when used in save file and 'save' option, need to add appropriate node to CurrentCycleMover schema """ toserial = self.to_serialize(json_) schema = self.__class__._schema() if json_ == 'webapi' and 'tide' in toserial: schema.add(TideSchema(name='tide')) return schema.serialize(toserial) @classmethod def deserialize(cls, json_): """ append correct schema for tide object """ schema = cls._schema() if 'tide' in json_: schema.add(TideSchema()) return schema.deserialize(json_)
class CurrentCycleMover(GridCurrentMover): _schema = CurrentCycleMoverSchema def __init__(self, filename=None, topology_file=None, tide=None, **kwargs): """ Initialize a CurrentCycleMover :param filename: Absolute or relative path to the data file: could be netcdf or filelist :param topology_file=None: Absolute or relative path to topology file. If not given, the GridCurrentMover will compute the topology from the data file. :param tide: A gnome.environment.Tide object to be attached to CatsMover :param active_range: Range of datetimes for when the mover should be active :type active_range: 2-tuple of datetimes :param current_scale: Value to scale current data :param uncertain_duration: How often does a given uncertain element get reset :param uncertain_time_delay: when does the uncertainly kick in. :param uncertain_cross: Scale for uncertainty perpendicular to the flow :param uncertain_along: Scale for uncertainty parallel to the flow :param extrapolate: Allow current data to be extrapolated before and after file data :param time_offset: Time zone shift if data is in GMT uses super: super(CurrentCycleMover,self).__init__(**kwargs) """ # NOTE: will need to add uncertainty parameters # and other dialog fields. # use super with kwargs to invoke base class __init__ self.mover = CyCurrentCycleMover() self._tide = None if tide: self.tide = tide super(CurrentCycleMover, self).__init__(filename=filename, topology_file=topology_file, **kwargs) def __repr__(self): return ('CurrentCycletMover(uncertain_duration={0.uncertain_duration}, ' 'uncertain_time_delay={0.uncertain_time_delay}, ' 'uncertain_cross={0.uncertain_cross}, ' 'uncertain_along={0.uncertain_along}, ' 'active_range={1.active_range}, ' 'on={1.on})' .format(self.mover, self)) def __str__(self): return ('CurrentCycleMover - current _state.\n' ' uncertain_duration={0.uncertain_duration}\n' ' uncertain_time_delay={0.uncertain_time_delay}\n' ' uncertain_cross={0.uncertain_cross}\n' ' uncertain_along={0.uncertain_along}' ' active_range time={1.active_range}' ' current on/off status={1.on}' .format(self.mover, self)) @property def tide(self): return self._tide @tide.setter def tide(self, tide_obj): if not isinstance(tide_obj, Tide): raise TypeError('tide must be of type environment.Tide') if isinstance(tide_obj.cy_obj, CyShioTime): self.mover.set_shio(tide_obj.cy_obj) elif isinstance(tide_obj.cy_obj, CyOSSMTime): self.mover.set_ossm(tide_obj.cy_obj) else: raise TypeError('Tide.cy_obj attribute must be either ' 'CyOSSMTime or CyShioTime type ' 'for CurrentCycleMover.') self._tide = tide_obj @property def data_start(self): if self.tide is not None: return self.tide.data_start else: return MinusInfTime() @property def data_stop(self): if self.tide is not None: return self.tide.data_stop else: return InfTime() @property def is_data_on_cells(self): return None
class CurrentCycleMover(GridCurrentMover, serializable.Serializable): _state = copy.deepcopy(GridCurrentMover._state) _state.add_field([serializable.Field('tide', save=True, update=True, save_reference=True)]) _schema = CurrentCycleMoverSchema def __init__(self, filename, topology_file=None, **kwargs): """ Initialize a CurrentCycleMover :param filename: Absolute or relative path to the data file: could be netcdf or filelist :param topology_file=None: Absolute or relative path to topology file. If not given, the GridCurrentMover will compute the topology from the data file. :param tide: A gnome.environment.Tide object to be attached to CatsMover :param active_start: datetime when the mover should be active :param active_stop: datetime after which the mover should be inactive :param current_scale: Value to scale current data :param uncertain_duration: How often does a given uncertain element get reset :param uncertain_time_delay: when does the uncertainly kick in. :param uncertain_cross: Scale for uncertainty perpendicular to the flow :param uncertain_along: Scale for uncertainty parallel to the flow :param extrapolate: Allow current data to be extrapolated before and after file data :param time_offset: Time zone shift if data is in GMT uses super: super(CurrentCycleMover,self).__init__(**kwargs) """ # NOTE: will need to add uncertainty parameters # and other dialog fields. # use super with kwargs to invoke base class __init__ self.mover = CyCurrentCycleMover() tide = kwargs.pop('tide', None) self._tide = None if tide is not None: self.tide = tide super(CurrentCycleMover, self).__init__(filename=filename, topology_file=topology_file, **kwargs) def __repr__(self): return ('GridCurrentMover(uncertain_duration={0.uncertain_duration}, ' 'uncertain_time_delay={0.uncertain_time_delay}, ' 'uncertain_cross={0.uncertain_cross}, ' 'uncertain_along={0.uncertain_along}, ' 'active_start={1.active_start}, ' 'active_stop={1.active_stop}, ' 'on={1.on})' .format(self.mover, self)) def __str__(self): return ('GridCurrentMover - current _state.\n' ' uncertain_duration={0.uncertain_duration}\n' ' uncertain_time_delay={0.uncertain_time_delay}\n' ' uncertain_cross={0.uncertain_cross}\n' ' uncertain_along={0.uncertain_along}' ' active_start time={1.active_start}' ' active_stop time={1.active_stop}' ' current on/off status={1.on}' .format(self.mover, self)) @property def tide(self): return self._tide @tide.setter def tide(self, tide_obj): if not isinstance(tide_obj, environment.Tide): raise TypeError('tide must be of type environment.Tide') if isinstance(tide_obj.cy_obj, CyShioTime): self.mover.set_shio(tide_obj.cy_obj) elif isinstance(tide_obj.cy_obj, CyOSSMTime): self.mover.set_ossm(tide_obj.cy_obj) else: raise TypeError('Tide.cy_obj attribute must be either ' 'CyOSSMTime or CyShioTime type ' 'for CurrentCycleMover.') self._tide = tide_obj def serialize(self, json_='webapi'): """ Since 'tide' property is saved as a reference when used in save file and 'save' option, need to add appropriate node to CurrentCycleMover schema """ toserial = self.to_serialize(json_) schema = self.__class__._schema() if json_ == 'webapi' and 'tide' in toserial: schema.add(environment.TideSchema(name='tide')) return schema.serialize(toserial) @classmethod def deserialize(cls, json_): """ append correct schema for tide object """ schema = cls._schema() if 'tide' in json_: schema.add(environment.TideSchema()) return schema.deserialize(json_)
class TestCurrentCycleMover: cm = Common() ccm = CyCurrentCycleMover() # delta = np.zeros((cm.num_le,), dtype=world_point) def move(self): self.ccm.prepare_for_model_run() print "Certain move" self.ccm.prepare_for_model_step(self.cm.model_time, self.cm.time_step) self.ccm.get_move( self.cm.model_time, self.cm.time_step, self.cm.ref, self.cm.delta, self.cm.status, spill_type.forecast, ) def move_uncertain(self): self.ccm.prepare_for_model_run() spill_size = np.zeros((1, ), dtype=np.int32) # number of LEs in 1 uncertainty spill - simple test spill_size[0] = self.cm.num_le # for uncertainty spills start_pos=(-76.149368,37.74496,0) print "Uncertain move" self.ccm.prepare_for_model_step(self.cm.model_time, self.cm.time_step, 1, spill_size) self.ccm.get_move( self.cm.model_time, self.cm.time_step, self.cm.ref, self.cm.delta_uncertainty, self.cm.status, spill_type.uncertainty, ) def check_move(self): self.move() print self.cm.delta assert np.all(self.cm.delta['lat'] != 0) assert np.all(self.cm.delta['long'] != 0) def check_move_uncertain(self): self.move_uncertain() print self.cm.delta_uncertainty assert np.all(self.cm.delta_uncertainty['lat'] != 0) assert np.all(self.cm.delta_uncertainty['long'] != 0) def check_move_certain_uncertain(self,uncertain_time_delay=0): self.check_move() self.check_move_uncertain() tol = 1e-5 msg = r"{0} move is not within a tolerance of {1}" if uncertain_time_delay == 0: assert np.all(self.cm.delta_uncertainty['lat'] != self.cm.delta['lat']) assert np.all(self.cm.delta_uncertainty['long'] != self.cm.delta['long']) if uncertain_time_delay > 0: np.testing.assert_allclose( self.cm.delta['lat'], self.cm.delta_uncertainty['lat'], tol, tol, msg.format('current_cycle.nc', tol), 0, ) np.testing.assert_allclose( self.cm.delta['long'], self.cm.delta_uncertainty['long'], tol, tol, msg.format('current_cycle.nc', tol), 0, ) def test_move_tri(self): """ test move for a triangular grid (first time in file) """ time = datetime.datetime(2014, 6, 9, 0) self.cm.model_time = time_utils.date_to_sec(time) self.ccm.text_read(time_grid_file, topology_file) # self.ccm.export_topology(topology_file2) self.cm.ref[:]['long'] = -66.991344 # for Passamaquoddy self.cm.ref[:]['lat'] = 45.059316 self.check_move() actual = np.empty((self.cm.num_le, ), dtype=world_point) actual[:]['lat'] = .00020319 actual[:]['long'] = -.0001276599 tol = 1e-5 msg = r"{0} move is not within a tolerance of {1}" np.testing.assert_allclose( self.cm.delta['lat'], actual['lat'], tol, tol, msg.format('PQBayCur.nc4', tol), 0, ) np.testing.assert_allclose( self.cm.delta['long'], actual['long'], tol, tol, msg.format('PQBayCur.nc4', tol), 0, ) def test_move_tri_tide(self): """ test move for a triangular grid (first time in file) """ time = datetime.datetime(2014, 6, 9, 0) self.cm.model_time = time_utils.date_to_sec(time) self.cm.uncertain = True yeardata_path = os.path.join(os.path.dirname(gnome.__file__), 'data/yeardata/') self.shio = cy_shio_time.CyShioTime(tide_file) self.ccm.set_shio(self.shio) self.ccm.text_read(time_grid_file, topology_file) self.shio.set_shio_yeardata_path(yeardata_path) self.cm.ref[:]['long'] = -66.991344 # for Passamaquoddy self.cm.ref[:]['lat'] = 45.059316 #self.check_move() self.check_move_certain_uncertain(self.ccm.uncertain_time_delay) actual = np.empty((self.cm.num_le, ), dtype=world_point) actual[:]['lat'] = -.000440779 actual[:]['long'] = .00016611 tol = 1e-5 msg = r"{0} move is not within a tolerance of {1}" np.testing.assert_allclose( self.cm.delta['lat'], actual['lat'], tol, tol, msg.format('ches_bay', tol), 0, ) np.testing.assert_allclose( self.cm.delta['long'], actual['long'], tol, tol, msg.format('ches_bay', tol), 0, ) #check that certain and uncertain are the same if uncertainty is time delayed #self.ccm.uncertain_time_delay = 3 self.ccm.uncertain_time_delay = 10800 # cython expects time_delay in seconds self.check_move_certain_uncertain(self.ccm.uncertain_time_delay)