Пример #1
0
 def test_compressed_file_based_raster_creation(self):
     rstfile = tempfile.NamedTemporaryFile(suffix='.tif')
     # Make a compressed copy of an existing raster.
     compressed = self.rs.warp({
         'papsz_options': {
             'compress': 'packbits'
         },
         'name': rstfile.name
     })
     # Check physically if compression worked.
     self.assertLess(os.path.getsize(compressed.name),
                     os.path.getsize(self.rs.name))
     # Create file-based raster with options from scratch.
     compressed = GDALRaster({
         'datatype':
         1,
         'driver':
         'tif',
         'name':
         rstfile.name,
         'width':
         40,
         'height':
         40,
         'srid':
         3086,
         'origin': (500000, 400000),
         'scale': (100, -100),
         'skew': (0, 0),
         'bands': [{
             'data': range(40 ^ 2),
             'nodata_value': 255,
         }],
         'papsz_options': {
             'compress': 'packbits',
             'pixeltype': 'signedbyte',
             'blockxsize': 23,
             'blockysize': 23,
         }
     })
     # Check if options used on creation are stored in metadata.
     # Reopening the raster ensures that all metadata has been written
     # to the file.
     compressed = GDALRaster(compressed.name)
     self.assertEqual(
         compressed.metadata['IMAGE_STRUCTURE']['COMPRESSION'],
         'PACKBITS',
     )
     self.assertEqual(
         compressed.bands[0].metadata['IMAGE_STRUCTURE']['PIXELTYPE'],
         'SIGNEDBYTE')
     if GDAL_VERSION >= (2, 1):
         self.assertIn('Block=40x23', compressed.info)
Пример #2
0
 def test_geotransform_and_friends(self):
     # Assert correct values for file based raster
     self.assertEqual(
         self.rs.geotransform,
         [511700.4680706557, 100.0, 0.0, 435103.3771231986, 0.0, -100.0])
     self.assertEqual(self.rs.origin,
                      [511700.4680706557, 435103.3771231986])
     self.assertEqual(self.rs.origin.x, 511700.4680706557)
     self.assertEqual(self.rs.origin.y, 435103.3771231986)
     self.assertEqual(self.rs.scale, [100.0, -100.0])
     self.assertEqual(self.rs.scale.x, 100.0)
     self.assertEqual(self.rs.scale.y, -100.0)
     self.assertEqual(self.rs.skew, [0, 0])
     self.assertEqual(self.rs.skew.x, 0)
     self.assertEqual(self.rs.skew.y, 0)
     # Create in-memory rasters and change gtvalues
     rsmem = GDALRaster(JSON_RASTER)
     # geotransform accepts both floats and ints
     rsmem.geotransform = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0]
     self.assertEqual(rsmem.geotransform, [0.0, 1.0, 2.0, 3.0, 4.0, 5.0])
     rsmem.geotransform = range(6)
     self.assertEqual(rsmem.geotransform, [float(x) for x in range(6)])
     self.assertEqual(rsmem.origin, [0, 3])
     self.assertEqual(rsmem.origin.x, 0)
     self.assertEqual(rsmem.origin.y, 3)
     self.assertEqual(rsmem.scale, [1, 5])
     self.assertEqual(rsmem.scale.x, 1)
     self.assertEqual(rsmem.scale.y, 5)
     self.assertEqual(rsmem.skew, [2, 4])
     self.assertEqual(rsmem.skew.x, 2)
     self.assertEqual(rsmem.skew.y, 4)
     self.assertEqual(rsmem.width, 5)
     self.assertEqual(rsmem.height, 5)
Пример #3
0
 def test_offset_size_and_shape_on_raster_creation(self):
     rast = GDALRaster({
         'datatype':
         1,
         'width':
         4,
         'height':
         4,
         'srid':
         4326,
         'bands': [{
             'data': (1, ),
             'offset': (1, 1),
             'size': (2, 2),
             'shape': (1, 1),
             'nodata_value': 2,
         }],
     })
     # Get array from raster.
     result = rast.bands[0].data()
     if numpy:
         result = result.flatten().tolist()
     # Band data is equal to nodata value except on input block of ones.
     self.assertEqual(result,
                      [2, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 2])
Пример #4
0
 def test_raster_warp_nodata_zone(self):
     # Create in memory raster.
     source = GDALRaster({
         'datatype':
         1,
         'driver':
         'MEM',
         'width':
         4,
         'height':
         4,
         'srid':
         3086,
         'origin': (500000, 400000),
         'scale': (100, -100),
         'skew': (0, 0),
         'bands': [{
             'data': range(16),
             'nodata_value': 23,
         }],
     })
     # Warp raster onto a location that does not cover any pixels of the original.
     result = source.warp({'origin': (200000, 200000)}).bands[0].data()
     if numpy:
         result = result.flatten().tolist()
     # The result is an empty raster filled with the correct nodata value.
     self.assertEqual(result, [23] * 16)
Пример #5
0
 def setUp(self):
     rast = GDALRaster({
         "srid":
         4326,
         "origin": [0, 0],
         "scale": [-1, 1],
         "skew": [0, 0],
         "width":
         5,
         "height":
         5,
         "nr_of_bands":
         2,
         "bands": [{
             "data": range(25)
         }, {
             "data": range(25, 50)
         }],
     })
     model_instance = RasterModel.objects.create(
         rast=rast,
         rastprojected=rast,
         geom="POINT (-95.37040 29.70486)",
     )
     RasterRelatedModel.objects.create(rastermodel=model_instance)
Пример #6
0
    def test_band_data_replication(self):
        band = GDALRaster({
            'srid':
            4326,
            'width':
            3,
            'height':
            3,
            'bands': [{
                'data': range(10, 19),
                'nodata_value': 0
            }],
        }).bands[0]

        # Variations for input (data, shape, expected result).
        combos = (
            ([1], (1, 1), [1] * 9),
            (range(3), (1, 3), [0, 0, 0, 1, 1, 1, 2, 2, 2]),
            (range(3), (3, 1), [0, 1, 2, 0, 1, 2, 0, 1, 2]),
        )
        for combo in combos:
            band.data(combo[0], shape=combo[1])
            if numpy:
                numpy.testing.assert_equal(band.data(),
                                           numpy.array(combo[2]).reshape(3, 3))
            else:
                self.assertEqual(band.data(), list(combo[2]))
Пример #7
0
    def test_raster_warp(self):
        # Create in memory raster
        source = GDALRaster({
            'datatype':
            1,
            'driver':
            'MEM',
            'name':
            'sourceraster',
            'width':
            4,
            'height':
            4,
            'nr_of_bands':
            1,
            'srid':
            3086,
            'origin': (500000, 400000),
            'scale': (100, -100),
            'skew': (0, 0),
            'bands': [{
                'data': range(16),
                'nodata_value': 255,
            }],
        })

        # Test altering the scale, width, and height of a raster
        data = {
            'scale': [200, -200],
            'width': 2,
            'height': 2,
        }
        target = source.warp(data)
        self.assertEqual(target.width, data['width'])
        self.assertEqual(target.height, data['height'])
        self.assertEqual(target.scale, data['scale'])
        self.assertEqual(target.bands[0].datatype(),
                         source.bands[0].datatype())
        self.assertEqual(target.name, 'sourceraster_copy.MEM')
        result = target.bands[0].data()
        if numpy:
            result = result.flatten().tolist()
        self.assertEqual(result, [5, 7, 13, 15])

        # Test altering the name and datatype (to float)
        data = {
            'name': '/path/to/targetraster.tif',
            'datatype': 6,
        }
        target = source.warp(data)
        self.assertEqual(target.bands[0].datatype(), 6)
        self.assertEqual(target.name, '/path/to/targetraster.tif')
        self.assertEqual(target.driver.name, 'MEM')
        result = target.bands[0].data()
        if numpy:
            result = result.flatten().tolist()
        self.assertEqual(result, [
            0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0,
            13.0, 14.0, 15.0
        ])
Пример #8
0
    def test_read_mode_error(self):
        # Open raster in read mode
        rs = GDALRaster(self.rs_path, write=False)
        band = rs.bands[0]

        # Setting attributes in write mode raises exception in the _flush method
        with self.assertRaises(GDALException):
            setattr(band, 'nodata_value', 10)
Пример #9
0
 def test_rs_srid(self):
     rast = GDALRaster({
         'width': 16,
         'height': 16,
         'srid': 4326,
     })
     self.assertEqual(rast.srid, 4326)
     rast.srid = 3086
     self.assertEqual(rast.srid, 3086)
Пример #10
0
 def test_band_statistics_empty_band(self):
     rsmem = GDALRaster({
         'srid': 4326,
         'width': 1,
         'height': 1,
         'bands': [{
             'data': [0],
             'nodata_value': 0
         }],
     })
     self.assertEqual(rsmem.bands[0].statistics(), (None, None, None, None))
Пример #11
0
 def test_vsi_buffer_property(self):
     # Create a vsi-based raster from scratch.
     rast = GDALRaster({
         'name': '/vsimem/raster.tif',
         'driver': 'tif',
         'width': 4,
         'height': 4,
         'srid': 4326,
         'bands': [{
             'data': range(16),
         }],
     })
     # Do a round trip from raster to buffer to raster.
     result = GDALRaster(rast.vsi_buffer).bands[0].data()
     if numpy:
         result = result.flatten().tolist()
     # Band data is equal to nodata value except on input block of ones.
     self.assertEqual(result, list(range(16)))
     # The vsi buffer is None for rasters that are not vsi based.
     self.assertIsNone(self.rs.vsi_buffer)
Пример #12
0
 def test_geotransform_bad_inputs(self):
     rsmem = GDALRaster(JSON_RASTER)
     error_geotransforms = [
         [1, 2],
         [1, 2, 3, 4, 5, 'foo'],
         [1, 2, 3, 4, 5, 6, 'foo'],
     ]
     msg = 'Geotransform must consist of 6 numeric values.'
     for geotransform in error_geotransforms:
         with self.subTest(i=geotransform), self.assertRaisesMessage(
                 ValueError, msg):
             rsmem.geotransform = geotransform
Пример #13
0
 def test_vsi_raster_creation(self):
     # Open a raster as a file object.
     with open(self.rs_path, 'rb') as dat:
         # Instantiate a raster from the file binary buffer.
         vsimem = GDALRaster(dat.read())
     # The data of the in-memory file is equal to the source file.
     result = vsimem.bands[0].data()
     target = self.rs.bands[0].data()
     if numpy:
         result = result.flatten().tolist()
         target = target.flatten().tolist()
     self.assertEqual(result, target)
Пример #14
0
 def test_lookup_with_raster_bbox(self):
     rast = GDALRaster(json.loads(JSON_RASTER))
     # Shift raster upwards
     rast.origin.y = 2
     # The raster in the model is not strictly below
     qs = RasterModel.objects.filter(rast__strictly_below=rast)
     self.assertEqual(qs.count(), 0)
     # Shift raster further upwards
     rast.origin.y = 6
     # The raster in the model is strictly below
     qs = RasterModel.objects.filter(rast__strictly_below=rast)
     self.assertEqual(qs.count(), 1)
Пример #15
0
    def test_file_based_raster_creation(self):
        # Prepare tempfile
        rstfile = tempfile.NamedTemporaryFile(suffix='.tif')

        # Create file-based raster from scratch
        GDALRaster({
            'datatype':
            self.rs.bands[0].datatype(),
            'driver':
            'tif',
            'name':
            rstfile.name,
            'width':
            163,
            'height':
            174,
            'nr_of_bands':
            1,
            'srid':
            self.rs.srs.wkt,
            'origin': (self.rs.origin.x, self.rs.origin.y),
            'scale': (self.rs.scale.x, self.rs.scale.y),
            'skew': (self.rs.skew.x, self.rs.skew.y),
            'bands': [{
                'data': self.rs.bands[0].data(),
                'nodata_value': self.rs.bands[0].nodata_value,
            }],
        })

        # Reload newly created raster from file
        restored_raster = GDALRaster(rstfile.name)
        self.assertEqual(restored_raster.srs.wkt, self.rs.srs.wkt)
        self.assertEqual(restored_raster.geotransform, self.rs.geotransform)
        if numpy:
            numpy.testing.assert_equal(restored_raster.bands[0].data(),
                                       self.rs.bands[0].data())
        else:
            self.assertEqual(restored_raster.bands[0].data(),
                             self.rs.bands[0].data())
Пример #16
0
 def test_vsi_raster_deletion(self):
     path = '/vsimem/raster.tif'
     # Create a vsi-based raster from scratch.
     vsimem = GDALRaster({
         'name': path,
         'driver': 'tif',
         'width': 4,
         'height': 4,
         'srid': 4326,
         'bands': [{
             'data': range(16),
         }],
     })
     # The virtual file exists.
     rst = GDALRaster(path)
     self.assertEqual(rst.width, 4)
     # Delete GDALRaster.
     del vsimem
     del rst
     # The virtual file has been removed.
     msg = 'Could not open the datasource at "/vsimem/raster.tif"'
     with self.assertRaisesMessage(GDALException, msg):
         GDALRaster(path)
Пример #17
0
 def test_lookup_with_polygonized_raster(self):
     rast = GDALRaster(json.loads(JSON_RASTER))
     # Move raster to overlap with the model point on the left side
     rast.origin.x = -95.37040 + 1
     rast.origin.y = 29.70486
     # Raster overlaps with point in model
     qs = RasterModel.objects.filter(geom__intersects=rast)
     self.assertEqual(qs.count(), 1)
     # Change left side of raster to be nodata values
     rast.bands[0].data(data=[0, 0, 0, 1, 1], shape=(5, 1))
     rast.bands[0].nodata_value = 0
     qs = RasterModel.objects.filter(geom__intersects=rast)
     # Raster does not overlap anymore after polygonization
     # where the nodata zone is not included.
     self.assertEqual(qs.count(), 0)
Пример #18
0
 def test_set_nodata_value_on_raster_creation(self):
     # Create raster filled with nodata values.
     rast = GDALRaster({
         'datatype': 1,
         'width': 2,
         'height': 2,
         'srid': 4326,
         'bands': [{
             'nodata_value': 23
         }],
     })
     # Get array from raster.
     result = rast.bands[0].data()
     if numpy:
         result = result.flatten().tolist()
     # All band data is equal to nodata value.
     self.assertEqual(result, [23] * 4)
Пример #19
0
 def test_band_delete_nodata(self):
     rsmem = GDALRaster({
         'srid': 4326,
         'width': 1,
         'height': 1,
         'bands': [{
             'data': [0],
             'nodata_value': 1
         }],
     })
     if GDAL_VERSION < (2, 1):
         msg = 'GDAL >= 2.1 required to delete nodata values.'
         with self.assertRaisesMessage(ValueError, msg):
             rsmem.bands[0].nodata_value = None
     else:
         rsmem.bands[0].nodata_value = None
         self.assertIsNone(rsmem.bands[0].nodata_value)
Пример #20
0
    def test_raster_metadata_property(self):
        data = self.rs.metadata
        self.assertEqual(data['DEFAULT'], {'AREA_OR_POINT': 'Area'})
        self.assertEqual(data['IMAGE_STRUCTURE'], {'INTERLEAVE': 'BAND'})

        # Create file-based raster from scratch
        source = GDALRaster({
            'datatype': 1,
            'width': 2,
            'height': 2,
            'srid': 4326,
            'bands': [{
                'data': range(4),
                'nodata_value': 99
            }],
        })
        # Set metadata on raster and on a band.
        metadata = {
            'DEFAULT': {
                'OWNER': 'Django',
                'VERSION': '1.0',
                'AREA_OR_POINT': 'Point'
            },
        }
        source.metadata = metadata
        source.bands[0].metadata = metadata
        self.assertEqual(source.metadata['DEFAULT'], metadata['DEFAULT'])
        self.assertEqual(source.bands[0].metadata['DEFAULT'],
                         metadata['DEFAULT'])
        # Update metadata on raster.
        metadata = {
            'DEFAULT': {
                'VERSION': '2.0'
            },
        }
        source.metadata = metadata
        self.assertEqual(source.metadata['DEFAULT']['VERSION'], '2.0')
        # Remove metadata on raster.
        metadata = {
            'DEFAULT': {
                'OWNER': None
            },
        }
        source.metadata = metadata
        self.assertNotIn('OWNER', source.metadata['DEFAULT'])
Пример #21
0
 def test_db_function_errors(self):
     """
     Errors are raised when using DB functions with raster content.
     """
     point = GEOSGeometry(
         "SRID=3086;POINT (-697024.9213808845 683729.1705516104)")
     rast = GDALRaster(json.loads(JSON_RASTER))
     msg = "Distance function requires a geometric argument in position 2."
     with self.assertRaisesMessage(TypeError, msg):
         RasterModel.objects.annotate(
             distance_from_point=Distance("geom", rast))
     with self.assertRaisesMessage(TypeError, msg):
         RasterModel.objects.annotate(
             distance_from_point=Distance("rastprojected", rast))
     msg = "Distance function requires a GeometryField in position 1, got RasterField."
     with self.assertRaisesMessage(TypeError, msg):
         RasterModel.objects.annotate(
             distance_from_point=Distance("rastprojected", point)).count()
Пример #22
0
 def test_set_nodata_none_on_raster_creation(self):
     if GDAL_VERSION < (2, 1):
         self.skipTest("GDAL >= 2.1 is required for this test.")
     # Create raster without data and without nodata value.
     rast = GDALRaster({
         'datatype': 1,
         'width': 2,
         'height': 2,
         'srid': 4326,
         'bands': [{
             'nodata_value': None
         }],
     })
     # Get array from raster.
     result = rast.bands[0].data()
     if numpy:
         result = result.flatten().tolist()
     # Band data is equal to zero becaues no nodata value has been specified.
     self.assertEqual(result, [0] * 4)
Пример #23
0
 def test_band_statistics_automatic_refresh(self):
     rsmem = GDALRaster({
         'srid': 4326,
         'width': 2,
         'height': 2,
         'bands': [{
             'data': [0] * 4,
             'nodata_value': 99
         }],
     })
     band = rsmem.bands[0]
     # Populate statistics cache
     self.assertEqual(band.statistics(), (0, 0, 0, 0))
     # Change data
     band.data([1, 1, 0, 0])
     # Statistics are properly updated
     self.assertEqual(band.statistics(), (0.0, 1.0, 0.5, 0.5))
     # Change nodata_value
     band.nodata_value = 0
     # Statistics are properly updated
     self.assertEqual(band.statistics(), (1.0, 1.0, 1.0, 0.0))
Пример #24
0
    def test_memory_based_raster_creation(self):
        # Create uint8 raster with full pixel data range (0-255)
        rast = GDALRaster({
            'datatype':
            1,
            'width':
            16,
            'height':
            16,
            'srid':
            4326,
            'bands': [{
                'data': range(256),
                'nodata_value': 255,
            }],
        })

        # Get array from raster
        result = rast.bands[0].data()
        if numpy:
            result = result.flatten().tolist()

        # Assert data is same as original input
        self.assertEqual(result, list(range(256)))
Пример #25
0
 def setUp(self):
     self.rs_path = os.path.join(os.path.dirname(__file__),
                                 '../data/rasters/raster.tif')
     rs = GDALRaster(self.rs_path)
     self.band = rs.bands[0]
Пример #26
0
 def test_lookup_input_band_not_allowed(self):
     rast = GDALRaster(json.loads(JSON_RASTER))
     qs = RasterModel.objects.filter(rast__bbcontains=(rast, 1))
     msg = 'Band indices are not allowed for this operator, it works on bbox only.'
     with self.assertRaisesMessage(ValueError, msg):
         qs.count()
Пример #27
0
 def test_lookup_input_tuple_too_long(self):
     rast = GDALRaster(json.loads(JSON_RASTER))
     msg = 'Tuple too long for lookup bbcontains.'
     with self.assertRaisesMessage(ValueError, msg):
         RasterModel.objects.filter(rast__bbcontains=(rast, 1, 2))
Пример #28
0
    def test_band_data_setters(self):
        # Create in-memory raster and get band
        rsmem = GDALRaster({
            'datatype': 1,
            'driver': 'MEM',
            'name': 'mem_rst',
            'width': 10,
            'height': 10,
            'nr_of_bands': 1,
            'srid': 4326,
        })
        bandmem = rsmem.bands[0]

        # Set nodata value
        bandmem.nodata_value = 99
        self.assertEqual(bandmem.nodata_value, 99)

        # Set data for entire dataset
        bandmem.data(range(100))
        if numpy:
            numpy.testing.assert_equal(bandmem.data(),
                                       numpy.arange(100).reshape(10, 10))
        else:
            self.assertEqual(bandmem.data(), list(range(100)))

        # Prepare data for setting values in subsequent tests
        block = list(range(100, 104))
        packed_block = struct.pack('<' + 'B B B B', *block)

        # Set data from list
        bandmem.data(block, (1, 1), (2, 2))
        result = bandmem.data(offset=(1, 1), size=(2, 2))
        if numpy:
            numpy.testing.assert_equal(result,
                                       numpy.array(block).reshape(2, 2))
        else:
            self.assertEqual(result, block)

        # Set data from packed block
        bandmem.data(packed_block, (1, 1), (2, 2))
        result = bandmem.data(offset=(1, 1), size=(2, 2))
        if numpy:
            numpy.testing.assert_equal(result,
                                       numpy.array(block).reshape(2, 2))
        else:
            self.assertEqual(result, block)

        # Set data from bytes
        bandmem.data(bytes(packed_block), (1, 1), (2, 2))
        result = bandmem.data(offset=(1, 1), size=(2, 2))
        if numpy:
            numpy.testing.assert_equal(result,
                                       numpy.array(block).reshape(2, 2))
        else:
            self.assertEqual(result, block)

        # Set data from bytearray
        bandmem.data(bytearray(packed_block), (1, 1), (2, 2))
        result = bandmem.data(offset=(1, 1), size=(2, 2))
        if numpy:
            numpy.testing.assert_equal(result,
                                       numpy.array(block).reshape(2, 2))
        else:
            self.assertEqual(result, block)

        # Set data from memoryview
        bandmem.data(memoryview(packed_block), (1, 1), (2, 2))
        result = bandmem.data(offset=(1, 1), size=(2, 2))
        if numpy:
            numpy.testing.assert_equal(result,
                                       numpy.array(block).reshape(2, 2))
        else:
            self.assertEqual(result, block)

        # Set data from numpy array
        if numpy:
            bandmem.data(
                numpy.array(block, dtype='int8').reshape(2, 2), (1, 1), (2, 2))
            numpy.testing.assert_equal(
                bandmem.data(offset=(1, 1), size=(2, 2)),
                numpy.array(block).reshape(2, 2))

        # Test json input data
        rsmemjson = GDALRaster(JSON_RASTER)
        bandmemjson = rsmemjson.bands[0]
        if numpy:
            numpy.testing.assert_equal(bandmemjson.data(),
                                       numpy.array(range(25)).reshape(5, 5))
        else:
            self.assertEqual(bandmemjson.data(), list(range(25)))
Пример #29
0
    def test_dwithin_gis_lookup_ouptut_with_rasters(self):
        """
        Check the logical functionality of the dwithin lookup for different
        input parameters.
        """
        # Create test raster and geom.
        rast = GDALRaster(json.loads(JSON_RASTER))
        stx_pnt = GEOSGeometry(
            'POINT (-95.370401017314293 29.704867409475465)', 4326)
        stx_pnt.transform(3086)

        # Filter raster with different lookup raster formats.
        qs = RasterModel.objects.filter(rastprojected__dwithin=(rast, D(km=1)))
        self.assertEqual(qs.count(), 1)

        qs = RasterModel.objects.filter(
            rastprojected__dwithin=(json.loads(JSON_RASTER), D(km=1)))
        self.assertEqual(qs.count(), 1)

        qs = RasterModel.objects.filter(rastprojected__dwithin=(JSON_RASTER,
                                                                D(km=1)))
        self.assertEqual(qs.count(), 1)

        # Filter in an unprojected coordinate system.
        qs = RasterModel.objects.filter(rast__dwithin=(rast, 40))
        self.assertEqual(qs.count(), 1)

        # Filter with band index transform.
        qs = RasterModel.objects.filter(rast__1__dwithin=(rast, 1, 40))
        self.assertEqual(qs.count(), 1)
        qs = RasterModel.objects.filter(rast__1__dwithin=(rast, 40))
        self.assertEqual(qs.count(), 1)
        qs = RasterModel.objects.filter(rast__dwithin=(rast, 1, 40))
        self.assertEqual(qs.count(), 1)

        # Filter raster by geom.
        qs = RasterModel.objects.filter(rast__dwithin=(stx_pnt, 500))
        self.assertEqual(qs.count(), 1)

        qs = RasterModel.objects.filter(rastprojected__dwithin=(stx_pnt,
                                                                D(km=10000)))
        self.assertEqual(qs.count(), 1)

        qs = RasterModel.objects.filter(rast__dwithin=(stx_pnt, 5))
        self.assertEqual(qs.count(), 0)

        qs = RasterModel.objects.filter(rastprojected__dwithin=(stx_pnt,
                                                                D(km=100)))
        self.assertEqual(qs.count(), 0)

        # Filter geom by raster.
        qs = RasterModel.objects.filter(geom__dwithin=(rast, 500))
        self.assertEqual(qs.count(), 1)

        # Filter through related model.
        qs = RasterRelatedModel.objects.filter(
            rastermodel__rast__dwithin=(rast, 40))
        self.assertEqual(qs.count(), 1)

        # Filter through related model with band index transform
        qs = RasterRelatedModel.objects.filter(
            rastermodel__rast__1__dwithin=(rast, 40))
        self.assertEqual(qs.count(), 1)

        # Filter through conditional statements.
        qs = RasterModel.objects.filter(
            Q(rast__dwithin=(rast, 40))
            & Q(rastprojected__dwithin=(stx_pnt, D(km=10000))))
        self.assertEqual(qs.count(), 1)

        # Filter through different lookup.
        qs = RasterModel.objects.filter(rastprojected__bbcontains=rast)
        self.assertEqual(qs.count(), 1)
Пример #30
0
    def test_all_gis_lookups_with_rasters(self):
        """
        Evaluate all possible lookups for all input combinations (i.e.
        raster-raster, raster-geom, geom-raster) and for projected and
        unprojected coordinate systems. This test just checks that the lookup
        can be called, but doesn't check if the result makes logical sense.
        """
        from djmodels.contrib.gis.db.backends.postgis.operations import PostGISOperations

        # Create test raster and geom.
        rast = GDALRaster(json.loads(JSON_RASTER))
        stx_pnt = GEOSGeometry(
            'POINT (-95.370401017314293 29.704867409475465)', 4326)
        stx_pnt.transform(3086)

        lookups = [(name, lookup)
                   for name, lookup in BaseSpatialField.get_lookups().items()
                   if issubclass(lookup, GISLookup)]
        self.assertNotEqual(lookups, [], 'No lookups found')
        # Loop through all the GIS lookups.
        for name, lookup in lookups:
            # Construct lookup filter strings.
            combo_keys = [
                field + name for field in [
                    'rast__',
                    'rast__',
                    'rastprojected__0__',
                    'rast__',
                    'rastprojected__',
                    'geom__',
                    'rast__',
                ]
            ]
            if issubclass(lookup, DistanceLookupBase):
                # Set lookup values for distance lookups.
                combo_values = [
                    (rast, 50, 'spheroid'),
                    (rast, 0, 50, 'spheroid'),
                    (rast, 0, D(km=1)),
                    (stx_pnt, 0, 500),
                    (stx_pnt, D(km=1000)),
                    (rast, 500),
                    (json.loads(JSON_RASTER), 500),
                ]
            elif name == 'relate':
                # Set lookup values for the relate lookup.
                combo_values = [
                    (rast, 'T*T***FF*'),
                    (rast, 0, 'T*T***FF*'),
                    (rast, 0, 'T*T***FF*'),
                    (stx_pnt, 0, 'T*T***FF*'),
                    (stx_pnt, 'T*T***FF*'),
                    (rast, 'T*T***FF*'),
                    (json.loads(JSON_RASTER), 'T*T***FF*'),
                ]
            elif name == 'isvalid':
                # The isvalid lookup doesn't make sense for rasters.
                continue
            elif PostGISOperations.gis_operators[name].func:
                # Set lookup values for all function based operators.
                combo_values = [
                    rast, (rast, 0), (rast, 0), (stx_pnt, 0), stx_pnt, rast,
                    json.loads(JSON_RASTER)
                ]
            else:
                # Override band lookup for these, as it's not supported.
                combo_keys[2] = 'rastprojected__' + name
                # Set lookup values for all other operators.
                combo_values = [
                    rast, None, rast, stx_pnt, stx_pnt, rast,
                    json.loads(JSON_RASTER)
                ]

            # Create query filter combinations.
            self.assertEqual(
                len(combo_keys),
                len(combo_values),
                'Number of lookup names and values should be the same',
            )
            combos = [x for x in zip(combo_keys, combo_values) if x[1]]
            self.assertEqual(
                [(n, x) for n, x in enumerate(combos) if x in combos[:n]],
                [],
                'There are repeated test lookups',
            )
            combos = [{k: v} for k, v in combos]

            for combo in combos:
                # Apply this query filter.
                qs = RasterModel.objects.filter(**combo)

                # Evaluate normal filter qs.
                self.assertIn(qs.count(), [0, 1])

            # Evaluate on conditional Q expressions.
            qs = RasterModel.objects.filter(Q(**combos[0]) & Q(**combos[1]))
            self.assertIn(qs.count(), [0, 1])