コード例 #1
0
    def __init__(self,
                 name=None,
                 units='kg/m^3',
                 temperature=None,
                 salinity=None):
        if (temperature is None or
                salinity is None or
                not isinstance(temperature, TemperatureTS) or
                not isinstance(salinity, SalinityTS)):
            raise ValueError('Must provide temperature and salinity '
                             'time series Environment objects')

        if len(temperature.time.time) > len(salinity.time.time):
            density_times = temperature.time
        else:
            density_times = salinity.time

        dummy_pt = np.array([[0, 0], ])

        import gsw
        from gnome import constants

        data = [gsw.rho(salinity.at(dummy_pt, t),
                        temperature.at(dummy_pt, t, units='C'),
                        constants.atmos_pressure * 0.0001)
                for t in density_times.time]

        TimeseriesData.__init__(self, name, units, time=density_times,
                                data=data)
コード例 #2
0
    def __init__(self,
                 name=None,
                 units='kg/m^3',
                 temperature=None,
                 salinity=None):
        if (temperature is None or salinity is None
                or not isinstance(temperature, TemperatureTS)
                or not isinstance(salinity, SalinityTS)):
            raise ValueError('Must provide temperature and salinity '
                             'time series Environment objects')

        if len(temperature.time.time) > len(salinity.time.time):
            density_times = temperature.time
        else:
            density_times = salinity.time

        dummy_pt = np.array([
            [0, 0],
        ])

        import gsw
        from gnome import constants

        data = [
            gsw.rho(salinity.at(dummy_pt, t),
                    temperature.at(dummy_pt, t, units='C'),
                    constants.atmos_pressure * 0.0001)
            for t in density_times.time
        ]

        TimeseriesData.__init__(self,
                                name,
                                units,
                                time=density_times,
                                data=data)
コード例 #3
0
    def constant(cls,
                 name='',
                 speed=0,
                 direction=0,
                 units='m/s'):
        """
        utility to create a constant wind "timeseries"

        :param speed: speed of wind
        :param direction: direction -- degrees True, direction wind is from
                          (degrees True)
        :param units='m/s': units for speed, as a string, i.e. "knots", "m/s",
                           "cm/s", etc.

        .. note::
            The time for a constant wind timeseries is irrelevant. This
            function simply sets it to datetime.now() accurate to hours.
        """
        direction = direction * -1 - 90

        u = speed * np.cos(direction * np.pi / 180)
        v = speed * np.sin(direction * np.pi / 180)

        u = TimeseriesData.constant('u', units, u)
        v = TimeseriesData.constant('v', units, v)

        return super(VelocityTS, cls).constant(name, units, variables=[u, v])
コード例 #4
0
    def constant(cls,
                 name='',
                 speed=0,
                 direction=0,
                 units='m/s'):
        """
        utility to create a constant wind "timeseries"

        :param speed: speed of wind
        :param direction: direction -- degrees True, direction wind is from
                          (degrees True)
        :param units='m/s': units for speed, as a string, i.e. "knots", "m/s",
                           "cm/s", etc.

        .. note::
            The time for a constant wind timeseries is irrelevant. This
            function simply sets it to datetime.now() accurate to hours.
        """
        direction = direction * -1 - 90

        u = speed * np.cos(direction * np.pi / 180)
        v = speed * np.sin(direction * np.pi / 180)

        u = TimeseriesData.constant('u', units, u)
        v = TimeseriesData.constant('v', units, v)

        return super(VelocityTS, cls).constant(name, units, variables=[u, v])
コード例 #5
0
    def build_test_instance(self, dates, series_data, series_data2):
        times = Time(dates)

        return TimeseriesVector(variables=[
            TimeseriesData(name='u', time=times, data=series_data),
            TimeseriesData(name='v', time=times, data=series_data2)
        ],
                                units='m/s')
コード例 #6
0
    def __init__(self, name=None, units='K', time=None, data=None, **kwargs):
        if 'timeseries' in kwargs:
            ts = kwargs['timeseries']

            time = map(lambda e: e[0], ts)
            data = np.array(map(lambda e: e[1], ts))

        TimeseriesData.__init__(self, name, units, time, data=data)
コード例 #7
0
    def get_tsv_instance(self, dates, series_data, series_data2):
        _t = Time(dates)

        return TimeseriesVector(variables=[
            TimeseriesData(name='u', time=_t, data=series_data),
            TimeseriesData(name='v', time=_t, data=series_data2)
        ],
                                units='m/s')
コード例 #8
0
    def demo(cls):
        _t = Time(dates())
        tsv = TimeseriesVector(variables=[
            TimeseriesData(name='u', time=_t, data=series_data()),
            TimeseriesData(name='v', time=_t, data=series_data2())
        ],
                               units='m/s')

        return DemoObj(variable=tsv, variables=[tsv, tsv.variables[0]])
コード例 #9
0
    def __init__(self, name=None, units='K',
                 time=None, data=None,
                 **kwargs):
        if 'timeseries' in kwargs:
            ts = kwargs['timeseries']

            time = map(lambda e: e[0], ts)
            data = np.array(map(lambda e: e[1], ts))

        TimeseriesData.__init__(self, name, units, time, data=data)
コード例 #10
0
 def generate_release_timeseries(self, num_ts, max_release, ts):
     '''
     Release timeseries describe release behavior as a function of time.
     _release_ts describes the number of LEs that should exist at time T
     _pos_ts describes the spill position at time T
     All use TimeseriesData objects.
     '''
     t = None
     if num_ts == 1:
         #This is a special case, when the release is short enough a single
         #timestep encompasses the whole thing.
         if self.release_duration == 0:
             t = Time([
                 self.release_time,
                 self.end_release_time + timedelta(seconds=1)
             ])
         else:
             t = Time([self.release_time, self.end_release_time])
     else:
         t = Time([
             self.release_time + timedelta(seconds=ts * step)
             for step in range(0, num_ts + 1)
         ])
         t.data[-1] = self.end_release_time
     self._release_ts = TimeseriesData(name=self.name + '_release_ts',
                                       time=t,
                                       data=np.linspace(
                                           0, max_release,
                                           num_ts + 1).astype(int))
     lon_ts = TimeseriesData(name=self.name + '_lon_ts',
                             time=t,
                             data=np.linspace(self.start_position[0],
                                              self.end_position[0],
                                              num_ts + 1))
     lat_ts = TimeseriesData(name=self.name + '_lat_ts',
                             time=t,
                             data=np.linspace(self.start_position[1],
                                              self.end_position[1],
                                              num_ts + 1))
     z_ts = TimeseriesData(name=self.name + '_z_ts',
                           time=t,
                           data=np.linspace(self.start_position[2],
                                            self.end_position[2],
                                            num_ts + 1))
     self._pos_ts = TimeseriesVector(name=self.name + '_pos_ts',
                                     time=t,
                                     variables=[lon_ts, lat_ts, z_ts])
コード例 #11
0
    def test_save_load(self, dates, series_data, series_data2):
        times = Time(dates)
        tsv = TimeseriesVector(variables=[
            TimeseriesData(name='u', time=times, data=series_data),
            TimeseriesData(name='v', time=times, data=series_data2)
        ],
                               units='m/s')

        inst = DemoObj(filename=None,
                       variable=tsv,
                       variables=[tsv, tsv.variables[0]])

        saveloc = tempfile.mkdtemp()
        _json_, zipfile_, _refs = inst.save(saveloc=saveloc)
        loaded = DemoObj.load(zipfile_)

        assert inst == loaded
コード例 #12
0
    def test_serialization(self, dates, series_data, series_data2):
        filename = 'foo.nc'
        times = Time(dates)
        tsv = TimeseriesVector(variables=[
            TimeseriesData(name='u', time=times, data=series_data),
            TimeseriesData(name='v', time=times, data=series_data2)
        ],
                               units='m/s')

        inst = DemoObj(filename=filename,
                       variable=tsv,
                       variables=[tsv, tsv.variables[0]])
        serial = inst.serialize()
        deser = DemoObj.deserialize(serial)

        assert deser.variable == inst.variable
        assert deser.variables == inst.variables
        assert deser.filename == 'foo.nc'
コード例 #13
0
    def test_serialization_options(self, dates, series_data, series_data2):
        times = Time(dates)
        tsv = TimeseriesVector(variables=[
            TimeseriesData(name='u', time=times, data=series_data),
            TimeseriesData(name='v', time=times, data=series_data2)
        ],
                               units='m/s')

        # kludge for platform differences
        # It should work for the platform the test is running on:
        if os.name == 'posix':
            filename = 'some/random/path/foo.nc'
        else:  # if not posix, should be windows
            filename = os.path.normpath('C:\\foo.nc')

        inst = DemoObj(filename=filename,
                       variable=tsv,
                       variables=[tsv, tsv.variables[0]])
        serial = inst.serialize(options={'raw_paths': False})

        assert serial['filename'] == 'foo.nc'
コード例 #14
0
    def __init__(self, angle=None, **kwargs):
        """
            :param angle: scalar field of cell rotation angles
                          (for rotated/distorted grids)
        """
        if 'variables' in kwargs:
            variables = kwargs['variables']
            if len(variables) == 2:
                variables.append(
                    TimeseriesData(name='constant w',
                                   data=[0.0],
                                   time=Time.constant_time(),
                                   units='m/s'))

            kwargs['variables'] = variables

        if angle is None:
            df = None

            if kwargs.get('dataset', None) is not None:
                df = kwargs['dataset']
            elif kwargs.get('grid_file', None) is not None:
                df = gridded.utilities.get_dataset(kwargs['grid_file'])

            if df is not None and 'angle' in df.variables.keys():
                # Unrotated ROMS Grid!
                self.angle = Variable(name='angle',
                                      units='radians',
                                      time=Time.constant_time(),
                                      grid=kwargs['grid'],
                                      data=df['angle'])
            else:
                self.angle = None
        else:
            self.angle = angle

        super(VelocityGrid, self).__init__(**kwargs)
コード例 #15
0
class PointLineRelease(Release):
    """
    The primary spill source class  --  a release of floating
    non-weathering particles, can be instantaneous or continuous, and be
    released at a single point, or over a line.
    """
    _schema = PointLineReleaseSchema

    def __init__(self,
                 release_time=None,
                 start_position=None,
                 num_elements=None,
                 num_per_timestep=None,
                 end_release_time=None,
                 end_position=None,
                 release_mass=0,
                 **kwargs):
        """
        Required Arguments:

        :param release_time: time the LEs are released (datetime object)
        :type release_time: datetime.datetime

        :param start_position: initial location the elements are released
        :type start_position: 3-tuple of floats (long, lat, z)

        Optional arguments:

        .. note:: Either num_elements or num_per_timestep must be given. If
            both are None, then it defaults to num_elements=1000. If both are
            given a TypeError is raised because user can only specify one or
            the other, not both.

        :param num_elements: total number of elements to be released
        :type num_elements: integer

        :param num_per_timestep: fixed number of LEs released at each timestep
        :type num_elements: integer

        :param end_release_time=None: optional -- for a time varying release,
            the end release time. If None, then release is instantaneous
        :type end_release_time: datetime.datetime

        :param end_position=None: optional. For moving source, the end position
            If None, then release from a point source
        :type end_position: 3-tuple of floats (long, lat, z)

        :param release_mass=0: optional. This is the mass released in kilograms.

        :type release_mass: integer

        num_elements and release_time passed to base class __init__ using super
        See base :class:`Release` documentation
        """

        self._num_elements = self._num_per_timestep = None

        if num_elements is None and num_per_timestep is None:
            num_elements = 1000
        super(PointLineRelease, self).__init__(release_time=release_time,
                                               num_elements=num_elements,
                                               release_mass=release_mass,
                                               **kwargs)

        if num_elements is not None and num_per_timestep is not None:
            msg = ('Either num_elements released or a release rate, defined by'
                   ' num_per_timestep must be given, not both')
            raise TypeError(msg)
        self._num_per_timestep = num_per_timestep

        # initializes internal variables: _end_release_time, _start_position,
        # _end_position
        self.end_release_time = asdatetime(end_release_time)
        self.start_position = start_position
        self.end_position = end_position

    def __repr__(self):
        return ('{0.__class__.__module__}.{0.__class__.__name__}('
                'release_time={0.release_time!r}, '
                'num_elements={0.num_elements}, '
                'start_position={0.start_position!r}, '
                'end_position={0.end_position!r}, '
                'end_release_time={0.end_release_time!r}'
                ')'.format(self))

    @property
    def is_pointsource(self):
        '''
        if end_position - start_position == 0, point source
        otherwise it is a line source

        :returns: True if point source, false otherwise
        '''
        if self.end_position is None:
            return True

        if np.all(self.end_position == self.start_position):
            return True

        return False

    @property
    def release_duration(self):
        '''
        duration over which particles are released in seconds
        '''
        if self.end_release_time is None:
            return 0
        else:
            return (self.end_release_time - self.release_time).total_seconds()

    @property
    def end_release_time(self):
        if self._end_release_time is None:
            return self.release_time
        else:
            return self._end_release_time

    @end_release_time.setter
    def end_release_time(self, val):
        '''
        Set end_release_time.
        If end_release_time is None or if end_release_time == release_time,
        it is an instantaneous release.

        Also update reference to set_newparticle_positions - if this was
        previously an instantaneous release but is now timevarying, we need
        to update this method
        '''
        val = asdatetime(val)
        if val is not None and self.release_time > val:
            raise ValueError('end_release_time must be greater than '
                             'release_time')

        self._end_release_time = val

    @property
    def num_per_timestep(self):
        return self._num_per_timestep

    @num_per_timestep.setter
    def num_per_timestep(self, val):
        '''
        Defines fixed number of LEs released per timestep

        Setter does the following:

        1. sets num_per_timestep attribute
        2. sets num_elements to None since total elements depends on duration
            and timestep
        3. invokes _reference_to_num_elements_to_release(), which updates the
            method referenced by num_elements_to_release
        '''
        self._num_per_timestep = val
        if val is not None or val < 0:
            self._num_elements = None

    @Release.num_elements.setter
    def num_elements(self, val):
        '''
        over ride base class setter. Makes num_per_timestep None since only one
        can be set at a time
        '''
        if val is None:
            self._num_elements = val
            if self._num_per_timestep is None:
                self._num_per_timestep = 1
        elif val < 0:
            raise ValueError('number of elements cannot be less than 0')
        else:
            self._num_elements = val
        if val is not None:
            self._num_per_timestep = None

    @property
    def start_position(self):
        return self._start_position

    @start_position.setter
    def start_position(self, val):
        '''
        set start_position and also make _delta_pos = None so it gets
        recomputed when model runs - it should be updated
        '''
        self._start_position = np.array(val, dtype=world_point_type).reshape(
            (3, ))

    @property
    def end_position(self):
        if self._end_position is None:
            return self.start_position
        else:
            return self._end_position

    @end_position.setter
    def end_position(self, val):
        '''
        set end_position and also make _delta_pos = None so it gets
        recomputed - it should be updated

        :param val: Set end_position to val. This can be None if release is a
            point source.
        '''
        if val is not None:
            val = np.array(val, dtype=world_point_type).reshape((3, ))

        self._end_position = val

    def LE_timestep_ratio(self, ts):
        '''
        Returns the ratio
        '''
        if self.num_elements is None and self.num_per_timestep is not None:
            return self.num_per_timestep
        return 1.0 * self.num_elements / self.get_num_release_time_steps(ts)

    def generate_release_timeseries(self, num_ts, max_release, ts):
        '''
        Release timeseries describe release behavior as a function of time.
        _release_ts describes the number of LEs that should exist at time T
        _pos_ts describes the spill position at time T
        All use TimeseriesData objects.
        '''
        t = None
        if num_ts == 1:
            #This is a special case, when the release is short enough a single
            #timestep encompasses the whole thing.
            if self.release_duration == 0:
                t = Time([
                    self.release_time,
                    self.end_release_time + timedelta(seconds=1)
                ])
            else:
                t = Time([self.release_time, self.end_release_time])
        else:
            t = Time([
                self.release_time + timedelta(seconds=ts * step)
                for step in range(0, num_ts + 1)
            ])
            t.data[-1] = self.end_release_time
        if self.release_duration == 0:
            self._release_ts = TimeseriesData(name=self.name + '_release_ts',
                                              time=t,
                                              data=np.full(
                                                  t.data.shape,
                                                  max_release).astype(int))
        else:
            self._release_ts = TimeseriesData(name=self.name + '_release_ts',
                                              time=t,
                                              data=np.linspace(
                                                  0, max_release,
                                                  num_ts + 1).astype(int))
        lon_ts = TimeseriesData(name=self.name + '_lon_ts',
                                time=t,
                                data=np.linspace(self.start_position[0],
                                                 self.end_position[0],
                                                 num_ts + 1))
        lat_ts = TimeseriesData(name=self.name + '_lat_ts',
                                time=t,
                                data=np.linspace(self.start_position[1],
                                                 self.end_position[1],
                                                 num_ts + 1))
        z_ts = TimeseriesData(name=self.name + '_z_ts',
                              time=t,
                              data=np.linspace(self.start_position[2],
                                               self.end_position[2],
                                               num_ts + 1))
        self._pos_ts = TimeseriesVector(name=self.name + '_pos_ts',
                                        time=t,
                                        variables=[lon_ts, lat_ts, z_ts])

    def rewind(self):
        self._prepared = False
        self._mass_per_le = 0
        self._release_ts = None
        self._pos_ts = None

    def prepare_for_model_run(self, ts):
        '''
        :param ts: integer seconds
        :param amount: integer kilograms
        '''
        if self._prepared:
            self.rewind()
        if self.LE_timestep_ratio(ts) < 1:
            raise ValueError('Not enough LEs: Number of LEs must at least \
                be equal to the number of timesteps in the release')

        num_ts = self.get_num_release_time_steps(ts)
        max_release = 0
        if self.num_per_timestep is not None:
            max_release = self.num_per_timestep * num_ts
        else:
            max_release = self.num_elements

        self.generate_release_timeseries(num_ts, max_release, ts)
        self._prepared = True
        self._mass_per_le = self.release_mass * 1.0 / max_release

    def num_elements_after_time(self, current_time, time_step):
        '''
        Returns the number of elements expected to exist at current_time+time_step.
        Returns 0 if prepare_for_model_run has not been called.
        :param ts: integer seconds
        :param amount: integer kilograms
        '''
        if not self._prepared:
            return 0
        if current_time < self.release_time:
            return 0
        return int(
            math.ceil(
                self._release_ts.at(None,
                                    current_time +
                                    timedelta(seconds=time_step),
                                    extrapolate=True)))

    def initialize_LEs(self, to_rel, data, current_time, time_step):
        '''
        Initializes the mass and position for num_released new LEs.
        current_time = datetime.datetime
        time_step = integer seconds
        '''
        if (time_step == 0):
            time_step = 1  #to deal with initializing position in instantaneous release case

        sl = slice(-to_rel, None, 1)
        start_position = self._pos_ts.at(None, current_time, extrapolate=True)
        end_position = self._pos_ts.at(None,
                                       current_time +
                                       timedelta(seconds=time_step),
                                       extrapolate=True)
        data['positions'][sl, 0] = \
            np.linspace(start_position[0],
                        end_position[0],
                        to_rel)
        data['positions'][sl, 1] = \
            np.linspace(start_position[1],
                        end_position[1],
                        to_rel)
        data['positions'][sl, 2] = \
            np.linspace(start_position[2],
                        end_position[2],
                        to_rel)
        data['mass'][sl] = self._mass_per_le
        data['init_mass'][sl] = self._mass_per_le
コード例 #16
0
 def get_tsd_instance(self, dates, series_data):
     return TimeseriesData(time=Time(dates), data=series_data, units='m')