Exemple #1
0
 def test_unwrap(self):
     geom = box(195, -40, 225, -30)
     gvar = GeometryVariable(name='geoms', value=geom, crs=Spherical(), dimensions='geoms')
     gvar.wrap()
     self.assertEqual(gvar.get_value()[0].bounds, (-165.0, -40.0, -135.0, -30.0))
     gvar.unwrap()
     self.assertEqual(gvar.get_value()[0].bounds, (195.0, -40.0, 225.0, -30.0))
Exemple #2
0
    def test_update_crs_to_cartesian(self):
        """Test a spherical to cartesian CRS update."""

        bbox = box(-170., 40., 150., 80.)
        original_bounds = deepcopy(bbox.bounds)
        geom = GeometryVariable(name='geom', value=[bbox], dimensions='geom', crs=Spherical())

        other_crs = Cartesian()
        geom.update_crs(other_crs)
        actual = geom.get_value()[0].bounds
        desired = (-0.7544065067354889, -0.13302222155948895, -0.15038373318043535, 0.38302222155948895)
        self.assertNumpyAllClose(np.array(actual), np.array(desired))
        self.assertIsInstance(geom.crs, Cartesian)

        other_crs = Spherical()
        geom.update_crs(other_crs)
        self.assertEqual(geom.crs, Spherical())
        actual = geom.get_value()[0].bounds
        self.assertNumpyAllClose(np.array(original_bounds), np.array(actual))

        # Test data may not be wrapped.
        bbox = box(0, 40, 270, 80)
        geom = GeometryVariable(name='geom', value=[bbox], dimensions='geom', crs=Spherical())
        other_crs = Cartesian()
        with self.assertRaises(ValueError):
            geom.update_crs(other_crs)
Exemple #3
0
    def test_update_crs_to_cartesian(self):
        """Test a spherical to cartesian CRS update."""

        bbox = box(-170., 40., 150., 80.)
        original_bounds = deepcopy(bbox.bounds)
        geom = GeometryVariable(name='geom',
                                value=[bbox],
                                dimensions='geom',
                                crs=Spherical())

        other_crs = Cartesian()
        geom.update_crs(other_crs)
        actual = geom.get_value()[0].bounds
        desired = (-0.7544065067354889, -0.13302222155948895,
                   -0.15038373318043535, 0.38302222155948895)
        self.assertNumpyAllClose(np.array(actual), np.array(desired))
        self.assertIsInstance(geom.crs, Cartesian)

        other_crs = Spherical()
        geom.update_crs(other_crs)
        self.assertEqual(geom.crs, Spherical())
        actual = geom.get_value()[0].bounds
        self.assertNumpyAllClose(np.array(original_bounds), np.array(actual))

        # Test data may not be wrapped.
        bbox = box(0, 40, 270, 80)
        geom = GeometryVariable(name='geom',
                                value=[bbox],
                                dimensions='geom',
                                crs=Spherical())
        other_crs = Cartesian()
        with self.assertRaises(ValueError):
            geom.update_crs(other_crs)
Exemple #4
0
    def test_init(self):
        # Test empty.
        gvar = GeometryVariable()
        self.assertEqual(gvar.dtype, object)

        gvar = self.get_geometryvariable()
        self.assertIsInstance(gvar.get_masked_value(), MaskedArray)
        self.assertEqual(gvar.ndim, 1)

        # Test passing a "crs".
        gvar = self.get_geometryvariable(crs=WGS84(),
                                         name='my_geom',
                                         dimensions='ngeom')
        self.assertEqual(gvar.crs, WGS84())

        # Test using lines.
        line1 = LineString([(0, 0), (1, 1)])
        line2 = LineString([(1, 1), (2, 2)])
        gvar = GeometryVariable(value=[line1, line2], dimensions='two')
        self.assertTrue(gvar.get_value()[1].almost_equals(line2))
        self.assertEqual(gvar.geom_type, line1.geom_type)
        lines = MultiLineString([line1, line2])
        lines2 = [lines, lines]
        for actual in [lines, lines2, lines]:
            gvar2 = GeometryVariable(value=actual, dimensions='ngeom')
            self.assertTrue(gvar2.get_value()[0].almost_equals(lines))
            self.assertEqual(gvar2.geom_type, lines.geom_type)
            self.assertTrue(gvar2.shape[0] > 0)
            self.assertIsNone(gvar2.get_mask())
Exemple #5
0
    def test_prepare_geometry(self):
        for geometry_record in self.get_subset_geometries():
            for ss, k in self:
                gvar = GeometryVariable(value=geometry_record['geom'],
                                        dimensions='dim',
                                        crs=WGS84())
                self.assertIsNotNone(gvar.crs)
                prepared = ss._prepare_geometry_(gvar)
                self.assertNotEqual(gvar.get_value()[0].bounds,
                                    prepared.get_value()[0].bounds)
                self.assertFalse(
                    np.may_share_memory(gvar.get_value(),
                                        prepared.get_value()))
                try:
                    self.assertEqual(prepared.crs, ss.field.crs)
                except AssertionError:
                    # Rotated pole on the fields become spherical.
                    self.assertEqual(prepared.crs, CFSpherical())
                    self.assertIsInstance(ss.field.crs, CFRotatedPole)

        # Test nebraska against an unwrapped dataset.
        nebraska = GeometryVariable(value=self.nebraska['geom'],
                                    dimensions='d',
                                    crs=WGS84())
        field = self.test_data.get_rd('cancm4_tas').get()
        ss = SpatialSubsetOperation(field)
        prepared = ss._prepare_geometry_(nebraska)
        self.assertEqual(prepared.wrapped_state, WrappedState.UNWRAPPED)
Exemple #6
0
 def test_unwrap(self):
     geom = box(195, -40, 225, -30)
     gvar = GeometryVariable(name='geoms',
                             value=geom,
                             crs=Spherical(),
                             dimensions='geoms')
     gvar.wrap()
     self.assertEqual(gvar.get_value()[0].bounds,
                      (-165.0, -40.0, -135.0, -30.0))
     gvar.unwrap()
     self.assertEqual(gvar.get_value()[0].bounds,
                      (195.0, -40.0, 225.0, -30.0))
    def test_get_buffered_geometry(self):
        proj4 = '+proj=aea +lat_1=20 +lat_2=60 +lat_0=40 +lon_0=-96 +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs'
        buffer_crs_list = [None, CoordinateReferenceSystem(proj4=proj4)]
        poly = make_poly((36, 44), (-104, -95))

        for buffer_crs in buffer_crs_list:
            gvar = GeometryVariable(value=poly, name='geoms', dimensions='dim', crs=WGS84())
            self.assertEqual(gvar.crs, WGS84())
            if buffer_crs is None:
                buffer_value = 1
            else:
                buffer_value = 10

            ret = SpatialSubsetOperation._get_buffered_geometry_(gvar, buffer_value, buffer_crs=buffer_crs)
            ref = ret.get_value()[0]

            if buffer_crs is None:
                self.assertEqual(ref.bounds, (-105.0, 35.0, -94.0, 45.0))
            else:
                self.assertNumpyAllClose(np.array(ref.bounds), np.array(
                    (-104.00013263459613, 35.9999147913708, -94.99986736540386, 44.00008450528758)))
            self.assertEqual(gvar.crs, ret.crs)

            # check deepcopy
            ret.get_value()[0] = make_poly((1, 2), (3, 4))
            ref_buffered = ret.get_value()[0]
            ref_original = gvar.get_value()[0]
            with self.assertRaises(AssertionError):
                self.assertNumpyAllClose(np.array(ref_buffered.bounds), np.array(ref_original.bounds))
Exemple #8
0
 def test_deepcopy(self):
     gvar = GeometryVariable(value=Point(1, 2), crs=Spherical(), dimensions='d')
     self.assertEqual(gvar.crs, Spherical())
     d = gvar.deepcopy()
     d.crs = WGS84()
     self.assertEqual(gvar.crs, Spherical())
     self.assertFalse(np.may_share_memory(gvar.get_value(), d.get_value()))
     self.assertIsNotNone(d.crs)
Exemple #9
0
 def test_deepcopy(self):
     gvar = GeometryVariable(value=Point(1, 2),
                             crs=Spherical(),
                             dimensions='d')
     self.assertEqual(gvar.crs, Spherical())
     d = gvar.deepcopy()
     d.crs = WGS84()
     self.assertEqual(gvar.crs, Spherical())
     self.assertFalse(np.may_share_memory(gvar.get_value(), d.get_value()))
     self.assertIsNotNone(d.crs)
Exemple #10
0
    def test_init(self):
        # Test empty.
        gvar = GeometryVariable()
        self.assertEqual(gvar.dtype, object)

        gvar = self.get_geometryvariable()
        self.assertIsInstance(gvar.get_masked_value(), MaskedArray)
        self.assertEqual(gvar.ndim, 1)

        # The geometry variable should set itself as the representative geometry on its parent field if that parent does
        # not have a representative geometry set.
        self.assertIsNotNone(gvar.parent.geom)

        # Test with a parent that already has a geometry.
        field = Field()
        field.set_geom(GeometryVariable(name='empty'))
        gvar = self.get_geometryvariable(parent=field)
        self.assertEqual(field.geom.name, 'empty')
        self.assertIn(gvar.name, field)

        # Test passing a "crs".
        gvar = self.get_geometryvariable(crs=WGS84(),
                                         name='my_geom',
                                         dimensions='ngeom')
        self.assertEqual(gvar.crs, WGS84())

        # Test using lines.
        line1 = LineString([(0, 0), (1, 1)])
        line2 = LineString([(1, 1), (2, 2)])
        gvar = GeometryVariable(value=[line1, line2], dimensions='two')
        self.assertTrue(gvar.get_value()[1].almost_equals(line2))
        self.assertEqual(gvar.geom_type, line1.geom_type)
        lines = MultiLineString([line1, line2])
        lines2 = [lines, lines]
        for actual in [lines, lines2, lines]:
            gvar2 = GeometryVariable(value=actual, dimensions='ngeom')
            self.assertTrue(gvar2.get_value()[0].almost_equals(lines))
            self.assertEqual(gvar2.geom_type, lines.geom_type)
            self.assertTrue(gvar2.shape[0] > 0)
            self.assertIsNone(gvar2.get_mask())
Exemple #11
0
    def test_init(self):
        # Test empty.
        gvar = GeometryVariable()
        self.assertEqual(gvar.dtype, object)

        gvar = self.get_geometryvariable()
        self.assertIsInstance(gvar.get_masked_value(), MaskedArray)
        self.assertEqual(gvar.ndim, 1)

        # The geometry variable should set itself as the representative geometry on its parent field if that parent does
        # not have a representative geometry set.
        self.assertIsNotNone(gvar.parent.geom)

        # Test with a parent that already has a geometry.
        field = Field()
        field.set_geom(GeometryVariable(name='empty'))
        gvar = self.get_geometryvariable(parent=field)
        self.assertEqual(field.geom.name, 'empty')
        self.assertIn(gvar.name, field)

        # Test passing a "crs".
        gvar = self.get_geometryvariable(crs=WGS84(), name='my_geom', dimensions='ngeom')
        self.assertEqual(gvar.crs, WGS84())

        # Test using lines.
        line1 = LineString([(0, 0), (1, 1)])
        line2 = LineString([(1, 1), (2, 2)])
        gvar = GeometryVariable(value=[line1, line2], dimensions='two')
        self.assertTrue(gvar.get_value()[1].almost_equals(line2))
        self.assertEqual(gvar.geom_type, line1.geom_type)
        lines = MultiLineString([line1, line2])
        lines2 = [lines, lines]
        for actual in [lines, lines2, lines]:
            gvar2 = GeometryVariable(value=actual, dimensions='ngeom')
            self.assertTrue(gvar2.get_value()[0].almost_equals(lines))
            self.assertEqual(gvar2.geom_type, lines.geom_type)
            self.assertTrue(gvar2.shape[0] > 0)
            self.assertIsNone(gvar2.get_mask())
Exemple #12
0
    def get_spatial_subset(self,
                           operation,
                           geom,
                           use_spatial_index=env.USE_SPATIAL_INDEX,
                           buffer_value=None,
                           buffer_crs=None,
                           geom_crs=None,
                           select_nearest=False,
                           optimized_bbox_subset=False):
        """
        Perform a spatial subset operation on ``target``.

        :param str operation: Either ``'intersects'`` or ``'clip'``.
        :param geom: The input geometry object to use for subsetting of ``target``.
        :type geom: :class:`shapely.geometry.base.BaseGeometry`
        :param bool use_spatial_index: If ``True``, use an ``rtree`` spatial index.
        :param bool select_nearest: If ``True``, select the geometry nearest ``polygon`` using
         :meth:`shapely.geometry.base.BaseGeometry.distance`.
        :rtype: Same as ``target``. If ``target`` is a :class:`ocgis.RequestDataset`,
         then a :class:`ocgis.interface.base.field.Field` will be returned.
        :param float buffer_value: The buffer radius to use in units of the coordinate system of ``subset_sdim``.
        :param buffer_crs: If provided, then ``buffer_value`` are not in units of the coordinate system of
         ``subset_sdim`` but in units of ``buffer_crs``.
        :param bool select_nearest: If ``True``, following the spatial subset operation, select the nearest geometry
         in the subset data to ``geom``. Centroid-based distance is used.
        :type buffer_crs: :class:`ocgis.interface.base.crs.CoordinateReferenceSystem`
        :param bool optimized_bbox_subset: If ``True``, only do a bounding box subset and do not perform more complext
         GIS subset operations such as constructing a spatial index.
        :raises: ValueError
        """

        if not isinstance(geom, GeometryVariable):
            geom = GeometryVariable(value=geom,
                                    name='geom',
                                    dimensions='one',
                                    crs=geom_crs)
        if geom.get_value().flatten().shape != (1, ):
            msg = 'Only one subset geometry allowed. The shape of the geometry variable is {}.'.format(
                geom.shape)
            raise ValueError(msg)
        if optimized_bbox_subset:
            if self.field.grid is None:
                msg = 'Subset operation must be performed on a grid when "optimized_bbox_subset=True".'
                raise ValueError(msg)
            if operation != 'intersects':
                msg = 'Only "intersects" spatial operations when "optimized_bbox_subset=True".'
                raise ValueError(msg)

        # Buffer the subset if a buffer value is provided.
        if buffer_value is not None:
            geom = self._get_buffered_geometry_(geom,
                                                buffer_value,
                                                buffer_crs=buffer_crs)

        self._prepare_target_()
        prepared = self._prepare_geometry_(geom)
        base_geometry = prepared.get_value().flatten()[0]

        # execute the spatial operation
        if operation == 'intersects':
            if self.field.grid is None:
                ret = self.field.geom.get_intersects(
                    base_geometry,
                    use_spatial_index=use_spatial_index,
                    cascade=True).parent
            else:
                ret = self.field.grid.get_intersects(
                    base_geometry,
                    cascade=True,
                    optimized_bbox_subset=optimized_bbox_subset).parent
        elif operation in ('clip', 'intersection'):
            if self.field.grid is None:
                ret = self.field.geom.get_intersection(
                    base_geometry,
                    use_spatial_index=use_spatial_index,
                    cascade=True).parent
            else:
                ret = self.field.grid.get_intersection(base_geometry,
                                                       cascade=True)
                # An intersection with a grid returns a geometry variable. Set this on the field.
                ret.parent.set_geom(ret)
                ret = ret.parent
        else:
            msg = 'The spatial operation "{0}" is not supported.'.format(
                operation)
            raise ValueError(msg)

        with vm.scoped_by_emptyable('return finalize', ret):
            if not vm.is_null:
                # Select the nearest geometry if requested.
                if select_nearest:
                    ret.set_abstraction_geom()
                    ret = ret.geom.get_nearest(base_geometry).parent

                # check for rotated pole and convert back to default CRS
                if self._original_rotated_pole_state is not None and self.output_crs == 'input':
                    ret.update_crs(self._original_rotated_pole_state)

                # wrap the data...
                if self._get_should_wrap_(ret):
                    ret.wrap()

                # convert the coordinate system if requested...
                if self.should_update_crs:
                    ret.update_crs(self.output_crs)

        return ret
Exemple #13
0
    def get_spatial_subset(self, operation, geom, use_spatial_index=env.USE_SPATIAL_INDEX, buffer_value=None,
                           buffer_crs=None, geom_crs=None, select_nearest=False, optimized_bbox_subset=False):
        """
        Perform a spatial subset operation on ``target``.

        :param str operation: Either ``'intersects'`` or ``'clip'``.
        :param geom: The input geometry object to use for subsetting of ``target``.
        :type geom: :class:`shapely.geometry.base.BaseGeometry` | :class:`ocgis.GeometryVariable`
        :param bool use_spatial_index: If ``True``, use an ``rtree`` spatial index.
        :param bool select_nearest: If ``True``, select the geometry nearest ``polygon`` using
         :meth:`shapely.geometry.base.BaseGeometry.distance`.
        :rtype: Same as ``target``. If ``target`` is a :class:`ocgis.RequestDataset`,
         then a :class:`ocgis.interface.base.field.Field` will be returned.
        :param float buffer_value: The buffer radius to use in units of the coordinate system of ``subset_sdim``.
        :param buffer_crs: If provided, then ``buffer_value`` are not in units of the coordinate system of
         ``subset_sdim`` but in units of ``buffer_crs``.
        :param geom_crs: The coordinate reference system for the subset geometry.
        :type geom_crs: :class:`ocgis.crs.CRS`
        :param bool select_nearest: If ``True``, following the spatial subset operation, select the nearest geometry
         in the subset data to ``geom``. Centroid-based distance is used.
        :type buffer_crs: :class:`ocgis.interface.base.crs.CoordinateReferenceSystem`
        :param bool optimized_bbox_subset: If ``True``, only do a bounding box subset and do not perform more complext
         GIS subset operations such as constructing a spatial index.
        :raises: ValueError
        """

        if not isinstance(geom, GeometryVariable):
            geom = GeometryVariable(value=geom, name='geom', dimensions='one', crs=geom_crs)
        if geom.get_value().flatten().shape != (1,):
            msg = 'Only one subset geometry allowed. The shape of the geometry variable is {}.'.format(geom.shape)
            raise ValueError(msg)
        if optimized_bbox_subset:
            if self.field.grid is None:
                msg = 'Subset operation must be performed on a grid when "optimized_bbox_subset=True".'
                raise ValueError(msg)
            if operation != 'intersects':
                msg = 'Only "intersects" spatial operations when "optimized_bbox_subset=True".'
                raise ValueError(msg)

        # Buffer the subset if a buffer value is provided.
        if buffer_value is not None:
            geom = self._get_buffered_geometry_(geom, buffer_value, buffer_crs=buffer_crs)
        prepared = self._prepare_geometry_(geom)
        base_geometry = prepared.get_value().flatten()[0]

        # Prepare the target field.
        self._prepare_target_()

        # execute the spatial operation
        if operation == 'intersects':
            if self.field.grid is None:
                ret = self.field.geom.get_intersects(base_geometry, use_spatial_index=use_spatial_index,
                                                     cascade=True).parent
            else:
                ret = self.field.grid.get_intersects(base_geometry, cascade=True,
                                                     optimized_bbox_subset=optimized_bbox_subset).parent
        elif operation in ('clip', 'intersection'):
            if self.field.grid is None:
                ret = self.field.geom.get_intersection(base_geometry, use_spatial_index=use_spatial_index,
                                                       cascade=True).parent
            else:
                ret = self.field.grid.get_intersection(base_geometry, cascade=True)
                # An intersection with a grid returns a geometry variable. Set this on the field.
                ret.parent.set_geom(ret)
                ret = ret.parent
        else:
            msg = 'The spatial operation "{0}" is not supported.'.format(operation)
            raise ValueError(msg)

        with vm.scoped_by_emptyable('return finalize', ret):
            if not vm.is_null:
                # Select the nearest geometry if requested.
                if select_nearest:
                    ret.set_abstraction_geom()
                    ret = ret.geom.get_nearest(base_geometry).parent

                # check for rotated pole and convert back to default CRS
                if self._original_rotated_pole_state is not None and self.output_crs == 'input':
                    ret.update_crs(self._original_rotated_pole_state)

                # wrap the data...
                if self._get_should_wrap_(ret):
                    ret.wrap()

                # convert the coordinate system if requested...
                if self.should_update_crs:
                    ret.update_crs(self.output_crs)

        return ret