Exemple #1
0
    def test_set_extrapolated_bounds(self):
        value_grid = [[[40.0, 40.0, 40.0, 40.0], [39.0, 39.0, 39.0, 39.0],
                       [38.0, 38.0, 38.0, 38.0]],
                      [[-100.0, -99.0, -98.0, -97.0],
                       [-100.0, -99.0, -98.0, -97.0],
                       [-100.0, -99.0, -98.0, -97.0]]]
        actual_corners = [[[[40.5, 40.5, 39.5, 39.5], [40.5, 40.5, 39.5, 39.5],
                            [40.5, 40.5, 39.5, 39.5], [40.5, 40.5, 39.5,
                                                       39.5]],
                           [[39.5, 39.5, 38.5, 38.5], [39.5, 39.5, 38.5, 38.5],
                            [39.5, 39.5, 38.5, 38.5], [39.5, 39.5, 38.5,
                                                       38.5]],
                           [[38.5, 38.5, 37.5, 37.5], [38.5, 38.5, 37.5, 37.5],
                            [38.5, 38.5, 37.5, 37.5], [38.5, 38.5, 37.5,
                                                       37.5]]],
                          [[[-100.5, -99.5, -99.5, -100.5],
                            [-99.5, -98.5, -98.5, -99.5],
                            [-98.5, -97.5, -97.5, -98.5],
                            [-97.5, -96.5, -96.5, -97.5]],
                           [[-100.5, -99.5, -99.5, -100.5],
                            [-99.5, -98.5, -98.5, -99.5],
                            [-98.5, -97.5, -97.5, -98.5],
                            [-97.5, -96.5, -96.5, -97.5]],
                           [[-100.5, -99.5, -99.5, -100.5],
                            [-99.5, -98.5, -98.5, -99.5],
                            [-98.5, -97.5, -97.5, -98.5],
                            [-97.5, -96.5, -96.5, -97.5]]]]

        for should_extrapolate in [False, True]:
            y = Variable(name='y',
                         value=value_grid[0],
                         dimensions=['ydim', 'xdim'])
            x = Variable(name='x',
                         value=value_grid[1],
                         dimensions=['ydim', 'xdim'])
            if should_extrapolate:
                y.set_extrapolated_bounds('ybounds', 'bounds')
                x.set_extrapolated_bounds('xbounds', 'bounds')
            grid = Grid(x, y)
            try:
                grid.set_extrapolated_bounds('ybounds', 'xbounds', 'bounds')
            except BoundsAlreadyAvailableError:
                self.assertTrue(should_extrapolate)
            else:
                np.testing.assert_equal(grid.y.bounds.get_value(),
                                        actual_corners[0])
                np.testing.assert_equal(grid.x.bounds.get_value(),
                                        actual_corners[1])

        # Test vectorized.
        y = Variable(name='y', value=[1., 2., 3.], dimensions='yy')
        x = Variable(name='x', value=[10., 20., 30.], dimensions='xx')
        grid = Grid(x, y)
        grid.set_extrapolated_bounds('ybounds', 'xbounds', 'bounds')
        self.assertEqual(grid.x.bounds.ndim, 2)
        self.assertTrue(grid.is_vectorized)
Exemple #2
0
    def test_system(self):
        from ocgis.regrid.base import create_esmf_grid, iter_esmf_fields, RegridOperation, destroy_esmf_objects
        import ESMF

        yc = Variable(name='yc', value=np.arange(-90 + (45 / 2.), 90, 45), dimensions='ydim', dtype=float)
        xc = Variable(name='xc', value=np.arange(15, 360, 30), dimensions='xdim', dtype=float)
        ogrid = Grid(y=yc, x=xc, crs=Spherical())
        ogrid.set_extrapolated_bounds('xc_bounds', 'yc_bounds', 'bounds')

        np.random.seed(1)
        mask = np.random.rand(*ogrid.shape)
        mask = mask > 0.5
        self.assertTrue(mask.sum() > 3)
        ogrid.set_mask(mask)

        egrid = create_esmf_grid(ogrid)
        actual_shape = egrid.size[0].tolist()
        desired_shape = np.flipud(ogrid.shape).tolist()
        self.assertEqual(actual_shape, desired_shape)
        desired = ogrid.get_value_stacked()
        desired = np.ma.array(desired, mask=False)
        desired.mask[0, :, :] = ogrid.get_mask()
        desired.mask[1, :, :] = ogrid.get_mask()
        desired = desired.sum()

        actual_col = egrid.get_coords(0)
        actual_row = egrid.get_coords(1)
        actual_mask = np.invert(egrid.mask[0].astype(bool))
        actual = np.ma.array(actual_row, mask=actual_mask).sum() + np.ma.array(actual_col, mask=actual_mask).sum()
        self.assertEqual(actual, desired)

        desired = 9900.0
        corners = egrid.coords[ESMF.StaggerLoc.CORNER]
        actual = corners[0].sum() + corners[1].sum()
        self.assertEqual(actual, desired)

        ofield = create_exact_field(ogrid, 'data', ntime=3, crs=Spherical())
        variable_name, efield, tidx = list(iter_esmf_fields(ofield, split=False))[0]
        desired_value = ofield['data'].get_value()
        self.assertAlmostEqual(efield.data.sum(), desired_value.sum(), places=3)

        destroy_esmf_objects([egrid, efield])

        ofield.grid.set_mask(ofield.grid.get_mask(), cascade=True)
        desired_value = ofield['data'].get_masked_value()
        keywords = dict(split=[False, True])
        for k in self.iter_product_keywords(keywords):
            opts = {'split': k.split}
            dofield = ofield.deepcopy()
            dofield['data'].get_value().fill(0)
            ro = RegridOperation(ofield, dofield, regrid_options=opts)
            actual_field = ro.execute()
            actual_value = actual_field['data'].get_masked_value()
            self.assertAlmostEqual(0.0, np.abs(desired_value - actual_value).max())
Exemple #3
0
    def test_set_extrapolated_bounds_empty(self):
        """Test bounds extrapolation works on empty objects."""

        dimx = Dimension('x', 2, is_empty=True, dist=True)
        x = Variable('x', dimensions=dimx)
        y = Variable('3', dimensions=Dimension('y', 3))
        grid = Grid(x, y)

        self.assertTrue(dimx.is_empty)
        self.assertTrue(x.is_empty)
        self.assertTrue(grid.is_empty)
        self.assertFalse(grid.has_bounds)
        self.assertEqual(grid.abstraction, 'point')

        grid.set_extrapolated_bounds('xbnds', 'ybnds', 'bounds')
        self.assertEqual(grid.abstraction, 'polygon')
        self.assertTrue(grid.has_bounds)
        self.assertTrue(grid.is_empty)
Exemple #4
0
    def test_get_field_write_target(self):
        # Test coordinate system names are added to attributes of dimensioned variables.
        x = Variable('x', dimensions='x', value=[1])
        y = Variable('y', dimensions='y', value=[2])
        t = Variable('t', dimensions='t', value=[3])
        crs = WGS84()
        d = Variable('data', dimensions=['t', 'y', 'x'], value=[[[1]]])
        grid = Grid(x, y)
        field = Field(grid=grid, time=t, crs=crs)
        field.add_variable(d, is_data=True)

        target = DriverNetcdfCF._get_field_write_target_(field)
        self.assertEqual(target[d.name].attrs['grid_mapping'], crs.name)
        self.assertEqual(field.x.units, 'degrees_east')

        # Test bounds units are removed when writing.
        x = Variable(name='x', value=[1, 2, 3], dtype=float, dimensions='xdim', units='hours')
        y = Variable(name='y', value=[1, 2, 3], dtype=float, dimensions='ydim', units='hours')
        grid = Grid(x, y)
        grid.set_extrapolated_bounds('x_bounds', 'y_bounds', 'bounds')
        self.assertEqual(x.bounds.units, x.units)
        self.assertEqual(y.bounds.units, y.units)
        field = Field(grid=grid)
        actual = DriverNetcdfCF._get_field_write_target_(field)
        self.assertEqual(x.bounds.units, x.units)
        self.assertNumpyMayShareMemory(actual[x.name].get_value(), field[x.name].get_value())
        self.assertIsNone(actual[x.name].bounds.units)
        self.assertIsNone(actual[y.name].bounds.units)
        self.assertEqual(x.bounds.units, x.units)
        self.assertEqual(y.bounds.units, y.units)

        # Test actual coordinate system is triggered.
        field = Field()
        src = CFSpherical()
        dst = WGS84()
        field.set_crs(src)
        self.assertEqual(field.crs, src)
        self.assertIsNone(env.COORDSYS_ACTUAL)
        env.COORDSYS_ACTUAL = dst
        actual = DriverNetcdfCF._get_field_write_target_(field)
        self.assertEqual(actual.crs, dst)
        self.assertEqual(field.crs, src)
        self.assertNotIn(src.name, actual)
        self.assertIn(dst.name, actual)
Exemple #5
0
    def test_init(self):
        # Test a field is always the parent of a grid.
        grid = self.get_gridxy()
        self.assertIsInstance(grid.parent, Field)

        crs = WGS84()
        grid = self.get_gridxy(crs=crs)
        self.assertIsInstance(grid, Grid)
        self.assertIn('x', grid.parent)
        self.assertIn('y', grid.parent)
        self.assertEqual(grid.crs, crs)
        self.assertEqual([dim.name for dim in grid.dimensions],
                         ['ydim', 'xdim'])
        self.assertEqual(grid.shape, (4, 3))
        self.assertTrue(grid.is_vectorized)
        self.assertEqual(grid.x.ndim, 1)
        self.assertEqual(grid.y.ndim, 1)

        # Test with different variable names.
        x = Variable(name='col', value=[1], dimensions='col')
        y = Variable(name='row', value=[2], dimensions='row')
        grid = Grid(x, y)
        assert_equal(grid.x.get_value(), [1])
        assert_equal(grid.y.get_value(), [2])

        # Test point and polygon representations.
        grid = self.get_gridxy(crs=WGS84())
        grid.set_extrapolated_bounds('x_bounds', 'y_bounds', 'bounds')
        targets = ['get_point', 'get_polygon']
        targets = [getattr(grid, t)() for t in targets]
        for t in targets:
            self.assertIsInstance(t, GeometryVariable)
        self.assertTrue(grid.is_vectorized)
        sub = grid[1, 1]
        targets = ['get_point', 'get_polygon']
        targets = [getattr(sub, t)() for t in targets]
        for t in targets:
            self.assertEqual(t.shape, (1, 1))
            self.assertIsInstance(t, GeometryVariable)
        self.assertTrue(grid.is_vectorized)
Exemple #6
0
    def test_get_field_write_target(self):
        # Test coordinate system names are added to attributes of dimensioned variables.
        x = Variable('x', dimensions='x', value=[1])
        y = Variable('y', dimensions='y', value=[2])
        t = Variable('t', dimensions='t', value=[3])
        crs = WGS84()
        d = Variable('data', dimensions=['t', 'y', 'x'], value=[[[1]]])
        grid = Grid(x, y)
        field = Field(grid=grid, time=t, crs=crs)
        field.add_variable(d, is_data=True)

        target = DriverNetcdfCF._get_field_write_target_(field)
        self.assertEqual(target[d.name].attrs['grid_mapping'], crs.name)
        self.assertEqual(field.x.units, 'degrees_east')

        # Test bounds units are removed when writing.
        x = Variable(name='x',
                     value=[1, 2, 3],
                     dtype=float,
                     dimensions='x',
                     units='hours')
        y = Variable(name='y',
                     value=[1, 2, 3],
                     dtype=float,
                     dimensions='x',
                     units='hours')
        grid = Grid(x, y)
        grid.set_extrapolated_bounds('x_bounds', 'y_bounds', 'bounds')
        self.assertEqual(x.bounds.units, x.units)
        self.assertEqual(y.bounds.units, y.units)
        field = Field(grid=grid)
        actual = DriverNetcdfCF._get_field_write_target_(field)
        self.assertEqual(x.bounds.units, x.units)
        self.assertNumpyMayShareMemory(actual[x.name].get_value(),
                                       field[x.name].get_value())
        self.assertIsNone(actual[x.name].bounds.units)
        self.assertIsNone(actual[y.name].bounds.units)
        self.assertEqual(x.bounds.units, x.units)
        self.assertEqual(y.bounds.units, y.units)
Exemple #7
0
    def test_system_line_subsetting(self):
        """Test subsetting with a line."""

        line = LineString([(-0.4, 0.2), (1.35, 0.3), (1.38, -0.716)])
        geom = [{'geom': line, 'crs': None}]

        x = Variable('x', [-1, -0.5, 0.5, 1.5, 2], 'x')
        y = Variable('y', [-0.5, 0.5, 1.5], 'y')
        grid = Grid(x, y)
        grid.set_extrapolated_bounds('x_bounds', 'y_bounds', 'bounds')
        field = Field(grid=grid)

        ops = OcgOperations(dataset=field, geom=geom)
        ret = ops.execute()
        field = ret.get_element()

        desired = [[[-0.5, -0.5, -0.5], [0.5, 0.5, 0.5]], [[-0.5, 0.5, 1.5], [-0.5, 0.5, 1.5]]]
        actual = field.grid.get_value_stacked().tolist()
        self.assertEqual(actual, desired)

        desired = [[True, True, False], [False, False, False]]
        actual = field.grid.get_mask().tolist()
        self.assertEqual(actual, desired)
Exemple #8
0
    def test_system(self):
        from ocgis.regrid.base import get_esmf_grid, iter_esmf_fields, RegridOperation, destroy_esmf_objects
        import ESMF

        yc = Variable(name='yc',
                      value=np.arange(-90 + (45 / 2.), 90, 45),
                      dimensions='ydim',
                      dtype=float)
        xc = Variable(name='xc',
                      value=np.arange(15, 360, 30),
                      dimensions='xdim',
                      dtype=float)
        ogrid = Grid(y=yc, x=xc, crs=Spherical())
        ogrid.set_extrapolated_bounds('xc_bounds', 'yc_bounds', 'bounds')

        np.random.seed(1)
        mask = np.random.rand(*ogrid.shape)
        mask = mask > 0.5
        self.assertTrue(mask.sum() > 3)
        ogrid.set_mask(mask)

        egrid = get_esmf_grid(ogrid)
        actual_shape = egrid.size[0].tolist()
        desired_shape = np.flipud(ogrid.shape).tolist()
        self.assertEqual(actual_shape, desired_shape)
        desired = ogrid.get_value_stacked()
        desired = np.ma.array(desired, mask=False)
        desired.mask[0, :, :] = ogrid.get_mask()
        desired.mask[1, :, :] = ogrid.get_mask()
        desired = desired.sum()

        actual_col = egrid.get_coords(0)
        actual_row = egrid.get_coords(1)
        actual_mask = np.invert(egrid.mask[0].astype(bool))
        actual = np.ma.array(actual_row, mask=actual_mask).sum() + np.ma.array(
            actual_col, mask=actual_mask).sum()
        self.assertEqual(actual, desired)

        desired = 9900.0
        corners = egrid.coords[ESMF.StaggerLoc.CORNER]
        actual = corners[0].sum() + corners[1].sum()
        self.assertEqual(actual, desired)

        ofield = create_exact_field(ogrid, 'data', ntime=3, crs=Spherical())
        variable_name, efield, tidx = list(
            iter_esmf_fields(ofield, split=False))[0]
        desired_value = ofield['data'].get_value()
        self.assertAlmostEqual(efield.data.sum(),
                               desired_value.sum(),
                               places=3)

        destroy_esmf_objects([egrid, efield])

        ofield.grid.set_mask(ofield.grid.get_mask(), cascade=True)
        desired_value = ofield['data'].get_masked_value()
        keywords = dict(split=[False, True])
        for k in self.iter_product_keywords(keywords):
            opts = {'split': k.split}
            dofield = ofield.deepcopy()
            dofield['data'].get_value().fill(0)
            ro = RegridOperation(ofield, dofield, regrid_options=opts)
            actual_field = ro.execute()
            actual_value = actual_field['data'].get_masked_value()
            self.assertAlmostEqual(0.0,
                                   np.abs(desired_value - actual_value).max())
Exemple #9
0
def get_ugrid_data_structure():
    x = Variable(name='node_x', value=[10, 20, 30], dtype=float, dimensions='x')
    y = Variable(name='node_y', value=[-60, -55, -50, -45, -40], dimensions='y')
    grid = Grid(x, y)
    grid.set_extrapolated_bounds('x_bounds', 'y_bounds', 'bounds')
    grid.expand()

    cindex = np.zeros((grid.archetype.size, 4), dtype=int)
    xc = grid.x.bounds.get_value().flatten()
    yc = grid.y.bounds.get_value().flatten()

    for eidx, (ridx, cidx) in enumerate(itertools.product(*[range(ii) for ii in grid.shape])):
        curr_element = grid[ridx, cidx]
        curr_xc = curr_element.x.bounds.get_value().flatten()
        curr_yc = curr_element.y.bounds.get_value().flatten()
        for element_node_idx in range(curr_xc.shape[0]):
            found_idx = find_index([xc, yc], [curr_xc[element_node_idx], curr_yc[element_node_idx]])
            cindex[eidx, element_node_idx] = found_idx

    new_cindex, uindices = reduce_reindex_coordinate_index(cindex.flatten(), start_index=0)
    new_cindex = new_cindex.reshape(*cindex.shape)
    xc = xc[uindices]
    yc = yc[uindices]

    centers = grid.get_value_stacked()
    center_xc = centers[1].flatten()
    center_yc = centers[0].flatten()

    longitude_attrs = {'standard_name': 'longitude', 'units': 'degrees_east'}
    latitude_attrs = {'standard_name': 'latitude', 'units': 'degrees_north'}

    vc = VariableCollection(attrs={'conventions': 'CF-1.6, UGRID-1.0'})
    face_center_x = Variable(name='face_center_x', value=center_xc, dimensions='n_face', parent=vc,
                             attrs=longitude_attrs, dtype=float)
    face_center_y = Variable(name='face_center_y', value=center_yc, dimensions='n_face', parent=vc,
                             attrs=latitude_attrs, dtype=float)

    face_node_index = Variable(name='face_node_index', value=new_cindex, dimensions=['n_face', 'max_nodes'],
                               parent=vc,
                               attrs={'standard_name': 'face_node_connectivity', 'order': 'counterclockwise'})

    face_node_x = Variable(name='face_node_x', value=xc, dimensions='n_node', parent=vc, attrs=longitude_attrs,
                           dtype=float)
    face_node_y = Variable(name='face_node_y', value=yc, dimensions='n_node', parent=vc, attrs=latitude_attrs,
                           dtype=float)

    mesh = Variable(name='mesh',
                    attrs={'standard_name': 'mesh_topology', 'cf_role': 'mesh_topology', 'dimension': 2,
                           'locations': 'face node', 'node_coordinates': 'face_node_x face_node_y',
                           'face_coordinates': 'face_center_x face_center_y',
                           'face_node_connectivity': 'face_node_index'},
                    parent=vc)

    # path = self.get_temporary_file_path('foo.nc')
    # vc.write(path)
    # self.ncdump(path)
    #

    # ==============================================================================================================
    # import matplotlib.pyplot as plt
    # from descartes import PolygonPatch
    # from shapely.geometry import Polygon, MultiPolygon
    #
    # BLUE = '#6699cc'
    # GRAY = '#999999'
    #
    # fig = plt.figure(num=1)
    # ax = fig.add_subplot(111)
    #
    # polys = []
    #
    # for face_idx in range(face_node_index.shape[0]):
    #     sub = face_node_index[face_idx, :].parent
    #     curr_cindex = sub[face_node_index.name].get_value().flatten()
    #     fcx = sub[face_node_x.name].get_value()[curr_cindex]
    #     fcy = sub[face_node_y.name].get_value()[curr_cindex]
    #
    #     coords = np.zeros((4, 2))
    #     coords[:, 0] = fcx
    #     coords[:, 1] = fcy
    #
    #     poly = Polygon(coords)
    #     polys.append(poly)
    #     patch = PolygonPatch(poly, fc=BLUE, ec=GRAY, alpha=0.5, zorder=2)
    #     ax.add_patch(patch)
    #
    # minx, miny, maxx, maxy = MultiPolygon(polys).bounds
    # w, h = maxx - minx, maxy - miny
    # ax.set_xlim(minx - 0.2 * w, maxx + 0.2 * w)
    # ax.set_ylim(miny - 0.2 * h, maxy + 0.2 * h)
    # ax.set_aspect(1)
    #
    # plt.scatter(center_xc, center_yc, zorder=1)
    #
    # plt.show()
    # ===============================================================================================================

    return vc