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
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)
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