def test_read_raster(self):
        """Test that raster can be read from file and accessed.
        """

        # FIXME (Ole): Some datasets show very large differences between extrema in the array and
        # those computed by GDAL. This may warrant another bug report to GEOS

        for coverage_name in [
            "test_grid",
            "shakemap_padang_20090930",
            "population_padang_1",
            "population_padang_2",
            #'fatality_padang_1',
            #'fatality_padang_2'
        ]:

            filename = "data/%s.asc" % coverage_name

            for R in [Raster(filename), read_coverage(filename)]:

                min, max = R.get_extrema()

                A = R.get_data(nan=True)
                B = R.get_data(nan=True)

                assert numpy.nanmax(A - B) == 0

                # FIXME (Ole): These tolerances are not really acceptable. Report to GEOS.
                assert numpy.allclose(min, numpy.nanmin(A[:]), rtol=1e-2)

                if coverage_name != "population_padang_2":
                    assert numpy.allclose(max, numpy.nanmax(A[:]), rtol=1e-2)
    def test_bins(self):
        """Test that linear and quantile bins are correct
        """

        for filename in ["data/population_padang_1.asc", "data/test_grid.asc"]:

            R = read_coverage(filename)

            min, max = R.get_extrema()  # use_numeric=True)

            for N in [2, 3, 5, 7, 10, 16]:
                linear_intervals = R.get_bins(N=N, quantiles=False)

                assert linear_intervals[0] == min
                assert linear_intervals[-1] == max

                d = (max - min) / N
                for i in range(N):
                    assert numpy.allclose(linear_intervals[i], min + i * d)

                quantiles = R.get_bins(N=N, quantiles=True)

                A = R.get_data(nan=True).flat[:]

                mask = numpy.logical_not(numpy.isnan(A))  # Omit NaN's
                l1 = len(A)
                A = A.compress(mask)
                l2 = len(A)

                if filename == "data/test_grid.asc":
                    # Check that NaN's were removed

                    assert l1 == 35
                    assert l2 == 30

                # Assert that there are no NaN's
                assert not numpy.alltrue(numpy.isnan(A))

                number_of_elements = len(A)
                average_elements_per_bin = number_of_elements / N

                # Count elements in each bin and check

                i0 = quantiles[0]
                for i1 in quantiles[1:]:
                    count = numpy.sum((i0 < A) & (A < i1))
                    if i0 == quantiles[0]:
                        refcount = count

                    if i1 < quantiles[-1]:
                        # Number of elements in each bin must vary by no more than 1
                        assert abs(count - refcount) <= 1
                        assert abs(count - average_elements_per_bin) <= 3

                    else:
                        # The last bin is allowed vary by more
                        pass

                    i0 = i1
Exemple #3
0
    def test_read_and_write_of_rasters(self):        
        """Test that rasters can be read and written correctly
        """    
        
        for coveragename in ['Earthquake_Ground_Shaking_clip.tif',
                             'Population_2010_clip.tif',
                             'shakemap_padang_20090930.asc',
                             'population_padang_1.asc']:
        
            filename = 'data/%s' % coveragename
            for R1 in [Raster(filename), read_coverage(filename)]:
                
                # Check consistency of raster
                A1 = R1.get_data()
                M, N = A1.shape
                
                msg = 'Dimensions of raster array do not match those of raster file %s' % R1.filename
                assert M == R1.rows, msg
                assert N == R1.columns, msg        

                # Write back to new file
                outfilename = '/tmp/%s' % coveragename
                try:
                    os.remove(outfilename)
                except:    
                    pass
                
                write_coverage_to_geotiff(A1, outfilename, R1.get_projection(), R1.get_geotransform())
                
                # Read again and check consistency
                R2 = Raster(outfilename)                
                
                msg = 'Dimensions of written raster array do not match those of input raster file\n'
                msg += '    Dimensions of input file %s:  (%s, %s)\n' % (R1.filename, R1.rows, R1.columns)
                msg += '    Dimensions of output file %s: (%s, %s)' % (R2.filename, R2.rows, R2.columns)                
                assert R1.rows == R2.rows, msg
                assert R1.columns == R2.columns, msg                        
        
                A2 = R2.get_data()     
                
                assert numpy.allclose(numpy.min(A1), numpy.min(A2))
                assert numpy.allclose(numpy.max(A1), numpy.max(A2))                

                msg = 'Array values of written raster array were not as expected'
                assert numpy.allclose(A1, A2), msg           
                
                # NOTE: This does not always hold as projection text might differ slightly. E.g.
                #assert R1.get_projection() == R2.get_projection(), msg  
                #E.g. These two refer to the same projection
                #GEOGCS["GCS_WGS_1984",DATUM["WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]]
                #GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.2572235630016,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433],AUTHORITY["EPSG","4326"]]
                
                msg = 'Geotransforms were different'
                assert R1.get_geotransform() == R2.get_geotransform(), msg                  
    def test_nodata(self):
        """Test that NODATA is treated correctly
        """

        filename = "data/test_grid.asc"
        R = read_coverage(filename)

        nan = R.get_nodata_value()
        assert nan == -9999

        A = R.get_data(nan=False)
        assert numpy.min(A[:]) == -9999
        assert numpy.allclose(numpy.max(A[:]), 50.9879837036)

        A = R.get_data(nan=True)
        assert numpy.allclose(numpy.nanmin(A[:]), -50.60135540866)
        assert numpy.allclose(numpy.nanmax(A[:]), 50.9879837036)
Exemple #5
0
    def test_raster_extrema(self):
        """Test that raster extrema are correct.
        """

        # FIXME (Ole): Some datasets show very large differences between extrema in the array and 
        # those computed by GDAL. This may warrant another bug report to GEOS
        
                              
        for coveragename in ['Earthquake_Ground_Shaking_clip.tif',
                             'Population_2010_clip.tif',
                             'shakemap_padang_20090930.asc',
                             'population_padang_1.asc',
                             'population_padang_2.asc']:
        
            
            filename = 'data/%s' % coveragename
            for R in [Raster(filename), read_coverage(filename)]:
                
                # Check consistency of raster
                minimum, maximum = R.get_extrema()
                
                # Check that arrays with NODATA value replaced by NaN's agree
                A = R.get_data(nan=False)
                B = R.get_data(nan=True)
                
                assert A.dtype == B.dtype
                assert numpy.nanmax(A-B) == 0                
                assert numpy.nanmax(B-A) == 0                                
                assert numpy.nanmax(numpy.abs(A-B)) == 0

                # Check that GDAL's reported extrema match real extrema
                # FIXME (Ole): The discrepancies are not acceptable. Report to GEOS.                
                assert numpy.allclose(maximum, numpy.max(A[:]), rtol=1.0e-1) # FIXME: Very very high rtol                         
                assert numpy.allclose(maximum, numpy.nanmax(B[:]), rtol=1.0e-1) # FIXME: Very very high rtol         

                assert numpy.allclose(minimum, numpy.min(A[:]), rtol=1e-2) # FIXME: Not good either           
    def test_get_raster_data(self):
        """Test that raster data can be retrieved from server and read into Python Raster object.
        """

        for coverage_name, reference_range in [('shakemap_padang_20090930', [3.025794, 8.00983]),
                                               ('population_padang_1', [50., 1835.]),
                                               ('population_padang_2', [50., 1835.]), 
                                               ('fatality_padang_1', [4.08928e-07, 0.5672711486]),
                                               ('fatality_padang_2', [4.08928e-07, 1.07241])]:
    
            # Upload first to make sure data is there
            self.api.create_workspace(geoserver_username, geoserver_userpass, geoserver_url, test_workspace_name)

            lh = self.api.create_geoserver_layer_handle(geoserver_username, 
                                                        geoserver_userpass, 
                                                        geoserver_url, 
                                                        coverage_name,
                                                        test_workspace_name)

            upload_filename = 'data/%s.asc' % coverage_name
            res = self.api.upload_geoserver_layer(upload_filename, lh)
            assert res.startswith('SUCCESS'), res                
    
            # Get bounding box for the uploaded TIF file
            bounding_box = get_bounding_box('%s.tif' % coverage_name)
    
                            
            # Download using the API and test that the data is the same.
            raster = self.api.get_raster_data(lh,
                                              bounding_box)
                                             
        
            #ref_shape = (254, 250) # FIXME (Ole): This is what it should be
            ref_shape = (253, 249)  # but Geoserver shrinks it by one row and one column?????????
            
            data = raster.get_data(nan=True)
            
            shape = data.shape
            msg = 'Got shape %s, should have been %s' % (shape, ref_shape)        
            assert numpy.allclose(shape, ref_shape), msg
        
            # Now compare the numerical data
            reference_raster = read_coverage(upload_filename)
            ref_data = reference_raster.get_data(nan=True)
        
            # Range
            assert numpy.allclose([numpy.nanmin(ref_data[:]), numpy.nanmax(ref_data[:])], 
                                  reference_range)        
            assert numpy.allclose([numpy.nanmin(data[:]), numpy.nanmax(data[:])], 
                                  reference_range)
                           
            # Sum up (ignoring NaN) and compare
            refsum = numpy.nansum(numpy.abs(ref_data))
            actualsum = numpy.nansum(numpy.abs(data))            
            
            #print 
            #print 'Ref vs act and diff', refsum, actualsum, abs(refsum - actualsum), abs(refsum - actualsum)/refsum
            assert abs(refsum - actualsum)/refsum < 1.0e-2

            
            # Check that raster data can be written back (USING COMPLETE HACK)
            try:
                i += 1
            except:
                i = 0
                
            layername = 'stored_raster_%i' % i    
            output_file = 'data/%s.asc' % layername
            write_coverage_to_ascii(raster.data, output_file, 
                                    xllcorner = bounding_box[0],
                                    yllcorner = bounding_box[1],
                                    cellsize=0.030741064,
                                    nodata_value=-9999,
                                    projection=open('data/%s.prj' % coverage_name).read())
                                                
            # And upload it again
            lh = self.api.create_geoserver_layer_handle(geoserver_username, 
                                                        geoserver_userpass, 
                                                        geoserver_url, 
                                                        '',
                                                        test_workspace_name)

            self.api.upload_geoserver_layer(output_file, lh)
            
            # Check that layer is there
            found = False
            page = get_web_page(os.path.join(geoserver_url, 'rest/layers'), 
                                username=geoserver_username, 
                                password=geoserver_userpass)
            for line in page:
                if line.find('rest/layers/%s.html' % layername) > 0:
                    found = True
                                                                                                          
            assert found