Exemplo n.º 1
0
Arquivo: mock.py Projeto: cpaulik/cis
def make_square_NxM_2d_cube_with_time(start_lat=-10, end_lat=10, lat_point_count=5,
                                      start_lon=-5, end_lon=5, lon_point_count=3,
                                      time_offset=0):
    """
        Makes a well defined cube of shape 5x3 with data as follows
        arr([[[   1.    2.    3.    4.    5.    6.    7.]
              [   8.    9.   10.   11.   12.   13.   14.]
              [  15.   16.   17.   18.   19.   20.   21.]]

             [[  22.   23.   24.   25.   26.   27.   28.]
              [  29.   30.   31.   32.   33.   34.   35.]
              [  36.   37.   38.   39.   40.   41.   42.]]

             [[  43.   44.   45.   46.   47.   48.   49.]
              [  50.   51.   52.   53.   54.   55.   56.]
              [  57.   58.   59.   60.   61.   62.   63.]]

             [[  64.   65.   66.   67.   68.   69.   70.]
              [  71.   72.   73.   74.   75.   76.   77.]
              [  78.   79.   80.   81.   82.   83.   84.]]

             [[  85.   86.   87.   88.   89.   90.   91.]
              [  92.   93.   94.   95.   96.   97.   98.]
              [  99.  100.  101.  102.  103.  104.  105.]]])
        and coordinates in latitude:
            array([ -10, -5, 0, 5, 10 ])
        longitude:
            array([ -5, 0, 5 ])
        time:
            array([1984-08-27, 1984-08-28, 1984-08-29, 1984-08-30, 1984-08-31, 1984-09-01, 1984-09-02])

        They are different lengths to make it easier to distinguish. Note the latitude increases
        as you step through the array in order - so downwards as it's written above
    """
    import numpy as np
    from iris.cube import Cube
    from iris.coords import DimCoord
    import datetime
    from cis.time_util import convert_obj_to_standard_date_array

    t0 = datetime.datetime(1984, 8, 27)
    times = np.array([t0 + datetime.timedelta(days=d + time_offset) for d in xrange(7)])

    time_nums = convert_obj_to_standard_date_array(times)

    time = DimCoord(time_nums, standard_name='time')
    latitude = DimCoord(np.linspace(start_lat, end_lat, lat_point_count), standard_name='latitude', units='degrees')
    longitude = DimCoord(np.linspace(start_lon, end_lon, lon_point_count), standard_name='longitude', units='degrees')
    data = np.reshape(np.arange(lat_point_count * lon_point_count * 7) + 1.0, (lat_point_count, lon_point_count, 7))
    cube = Cube(data, dim_coords_and_dims=[(latitude, 0), (longitude, 1), (time, 2)], var_name='dummy')

    return cube
Exemplo n.º 2
0
    def index_data(self, coords, hyper_points, coord_map):
        """
        Index the data that falls inside the grid cells

        :param coords: coordinates of grid
        :param hyper_points: list of HyperPoints to index
        :param coord_map: list of tuples relating index in HyperPoint to index in coords and in
                          coords to be iterated over
        """

        # create bounds in correct order
        hp_coords = []
        coord_descreasing = [False] * len(coords)
        coord_lengths = [0] * len(coords)
        lower_bounds = [None] * len(coords)
        max_bounds = [None] * len(coords)
        for (hpi, ci, shi) in coord_map:
            coord = coords[ci]
            # Coordinates must be monotonic; determine whether increasing or decreasing.
            if len(coord.points) > 1:
                if coord.points[1] < coord.points[0]:
                    coord_descreasing[shi] = True
            coord_lengths[shi] = len(coord.points)
            if coord_descreasing[shi]:
                lower_bounds[shi] = coord.bounds[::-1, 1]
                max_bounds[shi] = coord.bounds[0, 1]
            else:
                lower_bounds[shi] = coord.bounds[::, 0]
                max_bounds[shi] = coord.bounds[-1, 1]

            hp_coord = hyper_points.coords[hpi]
            if isinstance(hp_coord[0], datetime.datetime):
                hp_coord = convert_obj_to_standard_date_array(hp_coord)

            hp_coords.append(hp_coord)

        bounds_coords_max = zip(lower_bounds, hp_coords, max_bounds)

        # stack for each coordinate
        #    where the coordinate is larger than the maximum set to -1
        #    otherwise search in the sorted coordinate to find all the index of the hyperpoints
        # The choice of 'left' or 'right' and '<' and '<=' determines which
        #  cell is chosen when the coordinate is equal to the boundary.
        # -1 or M_i indicates the point is outside the grid.
        # Output is a list of coordinates which lists the indexes where the hyper points
        #    should be located in the grid
        indices = np.vstack(
            np.where(
                ci < max_coordinate_value,
                np.searchsorted(bi, ci, side='right') - 1,
                -1)
            for bi, ci, max_coordinate_value in bounds_coords_max)

        # D-tuple giving the shape of the output grid
        grid_shape = tuple(len(bi_ci[0]) for bi_ci in bounds_coords_max)

        # shape (N,) telling which points actually fall within the grid,
        # i.e. have indexes that are not -1 and are not masked data points
        grid_mask = np.all(
            (indices >= 0) &
            (ma.getmaskarray(hyper_points.data) == False),
            axis=0)

        # if the coordinate was decreasing then correct the indices for this cell
        for indices_slice, decreasing, coord_length in zip(xrange(indices.shape[0]), coord_descreasing, coord_lengths):
            if decreasing:
                # indices[indices_slice] += (coord_length - 1) - indices[indices_slice]
                indices[indices_slice] *= -1
                indices[indices_slice] += (coord_length - 1)

        # shape (N,) containing negative scalar cell numbers for each
        # input point (sequence doesn't matter so long as they are unique), or
        # -1 for points outside the grid.
        #
        # Possibly numpy.lexsort could be used to avoid the need for this,
        # although we'd have to be careful about points outside the grid.
        self.cell_numbers = np.where(
            grid_mask,
            np.tensordot(
                np.cumproduct((1,) + grid_shape[:-1]),
                indices,
                axes=1
            ),
            -1)

        # Sort everything by cell number
        self.sort_order = np.argsort(self.cell_numbers)
        self.cell_numbers = self.cell_numbers[self.sort_order]
        self._indices = indices[:, self.sort_order]
        self.hp_coords = [hp_coord[self.sort_order] for hp_coord in hp_coords]
Exemplo n.º 3
0
Arquivo: mock.py Projeto: cpaulik/cis
def make_regular_4d_ungridded_data():
    """
        Makes a well defined ungridded data object of shape 10x5 with data as follows

        data:
        [[  1.   2.   3.   4.   5.]
         [  6.   7.   8.   9.  10.]
         [ 11.  12.  13.  14.  15.]
         [ 16.  17.  18.  19.  20.]
         [ 21.  22.  23.  24.  25.]
         [ 26.  27.  28.  29.  30.]
         [ 31.  32.  33.  34.  35.]
         [ 36.  37.  38.  39.  40.]
         [ 41.  42.  43.  44.  45.]
         [ 46.  47.  48.  49.  50.]]

        latitude:
        [[-10.  -5.   0.   5.  10.]
         [-10.  -5.   0.   5.  10.]
         [-10.  -5.   0.   5.  10.]
         [-10.  -5.   0.   5.  10.]
         [-10.  -5.   0.   5.  10.]
         [-10.  -5.   0.   5.  10.]
         [-10.  -5.   0.   5.  10.]
         [-10.  -5.   0.   5.  10.]
         [-10.  -5.   0.   5.  10.]
         [-10.  -5.   0.   5.  10.]]

        longitude:
        [[-5.  -2.5  0.   2.5  5. ]
         [-5.  -2.5  0.   2.5  5. ]
         [-5.  -2.5  0.   2.5  5. ]
         [-5.  -2.5  0.   2.5  5. ]
         [-5.  -2.5  0.   2.5  5. ]
         [-5.  -2.5  0.   2.5  5. ]
         [-5.  -2.5  0.   2.5  5. ]
         [-5.  -2.5  0.   2.5  5. ]
         [-5.  -2.5  0.   2.5  5. ]
         [-5.  -2.5  0.   2.5  5. ]]

        altitude:
        [[  0.   0.   0.   0.   0.]
         [ 10.  10.  10.  10.  10.]
         [ 20.  20.  20.  20.  20.]
         [ 30.  30.  30.  30.  30.]
         [ 40.  40.  40.  40.  40.]
         [ 50.  50.  50.  50.  50.]
         [ 60.  60.  60.  60.  60.]
         [ 70.  70.  70.  70.  70.]
         [ 80.  80.  80.  80.  80.]
         [ 90.  90.  90.  90.  90.]]

        pressure:
        [[  4.   4.   4.   4.   4.]
         [ 16.  16.  16.  16.  16.]
         [ 20.  20.  20.  20.  20.]
         [ 30.  30.  30.  30.  30.]
         [ 40.  40.  40.  40.  40.]
         [ 50.  50.  50.  50.  50.]
         [ 60.  60.  60.  60.  60.]
         [ 70.  70.  70.  70.  70.]
         [ 80.  80.  80.  80.  80.]
         [ 90.  90.  90.  90.  90.]]

        time:
        [[1984-08-27 1984-08-28 1984-08-29 1984-08-30 1984-08-31]
         [1984-08-27 1984-08-28 1984-08-29 1984-08-30 1984-08-31]
         [1984-08-27 1984-08-28 1984-08-29 1984-08-30 1984-08-31]
         [1984-08-27 1984-08-28 1984-08-29 1984-08-30 1984-08-31]
         [1984-08-27 1984-08-28 1984-08-29 1984-08-30 1984-08-31]
         [1984-08-27 1984-08-28 1984-08-29 1984-08-30 1984-08-31]
         [1984-08-27 1984-08-28 1984-08-29 1984-08-30 1984-08-31]
         [1984-08-27 1984-08-28 1984-08-29 1984-08-30 1984-08-31]
         [1984-08-27 1984-08-28 1984-08-29 1984-08-30 1984-08-31]
         [1984-08-27 1984-08-28 1984-08-29 1984-08-30 1984-08-31]]

        They are shaped to represent a typical lidar type satelite data set.
    """
    import numpy as np
    from cis.data_io.Coord import CoordList, Coord
    from cis.data_io.ungridded_data import UngriddedData, Metadata
    import datetime
    from cis.time_util import convert_obj_to_standard_date_array

    x_points = np.linspace(-10, 10, 5)
    y_points = np.linspace(-5, 5, 5)
    t0 = datetime.datetime(1984, 8, 27)
    times = convert_obj_to_standard_date_array(np.array([t0 + datetime.timedelta(days=d) for d in xrange(5)]))

    alt = np.linspace(0, 90, 10)

    data = np.reshape(np.arange(50) + 1.0, (10, 5))
    # print np.mean(data[:,1:3])
    # print np.mean(data[4:6,:])
    # print np.mean(data[:,2])
    # print np.std(data)
    # print np.mean(data)
    # print len(data.flat)

    y, a = np.meshgrid(y_points, alt)
    x, a = np.meshgrid(x_points, alt)
    t, a = np.meshgrid(times, alt)
    p = a
    p[0, :] = 4
    p[1, :] = 16

    a = Coord(a, Metadata(standard_name='altitude', units='meters'))
    x = Coord(x, Metadata(standard_name='latitude', units='degrees'))
    y = Coord(y, Metadata(standard_name='longitude', units='degrees'))
    p = Coord(p, Metadata(standard_name='air_pressure', units='Pa'))
    t = Coord(t, Metadata(standard_name='time', units='DateTime Object'))

    coords = CoordList([x, y, a, p, t])
    return UngriddedData(data, Metadata(standard_name='rain', long_name="TOTAL RAINFALL RATE: LS+CONV KG/M2/S",
                                        units="kg m-2 s-1", missing_value=-999), coords)
Exemplo n.º 4
0
Arquivo: mock.py Projeto: cpaulik/cis
def make_mock_cube(lat_dim_length=5, lon_dim_length=3, lon_range=None, alt_dim_length=0, pres_dim_length=0,
                   time_dim_length=0,
                   horizontal_offset=0, altitude_offset=0, pressure_offset=0, time_offset=0, data_offset=0,
                   hybrid_ht_len=0, hybrid_pr_len=0, dim_order=None, mask=False):
    """
    Makes a cube of any shape required, with coordinate offsets from the default available. If no arguments are
    given get a 5x3 cube of the form:
        array([[1,2,3],
               [4,5,6],
               [7,8,9],
               [10,11,12],
               [13,14,15]])
        and coordinates in latitude:
            array([ -10, -5, 0, 5, 10 ])
        longitude:
            array([ -5, 0, 5 ])
    :param lat_dim_length: Latitude grid length
    :param lon_dim_length: Longitude grid length
    :param alt_dim_length: Altitude grid length
    :param pres_dim_length: Pressure grid length
    :param time_dim_length: Time grid length
    :param horizontal_offset: Offset from the default grid, in degrees, in lat and lon
    :param altitude_offset: Offset from the default grid in altitude
    :param pressure_offset: Offset from the default grid in pressure
    :param time_offset: Offset from the default grid in time
    :param data_offset: Offset from the default data values
    :param hybrid_ht_len: Hybrid height grid length
    :param hybrid_pr_len: Hybrid pressure grid length
    :param dim_order: List of 'lat', 'lon', 'alt', 'pres', 'time' in the order in which the dimensions occur
    :param mask: A mask to apply to the data, this should be either a scalar or the same shape as the data
    :return: A cube with well defined data.
    """
    import iris
    from iris.aux_factory import HybridHeightFactory, HybridPressureFactory

    data_size = 1
    DIM_NAMES = ['lat', 'lon', 'alt', 'pres', 'time', 'hybrid_ht', 'hybrid_pr']
    dim_lengths = [lat_dim_length, lon_dim_length, alt_dim_length, pres_dim_length, time_dim_length, hybrid_ht_len,
                   hybrid_pr_len]
    lon_range = lon_range or (-5., 5.)

    if dim_order is None:
        dim_order = list(DIM_NAMES)

    if any([True for d in dim_order if d not in DIM_NAMES]):
        raise ValueError("dim_order contains unrecognised name")

    for idx, dim in enumerate(DIM_NAMES):
        if dim_lengths[idx] == 0 and dim in dim_order:
            del dim_order[dim_order.index(dim)]

    coord_map = {}
    for idx, dim in enumerate(dim_order):
        coord_map[dim] = dim_order.index(dim)
    coord_list = [None] * len(coord_map)

    if lat_dim_length:
        coord_list[coord_map['lat']] = (DimCoord(np.linspace(-10., 10., lat_dim_length) + horizontal_offset,
                                                 standard_name='latitude', units='degrees'), coord_map['lat'])
        data_size *= lat_dim_length

    if lon_dim_length:
        coord_list[coord_map['lon']] = (
            DimCoord(np.linspace(lon_range[0], lon_range[1], lon_dim_length) + horizontal_offset,
                     standard_name='longitude', units='degrees'), coord_map['lon'])
        data_size *= lon_dim_length

    if alt_dim_length:
        coord_list[coord_map['alt']] = (DimCoord(np.linspace(0., 7., alt_dim_length) + altitude_offset,
                                                 standard_name='altitude', units='metres'), coord_map['alt'])
        data_size *= alt_dim_length

    if pres_dim_length:
        coord_list[coord_map['pres']] = (DimCoord(np.linspace(0., 7., pres_dim_length) + pressure_offset,
                                                  standard_name='air_pressure', units='hPa'), coord_map['pres'])
        data_size *= pres_dim_length

    if time_dim_length:
        t0 = datetime.datetime(1984, 8, 27)
        times = np.array([t0 + datetime.timedelta(days=d + time_offset) for d in xrange(time_dim_length)])
        time_nums = convert_obj_to_standard_date_array(times)
        time_bounds = None
        if time_dim_length == 1:
            time_bounds = convert_obj_to_standard_date_array(np.array([times[0] - datetime.timedelta(days=0.5),
                                                                       times[0] + datetime.timedelta(days=0.5)]))
        coord_list[coord_map['time']] = (DimCoord(time_nums, standard_name='time',
                                                  units='days since 1600-01-01 00:00:00', bounds=time_bounds),
                                         coord_map['time'])
        data_size *= time_dim_length

    if hybrid_ht_len:
        coord_list[coord_map['hybrid_ht']] = (DimCoord(np.arange(hybrid_ht_len, dtype='i8') + 10,
                                                       "model_level_number", units="1"), coord_map['hybrid_ht'])
        data_size *= hybrid_ht_len

    if hybrid_pr_len:
        coord_list[coord_map['hybrid_pr']] = (DimCoord(np.arange(hybrid_pr_len, dtype='i8'),
                                                       "atmosphere_hybrid_sigma_pressure_coordinate", units="1"),
                                              coord_map['hybrid_pr'])
        data_size *= hybrid_pr_len

    data = np.reshape(np.arange(data_size) + data_offset + 1., tuple(len(i[0].points) for i in coord_list))

    if mask:
        data = np.ma.asarray(data)
        data.mask = mask

    return_cube = Cube(data, dim_coords_and_dims=coord_list)

    if hybrid_ht_len:
        return_cube.add_aux_coord(iris.coords.AuxCoord(np.arange(hybrid_ht_len, dtype='i8') + 40,
                                                       long_name="level_height",
                                                       units="m"), coord_map['hybrid_ht'])
        return_cube.add_aux_coord(iris.coords.AuxCoord(np.arange(hybrid_ht_len, dtype='i8') + 50,
                                                       long_name="sigma", units="1"), coord_map['hybrid_ht'])
        return_cube.add_aux_coord(iris.coords.AuxCoord(
            np.arange(lat_dim_length * lon_dim_length, dtype='i8').reshape(lat_dim_length, lon_dim_length) + 100,
            long_name="surface_altitude",
            units="m"), [coord_map['lat'], coord_map['lon']])

        return_cube.add_aux_factory(HybridHeightFactory(
            delta=return_cube.coord("level_height"),
            sigma=return_cube.coord("sigma"),
            orography=return_cube.coord("surface_altitude")))
    elif hybrid_pr_len:
        return_cube.add_aux_coord(iris.coords.AuxCoord(np.arange(hybrid_pr_len, dtype='i8') + 40,
                                                       long_name="hybrid A coefficient at layer midpoints",
                                                       units="Pa"), coord_map['hybrid_pr'])
        return_cube.add_aux_coord(iris.coords.AuxCoord(np.arange(hybrid_pr_len, dtype='f8') + 50,
                                                       long_name="hybrid B coefficient at layer midpoints", units="1"),
                                  coord_map['hybrid_pr'])
        return_cube.add_aux_coord(
            iris.coords.AuxCoord(np.arange(lat_dim_length * lon_dim_length * time_dim_length, dtype='i8')
                                 .reshape(lat_dim_length, lon_dim_length, time_dim_length) * 100000,
                                 "surface_air_pressure", units="Pa"),
            [coord_map['lat'], coord_map['lon'], coord_map['time']])

        return_cube.add_aux_coord(iris.coords.AuxCoord(
            np.arange(lat_dim_length * lon_dim_length * time_dim_length * hybrid_pr_len, dtype='i8')
            .reshape(lat_dim_length, lon_dim_length, time_dim_length, hybrid_pr_len) + 10,
            "altitude", long_name="Geopotential height at layer midpoints", units="meter"),
            [coord_map['lat'], coord_map['lon'], coord_map['time'], coord_map['hybrid_pr']])

        return_cube.add_aux_factory(HybridPressureFactory(
            delta=return_cube.coord("hybrid A coefficient at layer midpoints"),
            sigma=return_cube.coord("hybrid B coefficient at layer midpoints"),
            surface_air_pressure=return_cube.coord("surface_air_pressure")))

    for coord in return_cube.coords(dim_coords=True):
        if coord.bounds is None:
            coord.guess_bounds()

    return return_cube
Exemplo n.º 5
0
Arquivo: Coord.py Projeto: cpaulik/cis
 def convert_datetime_to_standard_time(self):
     from cis.time_util import convert_obj_to_standard_date_array, cis_standard_time_unit
     self._data = convert_obj_to_standard_date_array(self.data)
     self.units = str(cis_standard_time_unit)
     self.metadata.calendar = cis_standard_time_unit.calendar