def __init__(self, filename,
                 topology_file=None,
                 extrapolate=False,
                 time_offset=0,
                 current_scale=1,
                 uncertain_along=0.5,
                 uncertain_across=0.25,
                 **kwargs):
        """
        Initialize a GridCurrentMover

        :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 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(GridCurrentMover,self).__init__(\*\*kwargs)
        """

        # if child is calling, the self.mover is set by child - do not reset
        if type(self) == GridCurrentMover:
            self.mover = CyGridCurrentMover()

        if not os.path.exists(filename):
            raise ValueError('Path for current file does not exist: {0}'
                             .format(filename))

        if topology_file is not None:
            if not os.path.exists(topology_file):
                raise ValueError('Path for Topology file does not exist: {0}'
                                 .format(topology_file))

        # check if this is stored with cy_gridcurrent_mover?
        self.filename = filename
        self.name = os.path.split(filename)[1]

        # check if this is stored with cy_gridcurrent_mover?
        self.topology_file = topology_file
        self.current_scale = current_scale
        self.uncertain_along = uncertain_along
        self.uncertain_across = uncertain_across
        self.mover.text_read(filename, topology_file)
        self.mover.extrapolate_in_time(extrapolate)
        self.mover.offset_time(time_offset * 3600.)

        super(GridCurrentMover, self).__init__(**kwargs)
Example #2
0
def test_init():
    kwargs = {'current_scale': 2,
              'uncertain_duration': 10*3600,
              'uncertain_time_delay': 900,
              'uncertain_along': 0.75,
              'uncertain_cross': 0.5}
    gcm = CyGridCurrentMover(**kwargs)
    for key, val in kwargs.iteritems():
        assert getattr(gcm, key) == val
Example #3
0
    def __init__(self,
                 filename,
                 topology_file=None,
                 extrapolate=False,
                 time_offset=0,
                 current_scale=1,
                 uncertain_along=0.5,
                 uncertain_across=0.25,
                 num_method='Euler',
                 **kwargs):
        """
        Initialize a GridCurrentMover

        :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 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
        :param num_method: Numerical method for calculating movement delta.
                           Default Euler
                           option: Runga-Kutta 4 (RK4)

        uses super, super(GridCurrentMover,self).__init__(\*\*kwargs)
        """
        # if child is calling, the self.mover is set by child - do not reset
        if type(self) == GridCurrentMover:
            self.mover = CyGridCurrentMover()

        if not os.path.exists(filename):
            raise ValueError(
                'Path for current file does not exist: {0}'.format(filename))

        if topology_file is not None:
            if not os.path.exists(topology_file):
                raise ValueError(
                    'Path for Topology file does not exist: {0}'.format(
                        topology_file))

        super(GridCurrentMover, self).__init__(**kwargs)

        # check if this is stored with cy_gridcurrent_mover?
        self.filename = filename
        self.name = os.path.split(filename)[1]

        # check if this is stored with cy_gridcurrent_mover?
        self.topology_file = topology_file
        self.current_scale = current_scale
        self.uncertain_along = uncertain_along
        self.uncertain_across = uncertain_across

        self.mover.text_read(filename, topology_file)
        self.mover.extrapolate_in_time(extrapolate)
        self.mover.offset_time(time_offset * 3600.)

        self.num_method = num_method

        if self.topology_file is None:
            # this causes an error saving for currents that don't have topology
            #self.topology_file = filename + '.dat'
            #self.export_topology(self.topology_file)
            temp_topology_file = filename + '.dat'
            self.export_topology(temp_topology_file)
            if os.path.exists(temp_topology_file):
                self.topology_file = temp_topology_file
Example #4
0
class GridCurrentMover(CurrentMoversBase):

    _schema = GridCurrentMoverSchema

    def __init__(self,
                 filename,
                 topology_file=None,
                 extrapolate=False,
                 time_offset=0,
                 current_scale=1,
                 uncertain_along=0.5,
                 uncertain_across=0.25,
                 num_method='Euler',
                 **kwargs):
        """
        Initialize a GridCurrentMover

        :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 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
        :param num_method: Numerical method for calculating movement delta.
                           Default Euler
                           option: Runga-Kutta 4 (RK4)

        uses super, super(GridCurrentMover,self).__init__(\*\*kwargs)
        """
        # if child is calling, the self.mover is set by child - do not reset
        if type(self) == GridCurrentMover:
            self.mover = CyGridCurrentMover()

        if not os.path.exists(filename):
            raise ValueError(
                'Path for current file does not exist: {0}'.format(filename))

        if topology_file is not None:
            if not os.path.exists(topology_file):
                raise ValueError(
                    'Path for Topology file does not exist: {0}'.format(
                        topology_file))

        super(GridCurrentMover, self).__init__(**kwargs)

        # check if this is stored with cy_gridcurrent_mover?
        self.filename = filename
        self.name = os.path.split(filename)[1]

        # check if this is stored with cy_gridcurrent_mover?
        self.topology_file = topology_file
        self.current_scale = current_scale
        self.uncertain_along = uncertain_along
        self.uncertain_across = uncertain_across

        self.mover.text_read(filename, topology_file)
        self.mover.extrapolate_in_time(extrapolate)
        self.mover.offset_time(time_offset * 3600.)

        self.num_method = num_method

        if self.topology_file is None:
            # this causes an error saving for currents that don't have topology
            #self.topology_file = filename + '.dat'
            #self.export_topology(self.topology_file)
            temp_topology_file = filename + '.dat'
            self.export_topology(temp_topology_file)
            if os.path.exists(temp_topology_file):
                self.topology_file = temp_topology_file

    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_range={1.active_range}, '
                '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}\n'
                '  active_range time={1.active_range}\n'
                '  current on/off status={1.on}'.format(self.mover, self))

    # Define properties using lambda functions: uses lambda function, which are
    # accessible via fget/fset as follows:
    uncertain_cross = property(
        lambda self: self.mover.uncertain_cross,
        lambda self, val: setattr(self.mover, 'uncertain_cross', val))

    uncertain_along = property(
        lambda self: self.mover.uncertain_along,
        lambda self, val: setattr(self.mover, 'uncertain_along', val))

    current_scale = property(
        lambda self: self.mover.current_scale,
        lambda self, val: setattr(self.mover, 'current_scale', val))

    extrapolate = property(
        lambda self: self.mover.extrapolate,
        lambda self, val: setattr(self.mover, 'extrapolate', val))

    time_offset = property(
        lambda self: self.mover.time_offset / 3600.,
        lambda self, val: setattr(self.mover, 'time_offset', val * 3600.))

    @property
    def data_start(self):
        return sec_to_datetime(self.mover.get_start_time())

    @property
    def data_stop(self):
        return sec_to_datetime(self.mover.get_end_time())

    @property
    def num_method(self):
        return self._num_method

    @num_method.setter
    def num_method(self, val):
        self.mover.num_method = val
        self._num_method = val

    @property
    def is_data_on_cells(self):
        return self.mover._is_data_on_cells()

    def get_grid_data(self):
        """
            The main function for getting grid data from the mover
        """
        if self.mover._is_triangle_grid():
            return self.get_triangles()
        else:
            return self.get_cells()

    def get_center_points(self):
        if self.mover._is_triangle_grid():
            if self.mover._is_data_on_cells():
                return self.get_triangle_center_points()
            else:
                return self.get_points()
        else:
            return self.get_cell_center_points()

    def get_scaled_velocities(self, time):
        """
        :param model_time=0:
        """
        num_tri = self.mover.get_num_triangles()

        # will need to update this for regular grids
        if self.mover._is_triangle_grid():
            if self.mover._is_data_on_cells():
                num_cells = num_tri
            else:
                num_vertices = self.mover.get_num_points()
                num_cells = num_vertices
        elif self.mover._is_regular_grid():
            num_cells = self.mover.get_num_points()
        else:
            num_cells = num_tri / 2

        vels = np.zeros(num_cells, dtype=basic_types.velocity_rec)

        self.mover.get_scaled_velocities(time, vels)

        return vels

    def export_topology(self, topology_file):
        """
        :param topology_file=None: absolute or relative path where
                                   topology file will be written.
        """
        if topology_file is None:
            raise ValueError(
                'Topology file path required: {0}'.format(topology_file))

        self.mover.export_topology(topology_file)

    def extrapolate_in_time(self, extrapolate):
        """
        :param extrapolate=false: allow current data to be extrapolated
                                  before and after file data.
        """
        self.mover.extrapolate_in_time(extrapolate)

    def offset_time(self, time_offset):
        """
        :param offset_time=0: allow data to be in GMT with a time zone offset
                              (hours).
        """
        self.mover.offset_time(time_offset * 3600.)

    def get_offset_time(self):
        """
        :param offset_time=0: allow data to be in GMT with a time zone offset
                              (hours).
        """
        return self.mover.get_offset_time() / 3600.

    def get_start_time(self):
        """
        :this will be the real_data_start time (seconds).
        """
        return self.mover.get_start_time()

    def get_end_time(self):
        """
        :this will be the real_data_stop time (seconds).
        """
        return self.mover.get_end_time()

    def get_num_method(self):
        return self.mover.num_method
Example #5
0
    def __init__(self, filename,
                 topology_file=None,
                 extrapolate=False,
                 time_offset=0,
                 current_scale=1,
                 uncertain_along=0.5,
                 uncertain_across=0.25,
                 num_method='Euler',
                 **kwargs):
        """
        Initialize a GridCurrentMover

        :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 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
        :param num_method: Numerical method for calculating movement delta.
                           Default Euler
                           option: Runga-Kutta 4 (RK4)

        uses super, super(GridCurrentMover,self).__init__(\*\*kwargs)
        """
        # if child is calling, the self.mover is set by child - do not reset
        if type(self) == GridCurrentMover:
            self.mover = CyGridCurrentMover()

        if not os.path.exists(filename):
            raise ValueError('Path for current file does not exist: {0}'
                             .format(filename))

        if topology_file is not None:
            if not os.path.exists(topology_file):
                raise ValueError('Path for Topology file does not exist: {0}'
                                 .format(topology_file))

        super(GridCurrentMover, self).__init__(**kwargs)

        # check if this is stored with cy_gridcurrent_mover?
        self.filename = filename
        self.name = os.path.split(filename)[1]

        # check if this is stored with cy_gridcurrent_mover?
        self.topology_file = topology_file
        self.current_scale = current_scale
        self.uncertain_along = uncertain_along
        self.uncertain_across = uncertain_across

        self.mover.text_read(filename, topology_file)
        self.mover.extrapolate_in_time(extrapolate)
        self.mover.offset_time(time_offset * 3600.)

        self.num_method = num_method

        if self.topology_file is None:
            # this causes an error saving for currents that don't have topology
            #self.topology_file = filename + '.dat'
            #self.export_topology(self.topology_file)
            temp_topology_file = filename + '.dat'
            self.export_topology(temp_topology_file)
            if os.path.exists(temp_topology_file):
                self.topology_file = temp_topology_file
Example #6
0
class GridCurrentMover(CurrentMoversBase):

    _schema = GridCurrentMoverSchema

    def __init__(self, filename,
                 topology_file=None,
                 extrapolate=False,
                 time_offset=0,
                 current_scale=1,
                 uncertain_along=0.5,
                 uncertain_across=0.25,
                 num_method='Euler',
                 **kwargs):
        """
        Initialize a GridCurrentMover

        :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 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
        :param num_method: Numerical method for calculating movement delta.
                           Default Euler
                           option: Runga-Kutta 4 (RK4)

        uses super, super(GridCurrentMover,self).__init__(\*\*kwargs)
        """
        # if child is calling, the self.mover is set by child - do not reset
        if type(self) == GridCurrentMover:
            self.mover = CyGridCurrentMover()

        if not os.path.exists(filename):
            raise ValueError('Path for current file does not exist: {0}'
                             .format(filename))

        if topology_file is not None:
            if not os.path.exists(topology_file):
                raise ValueError('Path for Topology file does not exist: {0}'
                                 .format(topology_file))

        super(GridCurrentMover, self).__init__(**kwargs)

        # check if this is stored with cy_gridcurrent_mover?
        self.filename = filename
        self.name = os.path.split(filename)[1]

        # check if this is stored with cy_gridcurrent_mover?
        self.topology_file = topology_file
        self.current_scale = current_scale
        self.uncertain_along = uncertain_along
        self.uncertain_across = uncertain_across

        self.mover.text_read(filename, topology_file)
        self.mover.extrapolate_in_time(extrapolate)
        self.mover.offset_time(time_offset * 3600.)

        self.num_method = num_method

        if self.topology_file is None:
            # this causes an error saving for currents that don't have topology
            #self.topology_file = filename + '.dat'
            #self.export_topology(self.topology_file)
            temp_topology_file = filename + '.dat'
            self.export_topology(temp_topology_file)
            if os.path.exists(temp_topology_file):
                self.topology_file = temp_topology_file

    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_range={1.active_range}, '
                '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}\n'
                '  active_range time={1.active_range}\n'
                '  current on/off status={1.on}'
                .format(self.mover, self))

    # Define properties using lambda functions: uses lambda function, which are
    # accessible via fget/fset as follows:
    uncertain_cross = property(lambda self: self.mover.uncertain_cross,
                               lambda self, val: setattr(self.mover,
                                                         'uncertain_cross',
                                                         val))

    uncertain_along = property(lambda self: self.mover.uncertain_along,
                               lambda self, val: setattr(self.mover,
                                                         'uncertain_along',
                                                         val))

    current_scale = property(lambda self: self.mover.current_scale,
                             lambda self, val: setattr(self.mover,
                                                       'current_scale',
                                                       val))

    extrapolate = property(lambda self: self.mover.extrapolate,
                           lambda self, val: setattr(self.mover,
                                                     'extrapolate',
                                                     val))

    time_offset = property(lambda self: self.mover.time_offset / 3600.,
                           lambda self, val: setattr(self.mover,
                                                     'time_offset',
                                                     val * 3600.))

    @property
    def data_start(self):
        return sec_to_datetime(self.mover.get_start_time())

    @property
    def data_stop(self):
        return sec_to_datetime(self.mover.get_end_time())

    @property
    def num_method(self):
        return self._num_method

    @num_method.setter
    def num_method(self, val):
        self.mover.num_method = val
        self._num_method = val

    @property
    def is_data_on_cells(self):
        return self.mover._is_data_on_cells()

    def get_grid_data(self):
        """
            The main function for getting grid data from the mover
        """
        if self.mover._is_triangle_grid():
            return self.get_triangles()
        else:
            return self.get_cells()

    def get_center_points(self):
        if self.mover._is_triangle_grid():
            if self.mover._is_data_on_cells():
                return self.get_triangle_center_points()
            else:
                return self.get_points()
        else:
            return self.get_cell_center_points()

    def get_scaled_velocities(self, time):
        """
        :param model_time=0:
        """
        num_tri = self.mover.get_num_triangles()

        # will need to update this for regular grids
        if self.mover._is_triangle_grid():
            if self.mover._is_data_on_cells():
                num_cells = num_tri
            else:
                num_vertices = self.mover.get_num_points()
                num_cells = num_vertices
        elif self.mover._is_regular_grid():
            num_cells = self.mover.get_num_points()
        else:
            num_cells = num_tri / 2

        vels = np.zeros(num_cells, dtype=basic_types.velocity_rec)

        self.mover.get_scaled_velocities(time, vels)

        return vels

    def export_topology(self, topology_file):
        """
        :param topology_file=None: absolute or relative path where
                                   topology file will be written.
        """
        if topology_file is None:
            raise ValueError('Topology file path required: {0}'
                             .format(topology_file))

        self.mover.export_topology(topology_file)

    def extrapolate_in_time(self, extrapolate):
        """
        :param extrapolate=false: allow current data to be extrapolated
                                  before and after file data.
        """
        self.mover.extrapolate_in_time(extrapolate)

    def offset_time(self, time_offset):
        """
        :param offset_time=0: allow data to be in GMT with a time zone offset
                              (hours).
        """
        self.mover.offset_time(time_offset * 3600.)

    def get_offset_time(self):
        """
        :param offset_time=0: allow data to be in GMT with a time zone offset
                              (hours).
        """
        return self.mover.get_offset_time() / 3600.

    def get_start_time(self):
        """
        :this will be the real_data_start time (seconds).
        """
        return self.mover.get_start_time()

    def get_end_time(self):
        """
        :this will be the real_data_stop time (seconds).
        """
        return self.mover.get_end_time()

    def get_num_method(self):
        return self.mover.num_method
class GridCurrentMover(CurrentMoversBase, serializable.Serializable):

    _update = ['uncertain_cross', 'uncertain_along', 'current_scale']
    _save = ['uncertain_cross', 'uncertain_along', 'current_scale']
    _state = copy.deepcopy(CurrentMoversBase._state)

    _state.add(update=_update, save=_save)
    _state.add_field([serializable.Field('filename',
                                         save=True, read=True, isdatafile=True,
                                         test_for_eq=False),
                      serializable.Field('topology_file',
                                         save=True, read=True, isdatafile=True,
                                         test_for_eq=False)])
    _schema = GridCurrentMoverSchema

    def __init__(self, filename,
                 topology_file=None,
                 extrapolate=False,
                 time_offset=0,
                 current_scale=1,
                 uncertain_along=0.5,
                 uncertain_across=0.25,
                 **kwargs):
        """
        Initialize a GridCurrentMover

        :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 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(GridCurrentMover,self).__init__(\*\*kwargs)
        """

        # if child is calling, the self.mover is set by child - do not reset
        if type(self) == GridCurrentMover:
            self.mover = CyGridCurrentMover()

        if not os.path.exists(filename):
            raise ValueError('Path for current file does not exist: {0}'
                             .format(filename))

        if topology_file is not None:
            if not os.path.exists(topology_file):
                raise ValueError('Path for Topology file does not exist: {0}'
                                 .format(topology_file))

        # check if this is stored with cy_gridcurrent_mover?
        self.filename = filename
        self.name = os.path.split(filename)[1]

        # check if this is stored with cy_gridcurrent_mover?
        self.topology_file = topology_file
        self.current_scale = current_scale
        self.uncertain_along = uncertain_along
        self.uncertain_across = uncertain_across
        self.mover.text_read(filename, topology_file)
        self.mover.extrapolate_in_time(extrapolate)
        self.mover.offset_time(time_offset * 3600.)

        super(GridCurrentMover, self).__init__(**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}\n'
                '  active_start time={1.active_start}\n'
                '  active_stop time={1.active_stop}\n'
                '  current on/off status={1.on}'
                .format(self.mover, self))

    # Define properties using lambda functions: uses lambda function, which are
    # accessible via fget/fset as follows:
    uncertain_cross = property(lambda self: self.mover.uncertain_cross,
                               lambda self, val: setattr(self.mover,
                                                         'uncertain_cross',
                                                         val))

    uncertain_along = property(lambda self: self.mover.uncertain_along,
                               lambda self, val: setattr(self.mover,
                                                         'uncertain_along',
                                                         val))

    current_scale = property(lambda self: self.mover.current_scale,
                             lambda self, val: setattr(self.mover,
                                                       'current_scale',
                                                       val))

    extrapolate = property(lambda self: self.mover.extrapolate,
                           lambda self, val: setattr(self.mover,
                                                     'extrapolate',
                                                     val))

    time_offset = property(lambda self: self.mover.time_offset / 3600.,
                           lambda self, val: setattr(self.mover,
                                                     'time_offset',
                                                     val * 3600.))

    def get_grid_data(self):
        """
            The main function for getting grid data from the mover
        """
        if self.mover._is_triangle_grid():
            return self.get_triangles()
        else:
            return self.get_cells()

    def get_center_points(self):
        if self.mover._is_triangle_grid():
            return self.get_triangle_center_points()
        else:
            return self.get_cell_center_points()

    def get_scaled_velocities(self, time):
        """
        :param model_time=0:
        """
        num_tri = self.mover.get_num_triangles()
        vels = np.zeros(num_tri, dtype=basic_types.velocity_rec)

        self.mover.get_scaled_velocities(time, vels)

        return vels

    def export_topology(self, topology_file):
        """
        :param topology_file=None: absolute or relative path where
                                   topology file will be written.
        """
        if topology_file is None:
            raise ValueError('Topology file path required: {0}'
                             .format(topology_file))

        self.mover.export_topology(topology_file)

    def extrapolate_in_time(self, extrapolate):
        """
        :param extrapolate=false: allow current data to be extrapolated
                                  before and after file data.
        """
        self.mover.extrapolate_in_time(extrapolate)

    def offset_time(self, time_offset):
        """
        :param offset_time=0: allow data to be in GMT with a time zone offset
                              (hours).
        """
        self.mover.offset_time(time_offset * 3600.)

    def get_offset_time(self):
        """
        :param offset_time=0: allow data to be in GMT with a time zone offset
                              (hours).
        """
        return (self.mover.get_offset_time()) / 3600.
Example #8
0
class TestGridCurrentMover:

    cm = Common()
    gcm = CyGridCurrentMover()

    # delta = np.zeros((cm.num_le,), dtype=world_point)

    def move(self):
        self.gcm.prepare_for_model_run()

        print "Certain move"
        self.gcm.prepare_for_model_step(self.cm.model_time, self.cm.time_step)
        self.gcm.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.gcm.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.gcm.prepare_for_model_step(self.cm.model_time, self.cm.time_step,
                                        1, spill_size)
        self.gcm.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('grid_current.nc', tol),
                0,
            )
            np.testing.assert_allclose(
                self.cm.delta['long'],
                self.cm.delta_uncertainty['long'],
                tol,
                tol,
                msg.format('grid_current.nc', tol),
                0,
            )

    def test_move_reg(self):
        """
        test move for a regular grid (first time in file)
        """

        time = datetime.datetime(1999, 11, 29, 21)
        self.cm.model_time = time_utils.date_to_sec(time)

        time_grid_file = testdata['GridCurrentMover']['curr_reg']

        self.gcm.text_read(time_grid_file)
        self.cm.ref[:]['long'] = 3.104588  # for simple example
        self.cm.ref[:]['lat'] = 52.016468
        self.check_move()

        actual = np.empty((self.cm.num_le, ), dtype=world_point)
        actual[:]['lat'] = .003354610952486354
        actual[:]['long'] = .0010056182923228838
        actual[:]['z'] = 0.
        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('test.cdf', tol),
            0,
        )
        np.testing.assert_allclose(
            self.cm.delta['long'],
            actual['long'],
            tol,
            tol,
            msg.format('test.cdf', tol),
            0,
        )

        # np.testing.assert_equal(self.cm.delta['z'], actual['z'],
        #                        "test_move_reg() failed", 0)

        np.all(self.cm.delta['z'] == 0)

    def test_move_curv(self):
        """
        test move for a curvilinear grid (first time in file)
        """

        time = datetime.datetime(2008, 1, 29, 17)
        self.cm.model_time = time_utils.date_to_sec(time)

        time_grid_file = testdata['GridCurrentMover']['curr_curv']
        topology_file = testdata['GridCurrentMover']['top_curv']

        self.gcm.text_read(time_grid_file, topology_file)

        # self.gcm.export_topology(topology_file2)

        self.cm.ref[:]['long'] = -74.03988  # for NY
        self.cm.ref[:]['lat'] = 40.536092
        self.check_move()

        actual = np.empty((self.cm.num_le, ), dtype=world_point)
        actual[:]['lat'] = .000911
        actual[:]['long'] = -.001288
        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('ny_cg.nc', tol),
            0,
        )
        np.testing.assert_allclose(
            self.cm.delta['long'],
            actual['long'],
            tol,
            tol,
            msg.format('ny_cg.nc', tol),
            0,
        )

    def test_move_curv_no_top(self):
        """
        test move for a curvilinear grid (first time in file)
        """

        time = datetime.datetime(2008, 1, 29, 17)
        self.cm.model_time = time_utils.date_to_sec(time)

        time_grid_file = testdata['GridCurrentMover']['curr_curv']
        self.gcm.text_read(time_grid_file, topology_file=None)

        topology_file2 = os.path.join(
            os.path.split(time_grid_file)[0], 'NYTopologyNew.dat')
        self.gcm.export_topology(topology_file2)
        self.cm.ref[:]['long'] = -74.03988  # for NY
        self.cm.ref[:]['lat'] = 40.536092
        self.check_move()

        actual = np.empty((self.cm.num_le, ), dtype=world_point)
        actual[:]['lat'] = .000911
        actual[:]['long'] = -.001288
        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('ny_cg.nc', tol),
            0,
        )
        np.testing.assert_allclose(
            self.cm.delta['long'],
            actual['long'],
            tol,
            tol,
            msg.format('ny_cg.nc', tol),
            0,
        )

    def test_move_curv_series(self):
        """
        Test a curvilinear file series
        - time in first file
        - time in second file
        """

        # time = datetime.datetime(2009, 8, 2, 0)  # first file

        time = datetime.datetime(2009, 8, 9, 0)  # second file
        self.cm.model_time = time_utils.date_to_sec(time)

        time_grid_file = testdata['GridCurrentMover']['series_curv']
        topology_file = testdata['GridCurrentMover']['series_top']

        self.gcm.text_read(time_grid_file, topology_file)
        self.cm.ref[:]['long'] = -157.795728  # for HiROMS
        self.cm.ref[:]['lat'] = 21.069288
        self.check_move()

        actual = np.empty((self.cm.num_le, ), dtype=world_point)
        #actual[:]['lat'] = -.003850193  # file 2
        #actual[:]['long'] = .000152012
        # updated to new curvilinear algorithm
        actual[:]['lat'] = .00292  # file 2
        actual[:]['long'] = .00051458
        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('HiROMS', tol),
            0,
        )
        np.testing.assert_allclose(
            self.cm.delta['long'],
            actual['long'],
            tol,
            tol,
            msg.format('HiROMS', tol),
            0,
        )

    def test_move_tri(self):
        """
        test move for a triangular grid (first time in file)
        """

        time = datetime.datetime(2004, 12, 31, 13)
        self.cm.model_time = time_utils.date_to_sec(time)
        self.cm.uncertain = True

        time_grid_file = testdata['GridCurrentMover']['curr_tri']
        topology_file = testdata['GridCurrentMover']['top_tri']

        self.gcm.text_read(time_grid_file, topology_file)
        self.cm.ref[:]['long'] = -76.149368  # for ChesBay
        self.cm.ref[:]['lat'] = 37.74496
        #self.check_move()
        self.check_move_certain_uncertain(self.gcm.uncertain_time_delay)

        actual = np.empty((self.cm.num_le, ), dtype=world_point)
        actual[:]['lat'] = .00148925
        actual[:]['long'] = .00088789
        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.gcm.uncertain_time_delay = 3
        self.gcm.uncertain_time_delay = 10800  # cython expects time_delay in seconds
        self.check_move_certain_uncertain(self.gcm.uncertain_time_delay)

    def test_move_ptcur(self):
        """
        test move for a ptCur grid (first time in file)
        """

        time = datetime.datetime(2000, 2, 14, 10)
        self.cm.model_time = time_utils.date_to_sec(time)

        time_grid_file = testdata['GridCurrentMover']['ptCur']

        self.gcm.text_read(time_grid_file)
        self.cm.ref[:]['long'] = -124.686928  # for ptCur test
        self.cm.ref[:]['lat'] = 48.401124
        self.check_move()

        actual = np.empty((self.cm.num_le, ), dtype=world_point)
        actual[:]['lat'] = .0161987
        actual[:]['long'] = -.02439887
        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('ptcur', tol),
            0,
        )
        np.testing.assert_allclose(
            self.cm.delta['long'],
            actual['long'],
            tol,
            tol,
            msg.format('ptcur', tol),
            0,
        )

    def test_move_ptcur_extrapolate(self):
        """
        test move for a ptCur grid (first time in file)
        """

        time = datetime.datetime(2000, 2, 14,
                                 8)  # time before first time in file
        self.cm.model_time = time_utils.date_to_sec(time)

        time_grid_file = testdata['GridCurrentMover']['ptCur']

        self.gcm.text_read(time_grid_file)
        self.gcm.extrapolate_in_time(
            True)  # result of move should be same as first step
        self.cm.ref[:]['long'] = -124.686928  # for ptCur test
        self.cm.ref[:]['lat'] = 48.401124
        self.check_move()

        actual = np.empty((self.cm.num_le, ), dtype=world_point)
        actual[:]['lat'] = .0161987
        actual[:]['long'] = -.02439887
        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('ptcur', tol),
            0,
        )
        np.testing.assert_allclose(
            self.cm.delta['long'],
            actual['long'],
            tol,
            tol,
            msg.format('ptcur', tol),
            0,
        )

    def test_move_gridcurtime(self):
        """
        test move for a gridCurTime, grid current time series, file (first time
        in file)
        """

        time = datetime.datetime(2002, 1, 30, 1)
        self.cm.model_time = time_utils.date_to_sec(time)

        time_grid_file = testdata['GridCurrentMover']['grid_ts']

        self.gcm.text_read(time_grid_file)
        self.cm.ref[:]['long'] = -119.933264  # for gridCur test
        self.cm.ref[:]['lat'] = 34.138736
        self.check_move()

        actual = np.empty((self.cm.num_le, ), dtype=world_point)
        actual[:]['lat'] = -0.0034527536849574456
        actual[:]['long'] = 0.005182449331779978
        actual[:]['z'] = 0.
        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('gridcurtime', tol),
            0,
        )
        np.testing.assert_allclose(
            self.cm.delta['long'],
            actual['long'],
            tol,
            tol,
            msg.format('gridcurtime', tol),
            0,
        )

        # np.testing.assert_equal(self.cm.delta, actual,
        #                        "test_move_gridcurtime() failed", 0)

        np.all(self.cm.delta['z'] == 0)

    def test_move_gridcur_series(self):
        """
        test move for a gridCur file series (first time in first file)
        """

        time = datetime.datetime(2002, 1, 30, 1)
        self.cm.model_time = time_utils.date_to_sec(time)

        time_grid_file = testdata['GridCurrentMover']['series_gridCur']
        topology_file = r""

        self.gcm.text_read(time_grid_file, topology_file)
        self.cm.ref[:]['long'] = -119.933264  # for gridCur test
        self.cm.ref[:]['lat'] = 34.138736
        self.check_move()

        actual = np.empty((self.cm.num_le, ), dtype=world_point)
        actual[:]['lat'] = -0.0034527536849574456
        actual[:]['long'] = 0.005182449331779978
        actual[:]['z'] = 0.
        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('gridcur series', tol),
            0,
        )
        np.testing.assert_allclose(
            self.cm.delta['long'],
            actual['long'],
            tol,
            tol,
            msg.format('gridcur series', tol),
            0,
        )

        # np.testing.assert_equal(self.cm.delta, actual,
        #                        "test_move_gridcur_series() failed", 0)

        np.all(self.cm.delta['z'] == 0)