def test_bounds_within_meridian(): host = GeoDict({'xmin': -180, 'xmax': 150, 'ymin': -90, 'ymax': 90, 'dx': 30, 'dy': 45, 'nx': 12, 'ny': 5}) sample = GeoDict({'xmin': 75, 'xmax': -135, 'ymin': -67.5, 'ymax': 67.5, 'dx': 30, 'dy': 45, 'nx': 6, 'ny': 4}) result = GeoDict({'xmin': 90, 'xmax': -150, 'ymin': -45, 'ymax': 45, 'dx': 30, 'dy': 45, 'nx': 5, 'ny': 3}) inside = host.getBoundsWithin(sample) assert inside == result
def test_grid_hdf_container(): f,fname = tempfile.mkstemp() os.close(f) try: #test grid container container = GridHDFContainer.create(fname) # before we put anything in here, let's make sure we get empty lists from # all of the methods that are supposed to return lists of stuff. assert container.getGrids() == [] #test grid2d geodict = GeoDict.createDictFromBox(-118.5,-114.5,32.1,36.7,0.01,0.02) nrows,ncols = geodict.ny,geodict.nx data = np.random.rand(nrows,ncols) metadata = {'name':'Gandalf', 'color':'white', 'powers':'magic'} grid = Grid2D(data,geodict) container.setGrid('testgrid',grid,metadata=metadata) outgrid,outmetadata = container.getGrid('testgrid') np.testing.assert_array_equal(outgrid.getData(),data) assert outgrid.getGeoDict() == geodict assert outmetadata == metadata #set another grid without compression geodict = GeoDict.createDictFromBox(-119.5,-115.5,32.3,37.7,0.01,0.02) nrows,ncols = geodict.ny,geodict.nx data = np.random.rand(nrows,ncols) metadata = {'name':'Legolas', 'color':'green', 'powers':'stealth'} grid2 = Grid2D(data,geodict) container.setGrid('testgrid2',grid2,metadata=metadata,compression=False) outgrid2,outmetadata2 = container.getGrid('testgrid2') np.testing.assert_array_equal(outgrid2.getData(),data) assert outgrid2.getGeoDict() == geodict assert outmetadata2 == metadata #test getGridNames() names = container.getGrids() assert sorted(names) == ['testgrid','testgrid2'] #test looking for a grid that does not exist try: container.getGrid('foo') except LookupError as le: pass #test dropping a grid container.dropGrid('testgrid2') container.close() container2 = GridHDFContainer.load(fname) names = container2.getGrids() assert sorted(names) == ['testgrid'] except: assert 1==2 finally: os.remove(fname)
def test_contains(): fxmin, fxmax = (-179.995833333333, 179.99583333189372) fymin, fymax = (-89.99583333333332, 89.9958333326134) fdx, fdy = (0.0083333333333, 0.0083333333333) fnx, fny = (43200, 21600) xmin, xmax = (-179.996, -177.496) ymin, ymax = (-21.89175, -19.55425) dx, dy = (0.025, 0.02513440860215052) nx, ny = (101, 94) host = GeoDict({'xmin': fxmin, 'xmax': fxmax, 'ymin': fymin, 'ymax': fymax, 'dx': fdx, 'dy': fdy, 'nx': fnx, 'ny': fny}) sample = GeoDict({'xmin': xmin, 'xmax': xmax, 'ymin': ymin, 'ymax': ymax, 'dx': dx, 'dy': dy, 'nx': nx, 'ny': ny}) assert host.contains(sample)
def test_bounds_within_again(): fxmin, fxmax = (-179.995833333333, 179.99583333189372) fymin, fymax = (-89.99583333333332, 89.9958333326134) fdx, fdy = (0.0083333333333, 0.0083333333333) fnx, fny = (43200, 21600) xmin, xmax = (97.233, 99.733) ymin, ymax = (84.854, 85.074) dx, dy = (0.025, 0.024444444444444317) nx, ny = (101, 10) host = GeoDict({'xmin': fxmin, 'xmax': fxmax, 'ymin': fymin, 'ymax': fymax, 'dx': fdx, 'dy': fdy, 'nx': fnx, 'ny': fny}) sample = GeoDict({'xmin': xmin, 'xmax': xmax, 'ymin': ymin, 'ymax': ymax, 'dx': dx, 'dy': dy, 'nx': nx, 'ny': ny}) inside = host.getBoundsWithin(sample)
def test_bounds_meridian2(): host = {'ny': 797, 'dx': 0.0083333333, 'ymin': -21.445972496439, 'dy': 0.0083333333, 'xmin': 178.33735967776101, 'nx': 841, 'xmax': -174.66264035023897, 'ymax': -14.812639189639} sample = {'ny': 773, 'dx': 0.008333333333333333, 'ymin': -21.35, 'dy': 0.008333333333333333, 'xmin': 178.43333333333334, 'nx': 817, 'xmax': -174.76666666666665, 'ymax': -14.916666666666666} host_geodict = GeoDict(host) sample_geodict = GeoDict(sample) within = host_geodict.getBoundsWithin(sample_geodict) assert within.xmin == 178.437359677361 assert within.xmax == -174.770973683139
def test_write(): data = np.arange(0, 25).reshape(5, 5).astype(np.float32) gdict = { 'xmin': 5.0, 'xmax': 9.0, 'ymin': 4.0, 'ymax': 8.0, 'dx': 1.0, 'dy': 1.0, 'nx': 5, 'ny': 5 } gd = GeoDict(gdict) grid = Grid2D(data, gd) for format_type in ['netcdf', 'esri', 'hdf']: tdir = tempfile.mkdtemp() fname = os.path.join(tdir, 'tempfile.grd') try: write(grid, fname, format_type) src = rasterio.open(fname, 'r') tdata = src.read(1) np.testing.assert_almost_equal(tdata, data) except Exception as e: raise e finally: shutil.rmtree(tdir)
def test_rasterize(): geodict = GeoDict({'xmin':0.5,'xmax':3.5, 'ymin':0.5,'ymax':3.5, 'dx':1.0,'dy':1.0, 'ny':4,'nx':4}) print('Testing rasterizeFromGeometry() burning in values from a polygon sequence...') #Define two simple polygons and assign them to shapes poly1 = [(0.25,3.75),(1.25,3.25),(1.25,2.25)] poly2 = [(2.25,3.75),(3.25,3.75),(3.75,2.75),(3.75,1.50),(3.25,0.75),(2.25,2.25)] shape1 = {'properties':{'value':5},'geometry':mapping(Polygon(poly1))} shape2 = {'properties':{'value':7},'geometry':mapping(Polygon(poly2))} shapes = [shape1,shape2] print('Testing burning in values where polygons need not contain pixel centers...') grid = Grid2D.rasterizeFromGeometry(shapes,geodict,fillValue=0,attribute='value',mustContainCenter=False) output = np.array([[5,5,7,7], [5,5,7,7], [0,0,7,7], [0,0,0,7]]) np.testing.assert_almost_equal(grid.getData(),output) print('Passed burning in values where polygons need not contain pixel centers.') print('Testing burning in values where polygons must contain pixel centers...') grid2 = Grid2D.rasterizeFromGeometry(shapes,geodict,fillValue=0,attribute='value',mustContainCenter=True) output = np.array([[5,0,7,0], [0,0,7,7], [0,0,0,7], [0,0,0,0]]) np.testing.assert_almost_equal(grid2.getData(),output) print('Passed burning in values where polygons must contain pixel centers.')
def getNoDataGrid(predictors,xmin,xmax,ymin,ymax): txmin = xmin txmax = xmax tymin = ymin tymax = ymax mindx = 9999999999 mindy = 9999999999 #figure out bounds enclosing all files for predname,predfile in predictors.items(): if not os.path.isfile(predfile): continue ftype = getFileType(predfile) if ftype == 'shapefile': f = fiona.open(predfile,'r') bxmin,bymin,bxmax,bymax = f.bounds f.close() if bxmin < txmin: txmin = bxmin if bxmax > txmax: txmax = bxmax if bymin < tymin: tymin = bymin if bymax > tymax: tymax = bymax elif ftype == 'grid': gridtype = getGridType(predfile) if gridtype is None: raise Exception('File "%s" does not appear to be either a GMT grid or an ESRI grid.' % gridfile) fdict = getFileGeoDict(predfile,gridtype) if fdict.dx < mindx: mindx = fdict.dx if fdict.dy < mindy: mindy = fdict.dy if fdict.xmin < txmin: txmin = fdict.xmin if fdict.xmax > txmax: txmax = txmax if fdict.ymin < tymin: tymin = tymin if fdict.ymax > tymax: tymax = tymax sdict = GeoDict.createDictFromBox(txmin,txmax,tymin,tymax,mindx,mindy) nanarray = np.zeros((sdict.ny,sdict.nx),dtype=np.int8) for predname,predfile in predictors.items(): if not os.path.isfile(predfile): continue ftype = getFileType(predfile) if ftype == 'shapefile': shapes = list(fiona.open(predfile,'r')) grid = Grid2D.rasterizeFromGeometry(shapes,sdict) else: gridtype = getGridType(predfile) if gridtype == 'gmt': grid = GMTGrid.load(predfile,samplegeodict=sdict,resample=True,method='nearest',doPadding=True) else: grid = GDALGrid.load(predfile,samplegeodict=sdict,resample=True,method='nearest',doPadding=True) nangrid = np.isnan(grid.getData()) nanarray = nanarray | nangrid nangrid = Grid2D(data=nanarray,geodict=sdict) return nangrid
def make_overlay(adict): """ Make a transparent PNG of intensity and a world file Args: adict (dict): The usual dictionary for the mapping functions. Returns: nothing: Nothing. """ mmidict = adict['imtdict'] mmi_array = mmidict['mean'] geodict = GeoDict(mmidict['mean_metadata']) palette = ColorPalette.fromPreset('mmi') mmi_rgb = palette.getDataColor(mmi_array, color_format='array') img = Image.fromarray(mmi_rgb) pngfile = os.path.join(adict['datadir'], 'intensity_overlay.png') img.save(pngfile, "PNG") # write out a world file # https://en.wikipedia.org/wiki/World_file worldfile = os.path.join(adict['datadir'], 'intensity_overlay.pngw') with open(worldfile, 'wt') as f: f.write('%.4f\n' % geodict.dx) f.write('0.0\n') f.write('0.0\n') f.write('-%.4f\n' % geodict.dy) f.write('%.4f\n' % geodict.xmin) f.write('%.4f\n' % geodict.ymax) return
def _trim_grid(ingrid): outgrid = Grid2D.copyFromGrid(ingrid) while np.isnan(outgrid._data).any(): nrows, ncols = outgrid._data.shape top = outgrid._data[0, :] bottom = outgrid._data[-1, :] left = outgrid._data[:, 0] right = outgrid._data[:, -1] ftop = np.isnan(top).sum() / ncols fbottom = np.isnan(bottom).sum() / ncols fleft = np.isnan(left).sum() / nrows fright = np.isnan(right).sum() / nrows side = np.argmax([ftop, fbottom, fleft, fright]) gdict = outgrid.getGeoDict().asDict() if side == 0: # removing top row outgrid._data = outgrid._data[1:, :] gdict['ymax'] -= gdict['dy'] gdict['ny'] -= 1 elif side == 1: # removing bottom row outgrid._data = outgrid._data[0:-1, :] gdict['ymin'] += gdict['dy'] gdict['ny'] -= 1 elif side == 2: # removing left column outgrid._data = outgrid._data[:, 1:] gdict['xmin'] += gdict['dx'] gdict['nx'] -= 1 elif side == 3: # removing right column outgrid._data = outgrid._data[:, 0:-1] gdict['xmax'] -= gdict['dx'] gdict['nx'] -= 1 geodict = GeoDict(gdict) outgrid = Grid2D(data=outgrid._data, geodict=geodict) return outgrid
def test_setData(): data = np.arange(0, 16).astype(np.float32).reshape(4, 4) geodict = GeoDict({ 'xmin': 0.5, 'xmax': 3.5, 'ymin': 0.5, 'ymax': 3.5, 'dx': 1.0, 'dy': 1.0, 'ny': 4, 'nx': 4 }) grid1 = Grid2D(data, geodict) x = np.ones((4, 4)) try: grid1.setData(x) #this should pass print('setData test passed.') except DataSetException as dse: print('setData test failed.') try: x = np.ones((5, 5)) grid1.setData(x) print('setData test did not fail when it should have.') except DataSetException as dse: print('setData test failed as expected.') try: x = 'fred' grid1.setData(x) print('setData test did not fail when it should have.') except DataSetException as dse: print('setData test failed as expected.')
def test_mapmaker_intensity(): homedir = os.path.dirname( os.path.abspath(__file__)) # where is this script? shakedir = os.path.abspath(os.path.join(homedir, '..', '..', '..')) out_file = os.path.join(shakedir, 'tests', 'data', 'containers', 'northridge', 'shake_result.hdf') container = ShakeMapOutputContainer.load(out_file) topofile = os.path.join(homedir, '..', '..', 'data', 'install', 'data', 'mapping', 'CA_topo.grd') info = container.getMetadata() xmin = info['output']['map_information']['min']['longitude'] xmax = info['output']['map_information']['max']['longitude'] ymin = info['output']['map_information']['min']['latitude'] ymax = info['output']['map_information']['max']['latitude'] xmin = float(xmin) - 0.1 xmax = float(xmax) + 0.1 ymin = float(ymin) - 0.1 ymax = float(ymax) + 0.1 dy = float(info['output']['map_information']['grid_spacing']['latitude']) dx = float(info['output']['map_information']['grid_spacing']['longitude']) sampledict = GeoDict.createDictFromBox(xmin, xmax, ymin, ymax, dx, dy) topogrid = GMTGrid.load(topofile, samplegeodict=sampledict, resample=False) outpath = mkdtemp() model_config = container.getConfig() comp = container.getComponents('MMI')[0] textfile = os.path.join(get_data_path(), 'mapping', 'map_strings.en') text_dict = get_text_strings(textfile) cities = Cities.fromDefault() d = { 'imtype': 'MMI', 'topogrid': topogrid, 'allcities': cities, 'states_provinces': None, 'countries': None, 'oceans': None, 'lakes': None, 'roads': None, 'faults': None, 'datadir': outpath, 'operator': 'NEIC', 'filter_size': 10, 'info': info, 'component': comp, 'imtdict': container.getIMTGrids('MMI', comp), 'ruptdict': copy.deepcopy(container.getRuptureDict()), 'stationdict': container.getStationDict(), 'config': model_config, 'tdict': text_dict } try: fig1, fig2 = draw_map(d) except Exception: assert 1 == 2 finally: shutil.rmtree(outpath)
def test_bounds_within_real(): fxmin, fxmax = (-179.995833333333, 179.99583333189372) fymin, fymax = (-89.99583333333332, 89.9958333326134) fdx, fdy = (0.0083333333333, 0.0083333333333) fnx, fny = (43200, 21600) xmin, xmax = (177.75, -179.75) ymin, ymax = (50.41625, 51.98375) dx, dy = (0.025, 0.02488095238095242) nx, ny = (101, 64) host = GeoDict({'xmin': fxmin, 'xmax': fxmax, 'ymin': fymin, 'ymax': fymax, 'dx': fdx, 'dy': fdy, 'nx': fnx, 'ny': fny}) sample = GeoDict({'xmin': xmin, 'xmax': xmax, 'ymin': ymin, 'ymax': ymax, 'dx': dx, 'dy': dy, 'nx': nx, 'ny': ny}) result = GeoDict({'xmin': 60, 'xmax': -120, 'ymin': -30, 'ymax': 30, 'dx': 60, 'dy': 30, 'nx': 4, 'ny': 3}) inside = host.getBoundsWithin(sample) ixmin, ixmax = (177.75416666523603, -179.7541666666673) iymin, iymax = (50.4208333327717, 51.9791666660988) idx, idy = (0.0083333333333, 0.0083333333333) inx, iny = (300, 188) result = GeoDict({'xmin': ixmin, 'xmax': ixmax, 'ymin': iymin, 'ymax': iymax, 'dx': idx, 'dy': idy, 'nx': inx, 'ny': iny}) assert inside == result
def test_copy(): data = np.arange(0,16).astype(np.float32).reshape(4,4) geodict = GeoDict({'xmin':0.5,'xmax':3.5,'ymin':0.5,'ymax':3.5,'dx':1.0,'dy':1.0,'ny':4,'nx':4}) grid1 = Grid2D(data,geodict) grid2 = grid1.copyFromGrid(grid1) grid1._data[0,0] = np.nan print(grid2._data) print(grid2._geodict)
def createFromCenter(cls, cx, cy, xspan, yspan, dx, dy, defaultVs30=686.0, vs30File=None, vs30measured_grid=None, backarc=False, padding=False, resample=False): """ Create a Sites object by defining a center point, resolution, extent, and Vs30 values. :param cx: X coordinate of desired center point. :param cy: Y coordinate of desired center point. :param xspan: Width of desired grid. :param yspan: Height of desired grid. :param dx: Resolution of desired grid in X direction. :param dy: Resolution of desired grid in Y direction. :param defaultVs30: Default Vs30 value to use if vs30File not specified. :param vs30File: Name of GMT or GDAL format grid file containing Vs30 values. :param vs30measured_grid: Boolean grid indicating whether Vs30 values were measured or derived (i.e., from slope) :param backarc: Boolean indicating whether event is on the backarc as defined `here <http://earthquake.usgs.gov/learn/glossary/?term=backarc>`__. :param padding: Boolean indicating whether or not to pad resulting Vs30 grid out to edges of input bounds. If False, grid will be clipped to the extent of the input file. :param resample: Boolean indicating whether or not the grid should be resampled. """ geodict = GeoDict.createDictFromCenter(cx, cy, dx, dy, xspan, yspan) if vs30File is not None: vs30grid = cls._create(geodict, defaultVs30, vs30File, padding, resample) else: griddata = np.ones( (geodict.ny, geodict.nx), dtype=np.float64) * defaultVs30 vs30grid = Grid2D(griddata, geodict) return cls(vs30grid, vs30measured_grid=vs30measured_grid, backarc=backarc, defaultVs30=defaultVs30)
def getRegions(self, lat, lon, depth): """Get information about the tectonic region of a given hypocenter. Args: lat (float): Earthquake hypocentral latitude. lon (float): Earthquake hypocentral longitude. depth (float): Earthquake hypocentral depth. Returns: Series: Pandas series object containing labels: - TectonicRegion: Subduction, Active, Stable, or Volcanic. - DistanceToStable: Distance in km to nearest stable region. - DistanceToActive: Distance in km to nearest active region. - DistanceToSubduction: Distance in km to nearest subduction region. - DistanceToVolcanic: Distance in km to nearest volcanic region. - Oceanic: Boolean indicating if epicenter is in the ocean. - DistanceToOceanic: Distance in km to nearest oceanic region. - DistanceToContinental: Distance in km to nearest continental region. """ regions = OrderedDict() gd = GeoDict.createDictFromCenter(lon, lat, DX, DY, XSPAN, YSPAN) tec_grid = read(self._tectonic_grid, samplegeodict=gd) region_dict = get_dist_to_type(lon, lat, tec_grid, TECTONIC_REGIONS) ocean_grid = read(self._oceanic_grid, samplegeodict=gd) ocean_dict = get_dist_to_type(lon, lat, ocean_grid, OCEANIC_REGIONS) if region_dict['DistanceToActive'] == 0: region_dict['TectonicRegion'] = 'Active' elif region_dict['DistanceToStable'] == 0: region_dict['TectonicRegion'] = 'Stable' elif region_dict['DistanceToSubduction'] == 0: region_dict['TectonicRegion'] = 'Subduction' else: region_dict['TectonicRegion'] = 'Volcanic' region_dict['DistanceToOceanic'] = ocean_dict['DistanceToOceanic'] region_dict['DistanceToContinental'] = ocean_dict['DistanceToContinental'] region_dict['Oceanic'] = False if ocean_dict['DistanceToOceanic'] == 0: region_dict['Oceanic'] = True regions = pd.Series(region_dict, index=['TectonicRegion', 'DistanceToStable', 'DistanceToActive', 'DistanceToSubduction', 'DistanceToVolcanic', 'Oceanic', 'DistanceToOceanic', 'DistanceToContinental']) return regions
def getRegions(self, lat, lon, depth): """Get information about the tectonic region of a given hypocenter. Args: lat (float): Earthquake hypocentral latitude. lon (float): Earthquake hypocentral longitude. depth (float): Earthquake hypocentral depth. Returns: Series: Pandas series object containing labels: - TectonicRegion: Subduction, Active, Stable, or Volcanic. - DistanceToStable: Distance in km to nearest stable region. - DistanceToActive: Distance in km to nearest active region. - DistanceToSubduction: Distance in km to nearest subduction region. - DistanceToVolcanic: Distance in km to nearest volcanic region. - Oceanic: Boolean indicating if epicenter is in the ocean. - DistanceToOceanic: Distance in km to nearest oceanic region. - DistanceToContinental: Distance in km to nearest continental region. """ regions = OrderedDict() gd = GeoDict.createDictFromCenter(lon, lat, DX, DY, XSPAN, YSPAN) tec_grid = read(self._tectonic_grid, samplegeodict=gd) region_dict = get_dist_to_type(lon, lat, tec_grid, TECTONIC_REGIONS) ocean_grid = read(self._oceanic_grid, samplegeodict=gd) ocean_dict = get_dist_to_type(lon, lat, ocean_grid, OCEANIC_REGIONS) if region_dict['DistanceToActive'] == 0: region_dict['TectonicRegion'] = 'Active' elif region_dict['DistanceToStable'] == 0: region_dict['TectonicRegion'] = 'Stable' elif region_dict['DistanceToSubduction'] == 0: region_dict['TectonicRegion'] = 'Subduction' else: region_dict['TectonicRegion'] = 'Volcanic' region_dict['DistanceToOceanic'] = ocean_dict['DistanceToOceanic'] region_dict['DistanceToContinental'] = ocean_dict[ 'DistanceToContinental'] region_dict['Oceanic'] = False if ocean_dict['DistanceToOceanic'] == 0: region_dict['Oceanic'] = True regions = pd.Series(region_dict, index=[ 'TectonicRegion', 'DistanceToStable', 'DistanceToActive', 'DistanceToSubduction', 'DistanceToVolcanic', 'Oceanic', 'DistanceToOceanic', 'DistanceToContinental' ]) return regions
def test_basics(): geodict = GeoDict({ 'xmin': 0.5, 'xmax': 3.5, 'ymin': 0.5, 'ymax': 3.5, 'dx': 1.0, 'dy': 1.0, 'ny': 4, 'nx': 4 }) data = np.arange(0, 16).reshape(4, 4).astype(np.float32) grid = Grid2D(data, geodict) print( 'Testing basic Grid2D functionality (retrieving data, lat/lon to pixel coordinates, etc...' ) np.testing.assert_almost_equal(grid.getData(), data) assert grid.getGeoDict() == geodict assert grid.getBounds() == (geodict.xmin, geodict.xmax, geodict.ymin, geodict.ymax) lat, lon = grid.getLatLon(0, 0) assert lat == 3.5 and lon == 0.5 row, col = grid.getRowCol(lat, lon) assert row == 0 and col == 0 value = grid.getValue(lat, lon) assert value == 0 frow, fcol = grid.getRowCol(1.0, 3.0, returnFloat=True) assert frow == 2.5 and fcol == 2.5 irow, icol = grid.getRowCol(1.0, 3.0, returnFloat=False) assert irow == 2 and icol == 2 #test getting values in and outside of the grid bounds lat = np.array([0.0, 0.5, 2.5, 4.0]) lon = np.array([0.0, 0.5, 2.5, 4.0]) default = np.nan output = np.array([np.nan, 12, 6, np.nan]) value = grid.getValue(lat, lon, default=default) np.testing.assert_almost_equal(value, output) print( 'Passed basic Grid2D functionality (retrieving data, lat/lon to pixel coordinates, etc...' )
def sampleGridFile(gridfile, xypoints, method='nearest'): """Sample grid file (ESRI or GMT format) at each of a set of XY (decimal degrees) points. :param gridfile: Name of ESRI or GMT grid format file from which to sample values. :param xypoints: 2D numpy array of XY points, decimal degrees. :param method: Interpolation method, either 'nearest' or 'linear'. :returns: 1D numpy array of grid values at each of input XY points. """ xmin = np.min(xypoints[:, 0]) xmax = np.max(xypoints[:, 0]) ymin = np.min(xypoints[:, 1]) ymax = np.max(xypoints[:, 1]) gridtype = None try: fdict = GMTGrid.getFileGeoDict(gridfile) gridtype = 'gmt' except Exception as error: try: fdict = GDALGrid.getFileGeoDict(gridfile) gridtype = 'esri' except: pass if gridtype is None: raise Exception( 'File "%s" does not appear to be either a GMT grid or an ESRI grid.' % gridfile) xmin = xmin - fdict.dx * 3 xmax = xmax + fdict.dx * 3 ymin = ymin - fdict.dy * 3 ymax = ymax + fdict.dy * 3 #bounds = (xmin, xmax, ymin, ymax) if gridtype == 'gmt': fgeodict = GMTGrid.getFileGeoDict(gridfile) else: fgeodict = GDALGrid.getFileGeoDict(gridfile) dx, dy = (fgeodict.dx, fgeodict.dy) sdict = GeoDict.createDictFromBox(xmin, xmax, ymin, ymax, dx, dy) if gridtype == 'gmt': grid = GMTGrid.load(gridfile, samplegeodict=sdict, resample=False, method=method, doPadding=True) else: grid = GDALGrid.load(gridfile, samplegeodict=sdict, resample=False, method=method, doPadding=True) return sampleFromGrid(grid, xypoints)
def test_intersection(): fxmin, fxmax = (178.311, -179.189) fymin, fymax = (50.616, 52.176) fdx, fdy = (0.025, 0.02516129032258068) fnx, fny = (101, 63) host = GeoDict({'xmin': fxmin, 'xmax': fxmax, 'ymin': fymin, 'ymax': fymax, 'dx': fdx, 'dy': fdy, 'nx': fnx, 'ny': fny}) sxmin, sxmax = (178.31249999999858, -179.19583333333335) symin, symax = (50.62083333333279, 52.17083333333278) sdx, sdy = (0.0083333333333333, 0.0083333333333333) snx, sny = (300, 187) sample = GeoDict({'xmin': sxmin, 'xmax': sxmax, 'ymin': symin, 'ymax': symax, 'dx': sdx, 'dy': sdy, 'nx': snx, 'ny': sny}) ixmin, ixmax = (178.31249999999858, -179.19583333333478) iymin, iymax = (50.62083333333278, 52.17083333333278) idx, idy = (0.0083333333333333, 0.0083333333333333) inx, iny = (300, 187) result = GeoDict({'xmin': ixmin, 'xmax': ixmax, 'ymin': iymin, 'ymax': iymax, 'dx': idx, 'dy': idy, 'nx': inx, 'ny': iny}) intersection = host.getIntersection(sample) np.testing.assert_allclose(intersection.xmin, ixmin) np.testing.assert_allclose(intersection.xmax, ixmax) np.testing.assert_allclose(intersection.ymin, iymin) np.testing.assert_allclose(intersection.ymax, iymax)
def test_interpolate(): geodict = GeoDict({'xmin': 0.5, 'xmax': 6.5, 'ymin': 1.5, 'ymax': 6.5, 'dx': 1.0, 'dy': 1.0, 'ny': 6, 'nx': 7}) data = np.arange(14, 56).reshape(6, 7) for method in ['nearest', 'linear', 'cubic']: print('Testing interpolate with method "%s"...' % method) grid = Grid2D(data, geodict) sampledict = GeoDict({'xmin': 3.0, 'xmax': 4.0, 'ymin': 3.0, 'ymax': 4.0, 'dx': 1.0, 'dy': 1.0, 'ny': 2, 'nx': 2}) grid = grid.interpolateToGrid(sampledict, method=method) tgrid = grid.interpolate2(sampledict, method=method) if method == 'nearest': output = np.array([[30.0, 31.0], [37.0, 38.0]]) elif method == 'linear': output = np.array([[34., 35.], [41., 42.]]) elif method == 'cubic': output = np.array([[34., 35.], [41., 42.]]) else: pass np.testing.assert_almost_equal(grid.getData(), output) print('Passed interpolate with method "%s".' % method) np.testing.assert_almost_equal(tgrid.getData(), output) print('Passed interpolate2 with method "%s".' % method) # speed test of interpolateToGrid and interpolate2 geodict = GeoDict.createDictFromBox(0, 10, 0, 10, 0.01, 0.01) data = np.random.rand(geodict.ny, geodict.nx) grid = Grid2D(data, geodict) sampledict = GeoDict.createDictFromBox(2, 8, 2, 8, 0.098, 0.098) t1 = time.time() grid2 = grid.interpolateToGrid(sampledict, method='linear') t2 = time.time() grid3 = grid.interpolate2(sampledict, method='linear') t3 = time.time() # np.testing.assert_almost_equal(grid2._data.sum(),grid3._data.sum()) print('scipy method: %.3f seconds' % (t2-t1)) print('gdal method: %.3f seconds' % (t3-t2))
def test_cut(): geodict = GeoDict({'xmin': 0.5, 'xmax': 4.5, 'ymin': 0.5, 'ymax': 4.5, 'dx': 1.0, 'dy': 1.0, 'ny': 5, 'nx': 5}) data = np.arange(0, 25).reshape(5, 5) print('Testing data extraction...') grid = Grid2D(data, geodict) xmin, xmax, ymin, ymax = (2.5, 3.5, 2.5, 3.5) newgrid = grid.cut(xmin, xmax, ymin, ymax) output = np.array([[7, 8], [12, 13]]) np.testing.assert_almost_equal(newgrid.getData(), output) print('Passed data extraction...') print('Testing data trimming with resampling...') # make a more complicated test using getboundswithin data = np.arange(0, 84).reshape(7, 12) geodict = GeoDict({'xmin': -180, 'xmax': 150, 'ymin': -90, 'ymax': 90, 'dx': 30, 'dy': 30, 'nx': 12, 'ny': 7}) grid = Grid2D(data, geodict) sampledict = GeoDict.createDictFromBox(-75, 45, -45, 75, geodict.dx, geodict.dy) cutdict = geodict.getBoundsWithin(sampledict) newgrid = grid.cut(cutdict.xmin, cutdict.xmax, cutdict.ymin, cutdict.ymax) output = np.array([[16, 17, 18, 19], [28, 29, 30, 31], [40, 41, 42, 43], [52, 53, 54, 55]]) np.testing.assert_almost_equal(newgrid.getData(), output) print('Passed data trimming with resampling...') print('Test cut with self-alignment...') geodict = GeoDict({'xmin': 0.5, 'xmax': 4.5, 'ymin': 0.5, 'ymax': 6.5, 'dx': 1.0, 'dy': 1.0, 'nx': 5, 'ny': 7}) data = np.arange(0, 35).astype(np.float32).reshape(7, 5) grid = Grid2D(data, geodict) cutxmin = 1.7 cutxmax = 3.7 cutymin = 1.7 cutymax = 5.7 cutgrid = grid.cut(cutxmin, cutxmax, cutymin, cutymax, align=True) output = np.array([[7, 8], [12, 13], [17, 18], [22, 23]]) np.testing.assert_almost_equal(cutgrid.getData(), output) print('Passed cut with self-alignment.')
def test_interpolate(): geodict = GeoDict({'xmin':0.5,'xmax':6.5,'ymin':1.5,'ymax':6.5,'dx':1.0,'dy':1.0,'ny':6,'nx':7}) data = np.arange(14,56).reshape(6,7) for method in ['nearest','linear','cubic']: print('Testing interpolate with method "%s"...' % method) grid = Grid2D(data,geodict) sampledict = GeoDict({'xmin':3.0,'xmax':4.0, 'ymin':3.0,'ymax':4.0, 'dx':1.0,'dy':1.0, 'ny':2,'nx':2}) grid = grid.interpolateToGrid(sampledict,method=method) if method == 'nearest': output = np.array([[30.0,31.0],[37.0,38.0]]) elif method == 'linear': output = np.array([[34.,35.],[41.,42.]]) elif method == 'cubic': output = np.array([[34.,35.],[41.,42.]]) else: pass np.testing.assert_almost_equal(grid.getData(),output) print('Passed interpolate with method "%s".' % method)
def big_test(): xmin = -180 xmax = -170 ymin = 30 ymax = 40 dx = 0.0083 dy = 0.0083 gd = GeoDict.createDictFromBox(xmin, xmax, ymin, ymax, dx, dy) data = np.random.rand(gd.ny, gd.nx) grid = Grid2D(data, gd) fname = os.path.join(os.path.expanduser('~'), 'tempfile.grd') write(grid, fname, 'hdf') print(fname) src = rasterio.open(fname, 'r')
def create_overlay_image(container, filename): """Create a semi-transparent PNG image of intensity. Args: container (ShakeMapOutputContainer): Results of model.conf. filename (str): Path to desired output PNG file. Returns: GeoDict: GeoDict object for the intensity grid. """ # extract the intensity data from the container comp = container.getComponents('MMI') if len(comp) == 0: return None comp = comp[0] imtdict = container.getIMTGrids('MMI', comp) mmigrid = imtdict['mean'] gd = GeoDict(imtdict['mean_metadata']) imtdata = mmigrid.copy() rows, cols = imtdata.shape # get the intensity colormap palette = ColorPalette.fromPreset('mmi') # map intensity values into # RGBA array rgba = palette.getDataColor(imtdata, color_format='array') # set the alpha value to 255 wherever we have MMI 0 rgba[imtdata <= 1.5] = 0 if 'CALLED_FROM_PYTEST' not in os.environ: # mask off the areas covered by ocean oceans = shpreader.natural_earth(category='physical', name='ocean', resolution='10m') bbox = (gd.xmin, gd.ymin, gd.xmax, gd.ymax) with fiona.open(oceans) as c: tshapes = list(c.items(bbox=bbox)) shapes = [] for tshp in tshapes: shapes.append(shape(tshp[1]['geometry'])) if len(shapes): oceangrid = Grid2D.rasterizeFromGeometry(shapes, gd, fillValue=0.0) rgba[oceangrid.getData() == 1] = 0 # save rgba image as png img = Image.fromarray(rgba) img.save(filename) return gd
def test_project(): data = np.array([[0, 0, 1, 0, 0], [0, 0, 1, 0, 0], [1, 1, 1, 1, 1], [0, 0, 1, 0, 0], [0, 0, 1, 0, 0]], dtype=np.int32) geodict = { 'xmin': 50, 'xmax': 50.4, 'ymin': 50, 'ymax': 50.4, 'dx': 0.1, 'dy': 0.1, 'nx': 5, 'ny': 5 } gd = GeoDict(geodict) grid = GDALGrid(data, gd) projstr = "+proj=utm +zone=40 +north +ellps=WGS84 +datum=WGS84 +units=m +no_defs " newgrid = grid.project(projstr, method='nearest') try: tdir = tempfile.mkdtemp() outfile = os.path.join(tdir, 'output.bil') grid.save(outfile) with rasterio.open(outfile) as src: aff = get_affine(src) data = src.read(1) src_crs = CRS().from_string(GeoDict.DEFAULT_PROJ4).to_dict() dst_crs = CRS().from_string(projstr).to_dict() nrows, ncols = data.shape left = aff.xoff top = aff.yoff right, bottom = aff * (ncols - 1, nrows - 1) dst_transform, width, height = calculate_default_transform( src_crs, dst_crs, ncols, nrows, left, bottom, right, top) destination = np.zeros((height, width)) reproject(data, destination, src_transform=aff, src_crs=src_crs, dst_transform=dst_transform, dst_crs=dst_crs, src_nodata=src.nodata, dst_nodata=np.nan, resampling=Resampling.nearest) x = 1 except: pass finally: shutil.rmtree(tdir)
def fromBounds(cls, xmin, xmax, ymin, ymax, dx, dy, defaultVs30=686.0, vs30File=None, vs30measured_grid=None, backarc=None, padding=False, resample=False): """ Create a Sites object by defining a center point, resolution, extent, and Vs30 values. Args: xmin: X coordinate of left edge of bounds. xmax: X coordinate of right edge of bounds. ymin: Y coordinate of bottom edge of bounds. ymax: Y coordinate of top edge of bounds. dx: Resolution of desired grid in X direction. dy: Resolution of desired grid in Y direction. defaultVs30: Default Vs30 value to use if vs30File not specified. vs30File: Name of GMT or GDAL format grid file containing Vs30 values. vs30measured_grid: Boolean grid indicating whether Vs30 values were measured or derived (i.e., from slope). backarc: Boolean array indicating whether site is in the subduction `backarc <http://earthquake.usgs.gov/learn/glossary/?term=backarc>`__. padding: Boolean indicating whether or not to pad resulting Vs30 grid out to edges of input bounds. If False, grid will be clipped to the extent of the input file. resample: Boolean indicating whether or not the grid should be resampled. """ # noqa geodict = GeoDict.createDictFromBox(xmin, xmax, ymin, ymax, dx, dy) if vs30File is not None: vs30grid = cls._create(geodict, defaultVs30, vs30File, padding, resample) else: griddata = np.ones( (geodict.ny, geodict.nx), dtype=np.float64) * defaultVs30 vs30grid = Grid2D(griddata, geodict) return cls(vs30grid, vs30measured_grid=vs30measured_grid, backarc=backarc, defaultVs30=defaultVs30)
def test_lat_lon_array(): gd = GeoDict({'xmin': 0, 'xmax': 4, 'ymin': 0, 'ymax': 3, 'dx': 1.0, 'dy': 1.0, 'nx': 5, 'ny': 4}) lat = np.array([0, 1, 2], dtype=np.float32) lon = np.array([2, 2, 2], dtype=np.float32) trow = np.array([3, 2, 1]) tcol = np.array([2, 2, 2]) row, col = gd.getRowCol(lat, lon) np.testing.assert_almost_equal(trow, row) np.testing.assert_almost_equal(tcol, col) gd = GeoDict({'xmin': 176, 'xmax': -176, 'ymin': 0, 'ymax': 6, 'nx': 5, 'ny': 4, 'dx': 2, 'dy': 2}) lat = np.array([2, 4, 6], dtype=np.float32) lon = np.array([178, 180, -178], dtype=np.float32) row, col = gd.getRowCol(lat, lon) trow = np.array([2, 1, 0]) tcol = np.array([1, 2, 3]) np.testing.assert_almost_equal(trow, row) np.testing.assert_almost_equal(tcol, col)
def test_bounds_within_real(): fxmin, fxmax = (-179.995833333333, 179.99583333189372) fymin, fymax = (-89.99583333333332, 89.9958333326134) fdx, fdy = (0.0083333333333, 0.0083333333333) fnx, fny = (43200, 21600) xmin, xmax = (177.75, -179.75) ymin, ymax = (50.41625, 51.98375) dx, dy = (0.025, 0.02488095238095242) nx, ny = (101, 64) host = GeoDict({ 'xmin': fxmin, 'xmax': fxmax, 'ymin': fymin, 'ymax': fymax, 'dx': fdx, 'dy': fdy, 'nx': fnx, 'ny': fny }) sample = GeoDict({ 'xmin': xmin, 'xmax': xmax, 'ymin': ymin, 'ymax': ymax, 'dx': dx, 'dy': dy, 'nx': nx, 'ny': ny }) result = GeoDict({ 'xmin': 60, 'xmax': -120, 'ymin': -30, 'ymax': 30, 'dx': 60, 'dy': 30, 'nx': 4, 'ny': 3 }) inside = host.getBoundsWithin(sample) ixmin, ixmax = (177.75416666523603, -179.7541666666673) iymin, iymax = (50.4208333327717, 51.9791666660988) idx, idy = (0.0083333333333, 0.0083333333333) inx, iny = (300, 188) result = GeoDict({ 'xmin': ixmin, 'xmax': ixmax, 'ymin': iymin, 'ymax': iymax, 'dx': idx, 'dy': idy, 'nx': inx, 'ny': iny }) assert inside == result
def test_read_meridian(): # where is this script? homedir = os.path.dirname(os.path.abspath(__file__)) # this is an HDF 5 file datafile = os.path.join(homedir, 'data', 'globalgrid_cdf.cdf') sdict = {'xmin': 180, 'xmax': -120, 'ymin': 0, 'ymax': 30, 'nx': 2, 'ny': 2, 'dx': 60, 'dy': 30} sampledict = GeoDict(sdict) grid = read(datafile, samplegeodict=sampledict) assert np.nansum(grid._data) == 50.0
def sampleGridFile(gridfile,xypoints,method='nearest'): """ Sample grid file (ESRI or GMT format) at each of a set of XY (decimal degrees) points. :param gridfile: Name of ESRI or GMT grid format file from which to sample values. :param xypoints: 2D numpy array of XY points, decimal degrees. :param method: Interpolation method, either 'nearest' or 'linear'. :returns: 1D numpy array of grid values at each of input XY points. """ if not len(xypoints): return np.array([]) xmin = np.min(xypoints[:,0]) xmax = np.max(xypoints[:,0]) ymin = np.min(xypoints[:,1]) ymax = np.max(xypoints[:,1]) gridtype = None try: fdict,tmp = GMTGrid.getFileGeoDict(gridfile) gridtype = 'gmt' except Exception as error: try: fdict,tmp = GDALGrid.getFileGeoDict(gridfile) gridtype = 'esri' except: pass if gridtype is None: raise Exception('File "%s" does not appear to be either a GMT grid or an ESRI grid.' % gridfile) xmin = xmin - fdict.dx*3 xmax = xmax + fdict.dx*3 ymin = ymin - fdict.dy*3 ymax = ymax + fdict.dy*3 bounds = (xmin,xmax,ymin,ymax) if gridtype == 'gmt': fgeodict,tmp = GMTGrid.getFileGeoDict(gridfile) else: fgeodict,tmp = GDALGrid.getFileGeoDict(gridfile) dx,dy = (fgeodict.dx,fgeodict.dy) sdict = GeoDict.createDictFromBox(xmin,xmax,ymin,ymax,dx,dy) if gridtype == 'gmt': grid = GMTGrid.load(gridfile,samplegeodict=sdict,resample=True,method=method,doPadding=True) else: grid = GDALGrid.load(gridfile,samplegeodict=sdict,resample=True,method=method,doPadding=True) return sampleFromGrid(grid,xypoints)
def get_data_range_test(): # a standard global grid, going from -180 to 180 normal_dict = GeoDict({'xmin': -180, 'xmax': 120, 'ymin': -90, 'ymax': 90, 'dx': 60, 'dy': 45, 'nx': 6, 'ny': 5}) # test a simple example which does NOT cross the 180 meridian sample1 = (-125, 65, -20, 20) dict1 = Grid2D.getDataRange(normal_dict, sample1) cdict1 = {'iulx1': 0, 'iuly1': 1, 'ilrx1': 6, 'ilry1': 4} assert dict1 == cdict1 # test a less-simple example which DOES cross the 180 meridian sample2 = (-235, -10, -20, 20) dict2 = Grid2D.getDataRange(normal_dict, sample2) cdict2 = {'iulx1': 5, 'iuly1': 1, 'ilrx1': 6, 'ilry1': 4, 'iulx2': 0, 'iuly2': 1, 'ilrx2': 4, 'ilry2': 4} assert dict2 == cdict2 # test a less-simple example which DOES cross the 180 meridian, and xmin > xmax sample3 = (125, -10, -20, 20) dict3 = Grid2D.getDataRange(normal_dict, sample3) cdict3 = {'iulx1': 5, 'iuly1': 1, 'ilrx1': 6, 'ilry1': 4, 'iulx2': 0, 'iuly2': 1, 'ilrx2': 4, 'ilry2': 4} assert dict3 == cdict3 # test an example where the sample bounds are from 0 to 360 sample4 = (160, 200, -20, 20) dict4 = Grid2D.getDataRange(normal_dict, sample4) cdict4 = {'iulx1': 5, 'iuly1': 1, 'ilrx1': 6, 'ilry1': 4, 'iulx2': 0, 'iuly2': 1, 'ilrx2': 2, 'ilry2': 4} assert dict4 == cdict4 # test an example where the sample bounds are from 0 to 360 sample5 = (220, 260, -20, 20) dict5 = Grid2D.getDataRange(normal_dict, sample5) cdict5 = {'iulx1': 0, 'iuly1': 1, 'ilrx1': 3, 'ilry1': 4} assert dict5 == cdict5
def test_read_subset_no_resample(): # where is this script? homedir = os.path.dirname(os.path.abspath(__file__)) # this is an HDF 5 file datafile = os.path.join(homedir, 'data', 'samplegrid_cdf.cdf') sdict = {'xmin': 6, 'xmax': 7, 'ymin': 5, 'ymax': 6, 'nx': 2, 'ny': 2, 'dx': 1, 'dy': 1} sampledict = GeoDict(sdict) grid = read(datafile, samplegeodict=sampledict) tdata = np.array([[11, 12], [16, 17]]) np.testing.assert_almost_equal(grid._data, tdata)
def fromBounds(cls, xmin, xmax, ymin, ymax, dx, dy, defaultVs30=686.0, vs30File=None, vs30measured_grid=None, backarc=None, padding=False, resample=False): """ Create a Sites object by defining a center point, resolution, extent, and Vs30 values. :param xmin: X coordinate of left edge of bounds. :param xmax: X coordinate of right edge of bounds. :param ymin: Y coordinate of bottom edge of bounds. :param ymax: Y coordinate of top edge of bounds. :param dx: Resolution of desired grid in X direction. :param dy: Resolution of desired grid in Y direction. :param defaultVs30: Default Vs30 value to use if vs30File not specified. :param vs30File: Name of GMT or GDAL format grid file containing Vs30 values. :param vs30measured_grid: Boolean grid indicating whether Vs30 values were measured or derived (i.e., from slope) :param backarc: Boolean array indicating whether site is in the subduction `backarc <http://earthquake.usgs.gov/learn/glossary/?term=backarc>`__. :param padding: Boolean indicating whether or not to pad resulting Vs30 grid out to edges of input bounds. If False, grid will be clipped to the extent of the input file. :param resample: Boolean indicating whether or not the grid should be resampled. """ geodict = GeoDict.createDictFromBox(xmin, xmax, ymin, ymax, dx, dy) if vs30File is not None: vs30grid = cls._create(geodict, defaultVs30, vs30File, padding, resample) else: griddata = np.ones((geodict.ny, geodict.nx), dtype=np.float64) * defaultVs30 vs30grid = Grid2D(griddata, geodict) return cls(vs30grid, vs30measured_grid=vs30measured_grid, backarc=backarc, defaultVs30=defaultVs30)
def test_read_subset_with_padding(): # where is this script? homedir = os.path.dirname(os.path.abspath(__file__)) # this is an HDF 5 file datafile = os.path.join(homedir, 'data', 'samplegrid_cdf.cdf') sdict = {'xmin': 4.5, 'xmax': 5.5, 'ymin': 7.5, 'ymax': 8.5, 'nx': 2, 'ny': 2, 'dx': 1, 'dy': 1} sampledict = GeoDict(sdict) grid = read(datafile, samplegeodict=sampledict, resample=False, doPadding=True) assert grid._data.shape == (3, 3) assert grid._data[1, 1] == 0
def test_resample(): # this should fail # where is this script? homedir = os.path.dirname(os.path.abspath(__file__)) # this is an HDF 5 file datafile = os.path.join(homedir, 'data', 'samplegrid_cdf.cdf') sdict = {'xmin': 6.5, 'xmax': 7.5, 'ymin': 5.5, 'ymax': 6.5, 'nx': 2, 'ny': 2, 'dx': 1, 'dy': 1} sampledict = GeoDict(sdict) grid = read(datafile, samplegeodict=sampledict, resample=True) tdata = np.array([[9, 10], [14, 15]]) np.testing.assert_almost_equal(grid._data, tdata)
def test_read_subset_with_resample_and_padding(): # where is this script? homedir = os.path.dirname(os.path.abspath(__file__)) # this is an HDF 5 file datafile = os.path.join(homedir, 'data', 'samplegrid_cdf.cdf') sdict = {'xmin': 4.5, 'xmax': 5.5, 'ymin': 7.5, 'ymax': 8.5, 'nx': 2, 'ny': 2, 'dx': 1, 'dy': 1} sampledict = GeoDict(sdict) grid = read(datafile, samplegeodict=sampledict, resample=True, doPadding=True) atest = np.array([[np.nan, np.nan], [np.nan, 3.]]) np.testing.assert_almost_equal(grid._data, atest)
def test_mapmaker_contour(): homedir = os.path.dirname(os.path.abspath( __file__)) # where is this script? shakedir = os.path.abspath(os.path.join(homedir, '..', '..', '..')) out_file = os.path.join(shakedir, 'tests', 'data', 'containers', 'northridge', 'shake_result.hdf') container = ShakeMapOutputContainer.load(out_file) topofile = os.path.join(homedir, '..', '..', 'data', 'install', 'data', 'mapping', 'CA_topo.grd') info = container.getMetadata() xmin = info['output']['map_information']['min']['longitude'] xmax = info['output']['map_information']['max']['longitude'] ymin = info['output']['map_information']['min']['latitude'] ymax = info['output']['map_information']['max']['latitude'] xmin = float(xmin) - 0.1 xmax = float(xmax) + 0.1 ymin = float(ymin) - 0.1 ymax = float(ymax) + 0.1 dy = float(info['output']['map_information'] ['grid_spacing']['latitude']) dx = float(info['output']['map_information'] ['grid_spacing']['longitude']) sampledict = GeoDict.createDictFromBox(xmin, xmax, ymin, ymax, dx, dy) topogrid = GMTGrid.load(topofile, samplegeodict=sampledict, resample=False) oceanfile = os.path.join(homedir, '..', '..', 'data', 'install', 'data', 'mapping', 'northridge_ocean.json') outpath = mkdtemp() filter_size = 10 try: pdf, png = draw_contour(container, 'PGA', topogrid, oceanfile, outpath, 'NEIC', filter_size) print(pdf) except Exception: assert 1 == 2 finally: shutil.rmtree(outpath)
def test_modify(): print('Testing ShakeGrid interpolate() method...') geodict = GeoDict({ 'xmin': 0.5, 'xmax': 6.5, 'ymin': 1.5, 'ymax': 6.5, 'dx': 1.0, 'dy': 1.0, 'ny': 6, 'nx': 7 }) data = np.arange(14, 56).reshape(6, 7) layers = OrderedDict() layers['pga'] = data shakeDict = { 'event_id': 'usabcd1234', 'shakemap_id': 'usabcd1234', 'shakemap_version': 1, 'code_version': '4.0', 'process_timestamp': datetime.utcnow(), 'shakemap_originator': 'us', 'map_status': 'RELEASED', 'shakemap_event_type': 'ACTUAL' } eventDict = { 'event_id': 'usabcd1234', 'magnitude': 7.6, 'depth': 1.4, 'lat': 2.0, 'lon': 2.0, 'event_timestamp': datetime.utcnow(), 'event_network': 'us', 'event_description': 'sample event' } uncDict = {'pga': (0.0, 0)} shake = ShakeGrid(layers, geodict, eventDict, shakeDict, uncDict) rdata = np.random.rand(data.shape[0], data.shape[1]) shake.setLayer('pga', rdata) newdata = shake.getLayer('pga').getData() np.testing.assert_almost_equal(rdata, newdata)
def getGrid(self, name): """ Retrieve a Grid2D object and any associated metadata from the container. Args: name (str): The name of the Grid2D object stored in the container. Returns: (tuple) Grid2D object, and a dictionary of metadata. """ array_name = '__grid_%s__' % name if array_name not in self._hdfobj: raise LookupError('Array %s not in %s' % (name, self.getFileName())) dset = self._hdfobj[array_name] data = dset[()] array_metadata, meta_metadata = _split_dset_attrs(dset) geodict = GeoDict(array_metadata) grid = Grid2D(data, geodict) return grid, meta_metadata
def createFromCenter(cls,cx,cy,xspan,yspan,dx,dy,defaultVs30=686.0,vs30File=None, vs30measured_grid=None,backarc=False,padding=False,resample=False): """Create a Sites object by defining a center point, resolution, extent, and Vs30 values. :param cx: X coordinate of desired center point. :param cy: X coordinate of desired center point. :param xspan: Width of desired grid. :param yspan: Height of desired grid. :param dx: Resolution of desired grid in X direction. :param dy: Resolution of desired grid in Y direction. :param defaultVs30: Default Vs30 value to use if vs30File not specified. :param vs30File: Name of GMT or GDAL format grid file containing Vs30 values. :param vs30measured_grid: Boolean grid indicating whether Vs30 values were measured or derived (i.e., from slope) :param backarc: Boolean indicating whether event is on the backarc as defined here: http://earthquake.usgs.gov/learn/glossary/?term=backarc :param padding: Boolean indicating whether or not to pad resulting Vs30 grid out to edges of input bounds. If False, grid will be clipped to the extent of the input file. :param resample: Boolean indicating whether or not the grid should be resampled. """ geodict = GeoDict.createDictFromCenter(cx,cy,dx,dy,xspan,yspan) if vs30File is not None: vs30grid = cls._create(geodict,defaultVs30,vs30File,padding,resample) else: griddata = np.ones((geodict.ny,geodict.nx), dtype=np.float64)*defaultVs30 vs30grid = Grid2D(griddata,geodict) return cls(vs30grid,vs30measured_grid=vs30measured_grid,backarc=backarc, defaultVs30=defaultVs30)
def test_getvalue(): array = np.arange(1, 26).reshape(5, 5) gdict = GeoDict({'xmin': 1.0, 'xmax': 5.0, 'ymin': 1.0, 'ymax': 5.0, 'dx': 1.0, 'dy': 1.0, 'nx': 5, 'ny': 5}) grid = Grid2D(array, gdict) assert grid.getValue(3.0, 3.0) == 13 lat = np.array([3.0, 4.0]) lon = np.array([3.0, 3.0]) test = grid.getValue(lat, lon) np.testing.assert_almost_equal(test, np.array([13, 8])) lat = np.array([[3.0, 4.0], [4.0, 5.0]]) lon = np.array([[3.0, 3.0], [4.0, 4.0]]) test = grid.getValue(lat, lon) np.testing.assert_almost_equal(test, np.array([[13, 8], [9, 4]]))
def read_user_file_test(fname, xmin, xmax, ymin, ymax): gd = get_file_geodict(fname) sample = GeoDict.createDictFromBox(xmin, xmax, ymin, ymax, gd.dx, gd.dy) t1 = time.time() grid = read(fname, samplegeodict=sample) t2 = time.time() nrows, ncols = grid._data.shape npixels = nrows*ncols print('%.2f seconds to read %i pixels using h5py' % (t2-t1, npixels)) west, east, south, north = (-105.00416666665, -102.98750000804999, 34.98750000805, 37.00416666665) src = rasterio.open(fname, 'r') window = src.window(west, south, east, north) t1 = time.time() data = src.read(window=window) t2 = time.time() print('%.2f seconds to read %i pixels using rasterio' % (t2-t1, npixels)) ratio = grid._data.sum()/data.sum() print('Ratio of h5py data to rasterio data is %.4f' % ratio) src.close()
def test_shapes(): gd = GeoDict.createDictFromBox(100.0, 102.0, 32.0, 34.0, 0.08, 0.08) # pass in scalar values inrow, incol = (10, 10) lat, lon = gd.getLatLon(inrow, incol) # should get scalar results assert np.isscalar(lat) and np.isscalar(lon) # pass in array values inrow = np.array([10, 11, 12]) incol = np.array([10, 11, 12]) lat, lon = gd.getLatLon(inrow, incol) # should get array results c1 = isinstance(lat, np.ndarray) and lat.shape == inrow.shape c2 = isinstance(lon, np.ndarray) and lon.shape == incol.shape assert c1 and c2 # this should fail, because inputs are un-dimensioned numpy arrays inrow = np.array(10) incol = np.array(10) try: lat, lon = gd.getLatLon(inrow, incol) # should get array results assert 1 == 0 # this should never happen except DataSetException as dse: pass
def test(): # these values taken from the shakemap header of: # http://earthquake.usgs.gov/realtime/product/shakemap/ak12496371/ak/1453829475592/download/grid.xml print('Testing various dictionaries for consistency...') print('Testing consistent dictionary...') # this should pass, and will serve as the comparison from now on gdict = {'xmin': -160.340600, 'xmax': -146.340600, 'ymin': 54.104700, 'ymax': 65.104700, 'dx': 0.025000, 'dy': 0.025000, 'ny': 441, 'nx': 561} gd = GeoDict(gdict) print('Consistent dictionary passed.') print('Testing dictionary with inconsistent resolution...') # this should pass gdict = {'xmin': -160.340600, 'xmax': -146.340600, 'ymin': 54.104700, 'ymax': 65.104700, 'dx': 0.026000, 'dy': 0.026000, 'ny': 441, 'nx': 561} gd3 = GeoDict(gdict, adjust='res') assert gd3 == gd print('Dimensions modification passed.') print('Testing dictionary with inconsistent lower right corner...') # this should pass gdict = {'xmin': -160.340600, 'xmax': -146.350600, 'ymin': 54.103700, 'ymax': 65.104700, 'dx': 0.025000, 'dy': 0.025000, 'ny': 441, 'nx': 561} gd4 = GeoDict(gdict, adjust='bounds') assert gd4 == gd print('Corner modification passed.') print('Testing to make sure lat/lon and row/col calculations are correct...') # make sure the lat/lon row/col calculations are correct ndec = int(np.abs(np.log10(GeoDict.EPS))) lat, lon = gd.getLatLon(0, 0) dlat = np.abs(lat-gd.ymax) dlon = np.abs(lon-gd.xmin) assert dlat < GeoDict.EPS and dlon < GeoDict.EPS row, col = gd.getRowCol(lat, lon) assert row == 0 and col == 0 lat, lon = gd.getLatLon(gd.ny-1, gd.nx-1) dlat = np.abs(lat-gd.ymin) dlon = np.abs(lon-gd.xmax) assert dlat < GeoDict.EPS and dlon < GeoDict.EPS row, col = gd.getRowCol(lat, lon) assert row == (gd.ny-1) and col == (gd.nx-1) print('lat/lon and row/col calculations are correct.') print('Testing a dictionary for a global grid...') # this is the file geodict for Landscan - should pass muster globaldict = {'nx': 43200, 'ny': 20880, 'dx': 0.00833333333333, 'xmax': 179.99583333318935, 'xmin': -179.99583333333334, 'dy': 0.00833333333333, 'ymax': 83.99583333326376, 'ymin': -89.99583333333334} gd5 = GeoDict(globaldict) lat, lon = gd5.getLatLon(gd5.ny-1, gd5.nx-1) dlat = np.abs(lat-gd5.ymin) dlon = np.abs(lon-gd5.xmax) assert dlat < GeoDict.EPS and dlon < GeoDict.EPS print('Global grid is internally consistent.') # Test class methods for creating a GeoDict print('Testing whether GeoDict creator class methods work...') xmin = -121.05333277776235 xmax = -116.03833388890432 ymin = 32.138334444506171 ymax = 36.286665555493826 dx = 0.0083333333333333332 dy = 0.0083333333333333332 gd6 = GeoDict.createDictFromBox( xmin, xmax, ymin, ymax, dx, dy, inside=False) assert gd6.xmax > xmax assert gd6.ymin < ymin print('Created dictionary (outside) is correct.') gd7 = GeoDict.createDictFromBox( xmin, xmax, ymin, ymax, dx, dy, inside=True) assert gd7.xmax < xmax assert gd7.ymin > ymin print('Created dictionary (inside) is correct.') xspan = 2.5 yspan = 2.5 gd8 = GeoDict.createDictFromCenter(xmin, ymin, dx, dy, xspan, yspan) print('Created dictionary (from center point) is valid.') print('Testing a geodict with dx/dy values that are NOT the same...') xmin, xmax, ymin, ymax = (-121.06166611109568, -116.03000055557099, 32.130001111172838, 36.294998888827159) dx, dy = (0.009999722214505959, 0.009999444413578534) td = GeoDict.createDictFromBox(xmin, xmax, ymin, ymax, dx, dy) print('Passed testing a geodict with dx/dy values that are NOT the same...') # test getBoundsWithin # use global grid, and then a shakemap grid that we can get print('Testing getBoundsWithin...') grussia = {'xmin': 155.506400, 'xmax': 161.506400, 'ymin': 52.243000, 'ymax': 55.771000, 'dx': 0.016667, 'dy': 0.016642, 'nx': 361, 'ny': 213} gdrussia = GeoDict(grussia, adjust='res') sampledict = gd5.getBoundsWithin(gdrussia) xSmaller = sampledict.xmin > grussia['xmin'] and sampledict.xmax < grussia['xmax'] ySmaller = sampledict.ymin > grussia['ymin'] and sampledict.ymax < grussia['ymax'] assert xSmaller and ySmaller assert gd5.isAligned(sampledict) print('getBoundsWithin returned correct result.') print('Testing isAligned() method...') gd = GeoDict({'xmin': 0.5, 'xmax': 3.5, 'ymin': 0.5, 'ymax': 3.5, 'dx': 1.0, 'dy': 1.0, 'nx': 4, 'ny': 4}) inside_aligned = GeoDict({'xmin': 1.5, 'xmax': 2.5, 'ymin': 1.5, 'ymax': 2.5, 'dx': 1.0, 'dy': 1.0, 'nx': 2, 'ny': 2}) inside_not_aligned = GeoDict({'xmin': 2.0, 'xmax': 3.0, 'ymin': 2.0, 'ymax': 3.0, 'dx': 1.0, 'dy': 1.0, 'nx': 2, 'ny': 2}) assert gd.isAligned(inside_aligned) assert not gd.isAligned(inside_not_aligned) print('Passed isAligned() method...') print('Testing getAligned method...') popdict = GeoDict({'dx': 0.00833333333333, 'dy': 0.00833333333333, 'nx': 43200, 'ny': 20880, 'xmax': 179.99583333318935, 'xmin': -179.99583333333334, 'ymax': 83.99583333326376, 'ymin': -89.99583333333334}) sampledict = GeoDict({'dx': 0.008333333333333333, 'dy': 0.008336693548387094, 'nx': 601, 'ny': 497, 'xmax': -116.046, 'xmin': -121.046, 'ymax': 36.2785, 'ymin': 32.1435}) aligndict = popdict.getAligned(sampledict) assert popdict.isAligned(aligndict) print('Testing geodict intersects method...') gd1 = GeoDict({'xmin': 0.5, 'xmax': 3.5, 'ymin': 0.5, 'ymax': 3.5, 'dx': 1.0, 'dy': 1.0, 'nx': 4, 'ny': 4}) print('Testing geodict intersects method...') gd2 = GeoDict({'xmin': 2.5, 'xmax': 5.5, 'ymin': 2.5, 'ymax': 5.5, 'dx': 1.0, 'dy': 1.0, 'nx': 4, 'ny': 4}) gd3 = GeoDict({'xmin': 4.5, 'xmax': 7.5, 'ymin': 4.5, 'ymax': 7.5, 'dx': 1.0, 'dy': 1.0, 'nx': 4, 'ny': 4}) gd4 = GeoDict({'xmin': 1.5, 'xmax': 2.5, 'ymin': 1.5, 'ymax': 2.5, 'dx': 1.0, 'dy': 1.0, 'nx': 2, 'ny': 2}) assert gd1.intersects(gd2) assert not gd1.intersects(gd3) print('Passed intersects method...') print('Testing geodict intersects method with real geographic data...') gda = GeoDict({'ymax': 83.62083333333263, 'nx': 43201, 'ny': 20835, 'dx': 0.00833333333333, 'dy': 0.00833333333333, 'xmin': -179.99583333333334, 'ymin': -89.99583333326461, 'xmax': -179.99583333347732}) gdb = GeoDict({'ymax': 28.729166666619193, 'nx': 300, 'ny': 264, 'dx': 0.00833333333333, 'dy': 0.00833333333333, 'xmin': 84.08749999989436, 'ymin': 26.537499999953404, 'xmax': 86.57916666656007}) assert gda.intersects(gdb) print('Passed geodict intersects method with real geographic data.') print('Testing geodict doesNotContain method...') assert gd1.doesNotContain(gd3) assert not gd1.doesNotContain(gd4) print('Passed doesNotContain method...') print('Testing geodict contains method...') assert gd1.contains(gd4) assert not gd1.contains(gd3) print('Passed contains method...')
def test_project(): # test projecting a grid that wraps the 180 meridian gd = GeoDict.createDictFromBox(175, -175, -5, 5, 1.0, 1.0) ncells = gd.ny * gd.nx data = np.arange(0.0, ncells).reshape(gd.ny, gd.nx) grid = GDALGrid(data, gd) projstr = "+proj=merc +lat_ts=55 +lon_0=180 +ellps=WGS84" newgrid = grid.project(projstr, method='nearest') proj = pyproj.Proj(projstr) # what would the ul/lr corners be? ulx, uly = proj(grid._geodict.xmin, grid._geodict.ymax) lrx, lry = proj(grid._geodict.xmax, grid._geodict.ymin) # what if we back-project? newxmin, newymax = proj(newgrid._geodict.xmin, newgrid._geodict.ymax, inverse=True) newxmax, newymin = proj(newgrid._geodict.xmax, newgrid._geodict.ymin, inverse=True) x = 1 # test simple projection data = np.array([[0, 0, 1, 0, 0], [0, 0, 1, 0, 0], [1, 1, 1, 1, 1], [0, 0, 1, 0, 0], [0, 0, 1, 0, 0]], dtype=np.int32) geodict = {'xmin': 50, 'xmax': 50.4, 'ymin': 50, 'ymax': 50.4, 'dx': 0.1, 'dy': 0.1, 'nx': 5, 'ny': 5} gd = GeoDict(geodict) grid = GDALGrid(data, gd) projstr = "+proj=utm +zone=40 +north +ellps=WGS84 +datum=WGS84 +units=m +no_defs " newgrid = grid.project(projstr, method='nearest') try: tdir = tempfile.mkdtemp() outfile = os.path.join(tdir, 'output.bil') grid.save(outfile) with rasterio.open(outfile) as src: aff = get_affine(src) data = src.read(1) src_crs = CRS().from_string(GeoDict.DEFAULT_PROJ4).to_dict() dst_crs = CRS().from_string(projstr).to_dict() nrows, ncols = data.shape left = aff.xoff top = aff.yoff right, bottom = aff * (ncols-1, nrows-1) dst_transform, width, height = calculate_default_transform(src_crs, dst_crs, ncols, nrows, left, bottom, right, top) destination = np.zeros((height, width)) reproject(data, destination, src_transform=aff, src_crs=src_crs, dst_transform=dst_transform, dst_crs=dst_crs, src_nodata=src.nodata, dst_nodata=np.nan, resampling=Resampling.nearest) x = 1 except: pass finally: shutil.rmtree(tdir)
def test_bounds_within(): host = GeoDict({'xmin': -180, 'xmax': 150, 'ymin': -90, 'ymax': 90, 'dx': 30, 'dy': 45, 'nx': 12, 'ny': 5}) sample = GeoDict({'xmin': -75, 'xmax': 45, 'ymin': -67.5, 'ymax': 67.5, 'dx': 30, 'dy': 45, 'nx': 5, 'ny': 4}) result = GeoDict({'xmin': -60, 'xmax': 30, 'ymin': -45, 'ymax': 45, 'dx': 30, 'dy': 45, 'nx': 4, 'ny': 3}) inside = host.getBoundsWithin(sample) assert inside == result # test degenerate case where first pass at getting inside bounds fails (xmax) host = GeoDict({'ymax': 84.0, 'dx': 0.008333333333333333, 'ny': 16801, 'xmax': 179.99166666666667, 'xmin': -180.0, 'nx': 43200, 'dy': 0.008333333333333333, 'ymin': -56.0}) sample = GeoDict({'ymax': 18.933333333333334, 'dx': 0.008333333333333333, 'ny': 877, 'xmax': -90.28333333333333, 'xmin': -97.86666666666666, 'nx': 911, 'dy': 0.008333333333333333, 'ymin': 11.633333333333333}) inside = host.getBoundsWithin(sample) assert sample.contains(inside) # this tests some logic that I can't figure out # a way to make happen inside getBoundsWithin(). newymin, ymin = (11.63333333333334, 11.633333333333333) fdy = 0.008333333333333333 yminrow = 8684.0 fymax = 84.0 newymin -= fdy/2 # bump it down while newymin <= ymin: yminrow = yminrow - 1 newymin = fymax - yminrow*fdy assert newymin > ymin
def test_output_container(): geodict = GeoDict.createDictFromBox(-118.5,-114.5,32.1,36.7,0.01,0.02) nrows,ncols = geodict.ny,geodict.nx #create MMI mean data for maximum component mean_mmi_maximum_data = np.random.rand(nrows,ncols) mean_mmi_maximum_metadata = {'name':'Gandalf', 'color':'white', 'powers':'magic'} mean_mmi_maximum_grid = Grid2D(mean_mmi_maximum_data,geodict) #create MMI std data for maximum component std_mmi_maximum_data = mean_mmi_maximum_data/10 std_mmi_maximum_metadata = {'name':'Legolas', 'color':'green', 'powers':'good hair'} std_mmi_maximum_grid = Grid2D(std_mmi_maximum_data,geodict) #create MMI mean data for rotd50 component mean_mmi_rotd50_data = np.random.rand(nrows,ncols) mean_mmi_rotd50_metadata = {'name':'Gimli', 'color':'brown', 'powers':'axing'} mean_mmi_rotd50_grid = Grid2D(mean_mmi_rotd50_data,geodict) #create MMI std data for rotd50 component std_mmi_rotd50_data = mean_mmi_rotd50_data/10 std_mmi_rotd50_metadata = {'name':'Aragorn', 'color':'white', 'powers':'scruffiness'} std_mmi_rotd50_grid = Grid2D(std_mmi_rotd50_data,geodict) #create PGA mean data for maximum component mean_pga_maximum_data = np.random.rand(nrows,ncols) mean_pga_maximum_metadata = {'name':'Pippin', 'color':'purple', 'powers':'rashness'} mean_pga_maximum_grid = Grid2D(mean_pga_maximum_data,geodict) #create PGA std data for maximum component std_pga_maximum_data = mean_pga_maximum_data/10 std_pga_maximum_metadata = {'name':'Merry', 'color':'grey', 'powers':'hunger'} std_pga_maximum_grid = Grid2D(std_pga_maximum_data,geodict) f,datafile = tempfile.mkstemp() os.close(f) try: container = ShakeMapOutputContainer.create(datafile) container.setIMTGrids('mmi', mean_mmi_maximum_grid,mean_mmi_maximum_metadata, std_mmi_maximum_grid,std_mmi_maximum_metadata, component='maximum') container.setIMTGrids('mmi', mean_mmi_rotd50_grid,mean_mmi_rotd50_metadata, std_mmi_rotd50_grid,std_mmi_rotd50_metadata, component='rotd50') container.setIMTGrids('pga', mean_pga_maximum_grid,mean_pga_maximum_metadata, std_pga_maximum_grid,std_pga_maximum_metadata, component='maximum') #get the maximum MMI imt data mmi_max_dict = container.getIMTGrids('mmi',component='maximum') np.testing.assert_array_equal(mmi_max_dict['mean'].getData(), mean_mmi_maximum_data) np.testing.assert_array_equal(mmi_max_dict['std'].getData(), std_mmi_maximum_data) assert mmi_max_dict['mean_metadata'] == mean_mmi_maximum_metadata assert mmi_max_dict['std_metadata'] == std_mmi_maximum_metadata #get the rotd50 MMI imt data mmi_rot_dict = container.getIMTGrids('mmi',component='rotd50') np.testing.assert_array_equal(mmi_rot_dict['mean'].getData(), mean_mmi_rotd50_data) np.testing.assert_array_equal(mmi_rot_dict['std'].getData(), std_mmi_rotd50_data) assert mmi_rot_dict['mean_metadata'] == mean_mmi_rotd50_metadata assert mmi_rot_dict['std_metadata'] == std_mmi_rotd50_metadata #get list of maximum imts max_imts = container.getIMTs(component='maximum') assert sorted(max_imts) == ['mmi','pga'] #get list of components for mmi mmi_comps = container.getComponents('mmi') assert sorted(mmi_comps) == ['maximum','rotd50'] except Exception as e: raise(e) finally: os.remove(datafile)
gridtype = 'esri' except: pass if gridtype is None: raise Exception('File "%s" does not appear to be either a GMT grid or an ESRI grid.' % gridfile) xmin = xmin - fdict.dx*3 xmax = xmax + fdict.dx*3 ymin = ymin - fdict.dy*3 ymax = ymax + fdict.dy*3 bounds = (xmin,xmax,ymin,ymax) if gridtype == 'gmt': fgeodict = GMTGrid.getFileGeoDict(gridfile) else: fgeodict = GDALGrid.getFileGeoDict(gridfile) dx,dy = (fgeodict.dx,fgeodict.dy) sdict = GeoDict.createDictFromBox(xmin,xmax,ymin,ymax,dx,dy) if gridtype == 'gmt': grid = GMTGrid.load(gridfile,samplegeodict=sdict,resample=False,method=method,doPadding=True) else: grid = GDALGrid.load(gridfile,samplegeodict=sdict,resample=False,method=method,doPadding=True) return sampleFromGrid(grid,xypoints) def sampleFromGrid(grid,xypoints,method='nearest'): """ Sample 2D grid object at each of a set of XY (decimal degrees) points. :param grid: Grid2D object at which to sample data. :param xypoints: 2D numpy array of XY points, decimal degrees. :param method:
def test_rupture_depth(interactive=False): DIP = 17.0 WIDTH = 20.0 GRIDRES = 0.1 names = ['single', 'double', 'triple', 'concave', 'concave_simple', 'ANrvSA'] means = [3.1554422780092461, 2.9224454569459781, 3.0381968625073563, 2.0522694624400271, 2.4805390352818755, 2.8740121776209673] stds = [2.1895293825074575, 2.0506459673526174, 2.0244588429154402, 2.0112565876976416, 2.1599789955270019, 1.6156220309120068] xp0list = [np.array([118.3]), np.array([10.1, 10.1]), np.array([10.1, 10.1, 10.3]), np.array([10.9, 10.5, 10.9]), np.array([10.9, 10.6]), np.array([-76.483, -76.626, -76.757, -76.99, -77.024, -76.925, -76.65, -76.321, -75.997, -75.958])] xp1list = [np.array([118.3]), np.array([10.1, 10.3]), np.array([10.1, 10.3, 10.1]), np.array([10.5, 10.9, 11.3]), np.array([10.6, 10.9]), np.array([-76.626, -76.757, -76.99, -77.024, -76.925, -76.65, -76.321, -75.997, -75.958, -76.006])] yp0list = [np.array([34.2]), np.array([34.2, 34.5]), np.array([34.2, 34.5, 34.8]), np.array([34.2, 34.5, 34.8]), np.array([35.1, 35.2]), np.array([-52.068, -51.377, -50.729, -49.845, -49.192, -48.507, -47.875, -47.478, -47.08, -46.422])] yp1list = [np.array([34.5]), np.array([34.5, 34.8]), np.array([34.5, 34.8, 35.1]), np.array([34.5, 34.8, 34.6]), np.array([35.2, 35.4]), np.array([-51.377, -50.729, -49.845, -49.192, -48.507, -47.875, -47.478, -47.08, -46.422, -45.659])] for i in range(0, len(xp0list)): xp0 = xp0list[i] xp1 = xp1list[i] yp0 = yp0list[i] yp1 = yp1list[i] name = names[i] mean_value = means[i] std_value = stds[i] zp = np.zeros(xp0.shape) strike = azimuth(xp0[0], yp0[0], xp1[-1], yp1[-1]) widths = np.ones(xp0.shape) * WIDTH dips = np.ones(xp0.shape) * DIP strike = [strike] origin = Origin({'eventsourcecode': 'test', 'lat': 0, 'lon': 0, 'depth': 5.0, 'mag': 7.0}) rupture = QuadRupture.fromTrace( xp0, yp0, xp1, yp1, zp, widths, dips, origin, strike=strike) # make a grid of points over both quads, ask for depths ymin = np.nanmin(rupture.lats) ymax = np.nanmax(rupture.lats) xmin = np.nanmin(rupture.lons) xmax = np.nanmax(rupture.lons) xmin = np.floor(xmin * (1 / GRIDRES)) / (1 / GRIDRES) xmax = np.ceil(xmax * (1 / GRIDRES)) / (1 / GRIDRES) ymin = np.floor(ymin * (1 / GRIDRES)) / (1 / GRIDRES) ymax = np.ceil(ymax * (1 / GRIDRES)) / (1 / GRIDRES) geodict = GeoDict.createDictFromBox( xmin, xmax, ymin, ymax, GRIDRES, GRIDRES) nx = geodict.nx ny = geodict.ny depths = np.zeros((ny, nx)) for row in range(0, ny): for col in range(0, nx): lat, lon = geodict.getLatLon(row, col) depth = rupture.getDepthAtPoint(lat, lon) depths[row, col] = depth np.testing.assert_almost_equal(np.nanmean(depths), mean_value) np.testing.assert_almost_equal(np.nanstd(depths), std_value) if interactive: fig, axes = plt.subplots(nrows=2, ncols=1) ax1, ax2 = axes xdata = np.append(xp0, xp1[-1]) ydata = np.append(yp0, yp1[-1]) plt.sca(ax1) plt.plot(xdata, ydata, 'b') plt.sca(ax2) im = plt.imshow(depths, cmap='viridis_r') # noqa ch = plt.colorbar() # noqa fname = os.path.join(os.path.expanduser('~'), 'quad_%s_test.png' % name) print('Saving image for %s quad test... %s' % (name, fname)) plt.savefig(fname) plt.close()
def modelMap(grids, shakefile=None, suptitle=None, inventory_shapefile=None, plotorder=None, maskthreshes=None, colormaps=None, boundaries=None, zthresh=0, scaletype='continuous', lims=None, logscale=False, ALPHA=0.7, maproads=True, mapcities=True, isScenario=False, roadfolder=None, topofile=None, cityfile=None, oceanfile=None, roadcolor='#6E6E6E', watercolor='#B8EEFF', countrycolor='#177F10', outputdir=None, savepdf=True, savepng=True, showplots=False, roadref='unknown', cityref='unknown', oceanref='unknown', printparam=False, ds=True, dstype='mean', upsample=False): """ This function creates maps of mapio grid layers (e.g. liquefaction or landslide models with their input layers) All grids must use the same bounds TO DO change so that all input layers do not have to have the same bounds, test plotting multiple probability layers, and add option so that if PDF and PNG aren't output, opens plot on screen using plt.show() :param grids: Dictionary of N layers and metadata formatted like: maplayers['layer name']={ 'grid': mapio grid2D object, 'label': 'label for colorbar and top line of subtitle', 'type': 'output or input to model', 'description': 'detailed description of layer for subtitle'}. Layer names must be unique. :type name: Dictionary or Ordered dictionary - import collections; grids = collections.OrderedDict() :param shakefile: optional ShakeMap file (url or full file path) to extract information for labels and folder names :type shakefile: Shakemap Event Dictionary :param suptitle: This will be displayed at the top of the plots and in the figure names :type suptitle: string :param plotorder: List of keys describing the order to plot the grids, if None and grids is an ordered dictionary, it will use the order of the dictionary, otherwise it will choose order which may be somewhat random but it will always put a probability grid first :type plotorder: list :param maskthreshes: N x 1 array or list of lower thresholds for masking corresponding to order in plotorder or order of OrderedDict if plotorder is None. If grids is not an ordered dict and plotorder is not specified, this will not work right. If None (default), nothing will be masked :param colormaps: List of strings of matplotlib colormaps (e.g. cm.autumn_r) corresponding to plotorder or order of dictionary if plotorder is None. The list can contain both strings and None e.g. colormaps = ['cm.autumn', None, None, 'cm.jet'] and None's will default to default colormap :param boundaries: None to show entire study area, 'zoom' to zoom in on the area of action (only works if there is a probability layer) using zthresh as a threshold, or a dictionary defining lats and lons in the form of boundaries.xmin = minlon, boundaries.xmax = maxlon, boundaries.ymin = min lat, boundaries.ymax = max lat :param zthresh: threshold for computing zooming bounds, only used if boundaries = 'zoom' :type zthresh: float :param scaletype: Type of scale for plotting, 'continuous' or 'binned' - will be reflected in colorbar :type scaletype: string :param lims: None or Nx1 list of tuples or numpy arrays corresponding to plotorder defining the limits for saturating the colorbar (vmin, vmax) if scaletype is continuous or the bins to use (clev) if scaletype if binned. The list can contain tuples, arrays, and Nones, e.g. lims = [(0., 10.), None, (0.1, 1.5), np.linspace(0., 1.5, 15)]. When None is specified, the program will estimate the limits, when an array is specified but the scale type is continuous, vmin will be set to min(array) and vmax will be set to max(array) :param lims: None or Nx1 list of Trues and Falses corresponding to plotorder defining whether to use a linear or log scale (log10) for plotting the layer. This will be reflected in the labels :param ALPHA: Transparency for mapping, if there is a hillshade that will plot below each layer, it is recommended to set this to at least 0.7 :type ALPHA: float :param maproads: Whether to show roads or not, default True, but requires that roadfile is specified and valid to work :type maproads: boolean :param mapcities: Whether to show cities or not, default True, but requires that cityfile is specified and valid to work :type mapcities: boolean :param isScenario: Whether this is a scenario (True) or a real event (False) (default False) :type isScenario: boolean :param roadfolder: Full file path to folder containing road shapefiles :type roadfolder: string :param topofile: Full file path to topography grid (GDAL compatible) - this is only needed to make a hillshade if a premade hillshade is not specified :type topofile: string :param cityfile: Full file path to Pager file containing city & population information :type cityfile: string :param roadcolor: Color to use for roads, if plotted, default #6E6E6E :type roadcolor: Hex color or other matplotlib compatible way of defining color :param watercolor: Color to use for oceans, lakes, and rivers, default #B8EEFF :type watercolor: Hex color or other matplotlib compatible way of defining color :param countrycolor: Color for country borders, default #177F10 :type countrycolor: Hex color or other matplotlib compatible way of defining color :param outputdir: File path for outputting figures, if edict is defined, a subfolder based on the event id will be created in this folder. If None, will use current directory :param savepdf: True to save pdf figure, False to not :param savepng: True to save png figure, False to not :param ds: True to allow downsampling for display (necessary when arrays are quite large, False to not allow) :param dstype: What function to use in downsampling, options are 'min', 'max', 'median', or 'mean' :param upsample: True to upsample the layer to the DEM resolution for better looking hillshades :returns: * PDF and/or PNG of map * Downsampled and trimmed version of input grids. If no modification was needed for plotting, this will be identical to grids but without the metadata """ if suptitle is None: suptitle = ' ' plt.ioff() defaultcolormap = cm.jet if shakefile is not None: edict = ShakeGrid.load(shakefile, adjust='res').getEventDict() temp = ShakeGrid.load(shakefile, adjust='res').getShakeDict() edict['eventid'] = temp['shakemap_id'] edict['version'] = temp['shakemap_version'] else: edict = None # Get output file location if outputdir is None: print('No output location given, using current directory for outputs\n') outputdir = os.getcwd() if edict is not None: outfolder = os.path.join(outputdir, edict['event_id']) else: outfolder = outputdir if not os.path.isdir(outfolder): os.makedirs(outfolder) # Get plotting order, if not specified if plotorder is None: plotorder = list(grids.keys()) # Get boundaries to use for all plots cut = True if boundaries is None: cut = False keytemp = list(grids.keys()) boundaries = grids[keytemp[0]]['grid'].getGeoDict() elif boundaries == 'zoom': # Find probability layer (will just take the maximum bounds if there is # more than one) keytemp = list(grids.keys()) key1 = [key for key in keytemp if 'model' in key.lower()] if len(key1) == 0: print('Could not find model layer to use for zoom, using default boundaries') keytemp = list(grids.keys()) boundaries = grids[keytemp[0]]['grid'].getGeoDict() else: lonmax = -1.e10 lonmin = 1.e10 latmax = -1.e10 latmin = 1.e10 for key in key1: # get lat lons of areas affected and add, if no areas affected, # switch to shakemap boundaries temp = grids[key]['grid'] xmin, xmax, ymin, ymax = temp.getBounds() lons = np.linspace(xmin, xmax, temp.getGeoDict().nx) lats = np.linspace(ymax, ymin, temp.getGeoDict().ny) # backwards so it plots right row, col = np.where(temp.getData() > float(zthresh)) lonmin = lons[col].min() lonmax = lons[col].max() latmin = lats[row].min() latmax = lats[row].max() # llons, llats = np.meshgrid(lons, lats) # make meshgrid # llons1 = llons[temp.getData() > float(zthresh)] # llats1 = llats[temp.getData() > float(zthresh)] # if llons1.min() < lonmin: # lonmin = llons1.min() # if llons1.max() > lonmax: # lonmax = llons1.max() # if llats1.min() < latmin: # latmin = llats1.min() # if llats1.max() > latmax: # latmax = llats1.max() boundaries1 = {'dx': 100, 'dy': 100., 'nx': 100., 'ny': 100} # dummy fillers, only really care about bounds if xmin < lonmin-0.15*(lonmax-lonmin): boundaries1['xmin'] = lonmin-0.1*(lonmax-lonmin) else: boundaries1['xmin'] = xmin if xmax > lonmax+0.15*(lonmax-lonmin): boundaries1['xmax'] = lonmax+0.1*(lonmax-lonmin) else: boundaries1['xmax'] = xmax if ymin < latmin-0.15*(latmax-latmin): boundaries1['ymin'] = latmin-0.1*(latmax-latmin) else: boundaries1['ymin'] = ymin if ymax > latmax+0.15*(latmax-latmin): boundaries1['ymax'] = latmax+0.1*(latmax-latmin) else: boundaries1['ymax'] = ymax boundaries = GeoDict(boundaries1, adjust='res') else: # SEE IF BOUNDARIES ARE SAME AS BOUNDARIES OF LAYERS keytemp = list(grids.keys()) tempgdict = grids[keytemp[0]]['grid'].getGeoDict() if np.abs(tempgdict.xmin-boundaries['xmin']) < 0.05 and \ np.abs(tempgdict.ymin-boundaries['ymin']) < 0.05 and \ np.abs(tempgdict.xmax-boundaries['xmax']) < 0.05 and \ np.abs(tempgdict.ymax - boundaries['ymax']) < 0.05: print('Input boundaries are almost the same as specified boundaries, no cutting needed') boundaries = tempgdict cut = False else: try: if boundaries['xmin'] > boundaries['xmax'] or \ boundaries['ymin'] > boundaries['ymax']: print('Input boundaries are not usable, using default boundaries') keytemp = list(grids.keys()) boundaries = grids[keytemp[0]]['grid'].getGeoDict() cut = False else: # Build dummy GeoDict boundaries = GeoDict({'xmin': boundaries['xmin'], 'xmax': boundaries['xmax'], 'ymin': boundaries['ymin'], 'ymax': boundaries['ymax'], 'dx': 100., 'dy': 100., 'ny': 100., 'nx': 100.}, adjust='res') except: print('Input boundaries are not usable, using default boundaries') keytemp = list(grids.keys()) boundaries = grids[keytemp[0]]['grid'].getGeoDict() cut = False # Pull out bounds for various uses bxmin, bxmax, bymin, bymax = boundaries.xmin, boundaries.xmax, boundaries.ymin, boundaries.ymax # Determine if need a single panel or multi-panel plot and if multi-panel, # how many and how it will be arranged fig = plt.figure() numpanels = len(grids) if numpanels == 1: rowpan = 1 colpan = 1 # create the figure and axes instances. fig.set_figwidth(5) elif numpanels == 2 or numpanels == 4: rowpan = np.ceil(numpanels/2.) colpan = 2 fig.set_figwidth(13) else: rowpan = np.ceil(numpanels/3.) colpan = 3 fig.set_figwidth(15) if rowpan == 1: fig.set_figheight(rowpan*6.0) else: fig.set_figheight(rowpan*5.3) # Need to update naming to reflect the shakemap version once can get # getHeaderData to work, add edict['version'] back into title, maybe # shakemap id also? fontsizemain = 14. fontsizesub = 12. fontsizesmallest = 10. if rowpan == 1.: fontsizemain = 12. fontsizesub = 10. fontsizesmallest = 8. if edict is not None: if isScenario: title = edict['event_description'] else: timestr = edict['event_timestamp'].strftime('%b %d %Y') title = 'M%.1f %s v%i - %s' % (edict['magnitude'], timestr, edict['version'], edict['event_description']) plt.suptitle(title+'\n'+suptitle, fontsize=fontsizemain) else: plt.suptitle(suptitle, fontsize=fontsizemain) clear_color = [0, 0, 0, 0.0] # Cut all of them and release extra memory xbuff = (bxmax-bxmin)/10. ybuff = (bymax-bymin)/10. cutxmin = bxmin-xbuff cutymin = bymin-ybuff cutxmax = bxmax+xbuff cutymax = bymax+ybuff if cut is True: newgrids = collections.OrderedDict() for k, layer in enumerate(plotorder): templayer = grids[layer]['grid'] try: newgrids[layer] = {'grid': templayer.cut(cutxmin, cutxmax, cutymin, cutymax, align=True)} except Exception as e: print(('Cutting failed, %s, continuing with full layers' % e)) newgrids = grids continue del templayer gc.collect() else: newgrids = grids tempgdict = newgrids[list(grids.keys())[0]]['grid'].getGeoDict() # Upsample layers to same as topofile if desired for better looking hillshades if upsample is True and topofile is not None: try: topodict = GDALGrid.getFileGeoDict(topofile) if topodict.dx >= tempgdict.dx or topodict.dy >= tempgdict.dy: print('Upsampling not possible, resolution of results already smaller than DEM') pass else: tempgdict1 = GeoDict({'xmin': tempgdict.xmin-xbuff, 'ymin': tempgdict.ymin-ybuff, 'xmax': tempgdict.xmax+xbuff, 'ymax': tempgdict.ymax+ybuff, 'dx': topodict.dx, 'dy': topodict.dy, 'nx': topodict.nx, 'ny': topodict.ny}, adjust='res') tempgdict2 = tempgdict1.getBoundsWithin(tempgdict) for k, layer in enumerate(plotorder): newgrids[layer]['grid'] = newgrids[layer]['grid'].subdivide(tempgdict2) except: print('Upsampling failed, continuing') # Downsample all of them for plotting, if needed, and replace them in # grids (to save memory) tempgrid = newgrids[list(grids.keys())[0]]['grid'] xsize = tempgrid.getGeoDict().nx ysize = tempgrid.getGeoDict().ny inchesx, inchesy = fig.get_size_inches() divx = int(np.round(xsize/(500.*inchesx))) divy = int(np.round(ysize/(500.*inchesy))) xmin, xmax, ymin, ymax = tempgrid.getBounds() gdict = tempgrid.getGeoDict() # Will be replaced if downsampled del tempgrid gc.collect() if divx <= 1: divx = 1 if divy <= 1: divy = 1 if (divx > 1. or divy > 1.) and ds: if dstype == 'max': func = np.nanmax elif dstype == 'min': func = np.nanmin elif dstype == 'med': func = np.nanmedian else: func = np.nanmean for k, layer in enumerate(plotorder): layergrid = newgrids[layer]['grid'] dat = block_reduce(layergrid.getData().copy(), block_size=(divy, divx), cval=float('nan'), func=func) if k == 0: lons = block_reduce(np.linspace(xmin, xmax, layergrid.getGeoDict().nx), block_size=(divx,), func=np.mean, cval=float('nan')) if math.isnan(lons[-1]): lons[-1] = lons[-2] + (lons[1]-lons[0]) lats = block_reduce(np.linspace(ymax, ymin, layergrid.getGeoDict().ny), block_size=(divy,), func=np.mean, cval=float('nan')) if math.isnan(lats[-1]): lats[-1] = lats[-2] + (lats[1]-lats[0]) gdict = GeoDict({'xmin': lons.min(), 'xmax': lons.max(), 'ymin': lats.min(), 'ymax': lats.max(), 'dx': np.abs(lons[1]-lons[0]), 'dy': np.abs(lats[1]-lats[0]), 'nx': len(lons), 'ny': len(lats)}, adjust='res') newgrids[layer]['grid'] = Grid2D(dat, gdict) del layergrid, dat else: lons = np.linspace(xmin, xmax, xsize) lats = np.linspace(ymax, ymin, ysize) # backwards so it plots right side up #make meshgrid llons1, llats1 = np.meshgrid(lons, lats) # See if there is an oceanfile for masking bbox = PolygonSH(((cutxmin, cutymin), (cutxmin, cutymax), (cutxmax, cutymax), (cutxmax, cutymin))) if oceanfile is not None: try: f = fiona.open(oceanfile) oc = next(f) f.close shapes = shape(oc['geometry']) # make boundaries into a shape ocean = shapes.intersection(bbox) except: print('Not able to read specified ocean file, will use default ocean masking') oceanfile = None if inventory_shapefile is not None: try: f = fiona.open(inventory_shapefile) invshp = list(f.items(bbox=(bxmin, bymin, bxmax, bymax))) f.close() inventory = [shape(inv[1]['geometry']) for inv in invshp] except: print('unable to read inventory shapefile specified, will not plot inventory') inventory_shapefile = None # # Find cities that will be plotted if mapcities is True and cityfile is not None: try: mycity = BasemapCities.loadFromGeoNames(cityfile=cityfile) bcities = mycity.limitByBounds((bxmin, bxmax, bymin, bymax)) #bcities = bcities.limitByPopulation(40000) bcities = bcities.limitByGrid(nx=4, ny=4, cities_per_grid=2) except: print('Could not read in cityfile, not plotting cities') mapcities = False cityfile = None # Load in topofile if topofile is not None: try: topomap = GDALGrid.load(topofile, resample=True, method='linear', samplegeodict=gdict) except: topomap = GMTGrid.load(topofile, resample=True, method='linear', samplegeodict=gdict) topodata = topomap.getData().copy() # mask oceans if don't have ocean shapefile if oceanfile is None: topodata = maskoceans(llons1, llats1, topodata, resolution='h', grid=1.25, inlands=True) else: print('no hillshade is possible\n') topomap = None topodata = None # Load in roads, if needed if maproads is True and roadfolder is not None: try: roadslist = [] for folder in os.listdir(roadfolder): road1 = os.path.join(roadfolder, folder) shpfiles = glob.glob(os.path.join(road1, '*.shp')) if len(shpfiles): shpfile = shpfiles[0] f = fiona.open(shpfile) shapes = list(f.items(bbox=(bxmin, bymin, bxmax, bymax))) for shapeid, shapedict in shapes: roadslist.append(shapedict) f.close() except: print('Not able to plot roads') roadslist = None val = 1 for k, layer in enumerate(plotorder): layergrid = newgrids[layer]['grid'] if 'label' in list(grids[layer].keys()): label1 = grids[layer]['label'] else: label1 = layer try: sref = grids[layer]['description']['name'] except: sref = None ax = fig.add_subplot(rowpan, colpan, val) val += 1 clat = bymin + (bymax-bymin)/2.0 clon = bxmin + (bxmax-bxmin)/2.0 # setup of basemap ('lcc' = lambert conformal conic). # use major and minor sphere radii from WGS84 ellipsoid. m = Basemap(llcrnrlon=bxmin, llcrnrlat=bymin, urcrnrlon=bxmax, urcrnrlat=bymax, rsphere=(6378137.00, 6356752.3142), resolution='l', area_thresh=1000., projection='lcc', lat_1=clat, lon_0=clon, ax=ax) x1, y1 = m(llons1, llats1) # get projection coordinates axsize = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted()) if k == 0: wid, ht = axsize.width, axsize.height if colormaps is not None and \ len(colormaps) == len(newgrids) and \ colormaps[k] is not None: palette = colormaps[k] else: # Find preferred default color map for each type of layer if 'prob' in layer.lower() or 'pga' in layer.lower() or \ 'pgv' in layer.lower() or 'cohesion' in layer.lower() or \ 'friction' in layer.lower() or 'fs' in layer.lower(): palette = cm.jet elif 'slope' in layer.lower(): palette = cm.gnuplot2 elif 'precip' in layer.lower(): palette = cm2.s3pcpn else: palette = defaultcolormap if topodata is not None: if k == 0: ptopo = m.transform_scalar( np.flipud(topodata), lons+0.5*gdict.dx, lats[::-1]-0.5*gdict.dy, np.round(300.*wid), np.round(300.*ht), returnxy=False, checkbounds=False, order=1, masked=False) #use lightsource class to make our shaded topography ls = LightSource(azdeg=135, altdeg=45) ls1 = LightSource(azdeg=120, altdeg=45) ls2 = LightSource(azdeg=225, altdeg=45) intensity1 = ls1.hillshade(ptopo, fraction=0.25, vert_exag=1.) intensity2 = ls2.hillshade(ptopo, fraction=0.25, vert_exag=1.) intensity = intensity1*0.5 + intensity2*0.5 #hillshm_im = m.transform_scalar(np.flipud(hillshm), lons, lats[::-1], np.round(300.*wid), np.round(300.*ht), returnxy=False, checkbounds=False, order=0, masked=False) #m.imshow(hillshm_im, cmap='Greys', vmin=0., vmax=3., zorder=1, interpolation='none') # vmax = 3 to soften colors to light gray #m.pcolormesh(x1, y1, hillshm, cmap='Greys', linewidth=0., rasterized=True, vmin=0., vmax=3., edgecolors='none', zorder=1); # plt.draw() # Get the data dat = layergrid.getData().copy() # mask out anything below any specified thresholds # Might need to move this up to before downsampling...might give illusion of no hazard in places where there is some that just got averaged out if maskthreshes is not None and len(maskthreshes) == len(newgrids): if maskthreshes[k] is not None: dat[dat <= maskthreshes[k]] = float('NaN') dat = np.ma.array(dat, mask=np.isnan(dat)) if logscale is not False and len(logscale) == len(newgrids): if logscale[k] is True: dat = np.log10(dat) label1 = r'$log_{10}$(' + label1 + ')' if scaletype.lower() == 'binned': # Find order of range to know how to scale order = np.round(np.log(np.nanmax(dat) - np.nanmin(dat))) if order < 1.: scal = 10**-order else: scal = 1. if lims is None or len(lims) != len(newgrids): clev = (np.linspace(np.floor(scal*np.nanmin(dat)), np.ceil(scal*np.nanmax(dat)), 10))/scal else: if lims[k] is None: clev = (np.linspace(np.floor(scal*np.nanmin(dat)), np.ceil(scal*np.nanmax(dat)), 10))/scal else: clev = lims[k] # Adjust to colorbar levels dat[dat < clev[0]] = clev[0] for j, level in enumerate(clev[:-1]): dat[(dat >= clev[j]) & (dat < clev[j+1])] = clev[j] # So colorbar saturates at top dat[dat > clev[-1]] = clev[-1] #panelhandle = m.contourf(x1, y1, datm, clev, cmap=palette, linewidth=0., alpha=ALPHA, rasterized=True) vmin = clev[0] vmax = clev[-1] else: if lims is not None and len(lims) == len(newgrids): if lims[k] is None: vmin = np.nanmin(dat) vmax = np.nanmax(dat) else: vmin = lims[k][0] vmax = lims[k][-1] else: vmin = np.nanmin(dat) vmax = np.nanmax(dat) # Mask out cells overlying oceans or block with a shapefile if available if oceanfile is None: dat = maskoceans(llons1, llats1, dat, resolution='h', grid=1.25, inlands=True) else: #patches = [] if type(ocean) is PolygonSH: ocean = [ocean] for oc in ocean: patch = getProjectedPatch(oc, m, edgecolor="#006280", facecolor=watercolor, lw=0.5, zorder=4.) #x, y = m(oc.exterior.xy[0], oc.exterior.xy[1]) #xy = zip(x, y) #patch = Polygon(xy, facecolor=watercolor, edgecolor="#006280", lw=0.5, zorder=4.) ##patches.append(Polygon(xy, facecolor=watercolor, edgecolor=watercolor, zorder=500.)) ax.add_patch(patch) ##ax.add_collection(PatchCollection(patches)) if inventory_shapefile is not None: for in1 in inventory: if 'point' in str(type(in1)): x, y = in1.xy x = x[0] y = y[0] m.scatter(x, y, c='m', s=50, latlon=True, marker='^', zorder=100001) else: x, y = m(in1.exterior.xy[0], in1.exterior.xy[1]) xy = list(zip(x, y)) patch = Polygon(xy, facecolor='none', edgecolor='k', lw=0.5, zorder=10.) #patches.append(Polygon(xy, facecolor=watercolor, edgecolor=watercolor, zorder=500.)) ax.add_patch(patch) palette.set_bad(clear_color, alpha=0.0) # Plot it up dat_im = m.transform_scalar( np.flipud(dat), lons+0.5*gdict.dx, lats[::-1]-0.5*gdict.dy, np.round(300.*wid), np.round(300.*ht), returnxy=False, checkbounds=False, order=0, masked=True) if topodata is not None: # Drape over hillshade #turn data into an RGBA image cmap = palette #adjust data so scaled between vmin and vmax and between 0 and 1 dat1 = dat_im.copy() dat1[dat1 < vmin] = vmin dat1[dat1 > vmax] = vmax dat1 = (dat1 - vmin)/(vmax-vmin) rgba_img = cmap(dat1) maskvals = np.dstack((dat1.mask, dat1.mask, dat1.mask)) rgb = np.squeeze(rgba_img[:, :, 0:3]) rgb[maskvals] = 1. draped_hsv = ls.blend_hsv(rgb, np.expand_dims(intensity, 2)) m.imshow(draped_hsv, zorder=3., interpolation='none') # This is just a dummy layer that will be deleted to make the # colorbar look right panelhandle = m.imshow(dat_im, cmap=palette, zorder=0., vmin=vmin, vmax=vmax) else: panelhandle = m.imshow(dat_im, cmap=palette, zorder=3., vmin=vmin, vmax=vmax, interpolation='none') #panelhandle = m.pcolormesh(x1, y1, dat, linewidth=0., cmap=palette, vmin=vmin, vmax=vmax, alpha=ALPHA, rasterized=True, zorder=2.); #panelhandle.set_edgecolors('face') # add colorbar cbfmt = '%1.1f' if vmax is not None and vmin is not None: if (vmax - vmin) < 1.: cbfmt = '%1.2f' elif vmax > 5.: # (vmax - vmin) > len(clev): cbfmt = '%1.0f' #norm = mpl.colors.Normalize(vmin=vmin, vmax=vmax) if scaletype.lower() == 'binned': cbar = fig.colorbar(panelhandle, spacing='proportional', ticks=clev, boundaries=clev, fraction=0.036, pad=0.04, format=cbfmt, extend='both') #cbar1 = ColorbarBase(cbar.ax, cmap=palette, norm=norm, spacing='proportional', ticks=clev, boundaries=clev, fraction=0.036, pad=0.04, format=cbfmt, extend='both', extendfrac='auto') else: cbar = fig.colorbar(panelhandle, fraction=0.036, pad=0.04, extend='both', format=cbfmt) #cbar1 = ColorbarBase(cbar.ax, cmap=palette, norm=norm, fraction=0.036, pad=0.04, extend='both', extendfrac='auto', format=cbfmt) if topodata is not None: panelhandle.remove() cbar.set_label(label1, fontsize=10) cbar.ax.tick_params(labelsize=8) parallels = m.drawparallels(getMapLines(bymin, bymax, 3), labels=[1, 0, 0, 0], linewidth=0.5, labelstyle='+/-', fontsize=9, xoffset=-0.8, color='gray', zorder=100.) m.drawmeridians(getMapLines(bxmin, bxmax, 3), labels=[0, 0, 0, 1], linewidth=0.5, labelstyle='+/-', fontsize=9, color='gray', zorder=100.) for par in parallels: try: parallels[par][1][0].set_rotation(90) except: pass #draw roads on the map, if they were provided to us if maproads is True and roadslist is not None: try: for road in roadslist: try: xy = list(road['geometry']['coordinates']) roadx, roady = list(zip(*xy)) mapx, mapy = m(roadx, roady) m.plot(mapx, mapy, roadcolor, lw=0.5, zorder=9) except: continue except Exception as e: print(('Failed to plot roads, %s' % e)) #add city names to map if mapcities is True and cityfile is not None: try: fontname = 'Arial' fontsize = 8 if k == 0: # Only need to choose cities first time and then apply to rest fcities = bcities.limitByMapCollision( m, fontname=fontname, fontsize=fontsize) ctlats, ctlons, names = fcities.getCities() cxis, cyis = m(ctlons, ctlats) for ctlat, ctlon, cxi, cyi, name in zip(ctlats, ctlons, cxis, cyis, names): m.scatter(ctlon, ctlat, c='k', latlon=True, marker='.', zorder=100000) ax.text(cxi, cyi, name, fontname=fontname, fontsize=fontsize, zorder=100000) except Exception as e: print('Failed to plot cities, %s' % e) #draw star at epicenter plt.sca(ax) if edict is not None: elat, elon = edict['lat'], edict['lon'] ex, ey = m(elon, elat) plt.plot(ex, ey, '*', markeredgecolor='k', mfc='None', mew=1.0, ms=15, zorder=10000.) m.drawmapboundary(fill_color=watercolor) m.fillcontinents(color=clear_color, lake_color=watercolor) m.drawrivers(color=watercolor) ##m.drawcoastlines() #draw country boundaries m.drawcountries(color=countrycolor, linewidth=1.0) #add map scale m.drawmapscale((bxmax+bxmin)/2., (bymin+(bymax-bymin)/9.), clon, clat, np.round((((bxmax-bxmin)*111)/5)/10.)*10, barstyle='fancy', zorder=10) # Add border autoAxis = ax.axis() rec = Rectangle((autoAxis[0]-0.7, autoAxis[2]-0.2), (autoAxis[1]-autoAxis[0])+1, (autoAxis[3]-autoAxis[2])+0.4, fill=False, lw=1, zorder=1e8) rec = ax.add_patch(rec) rec.set_clip_on(False) plt.draw() if sref is not None: label2 = '%s\nsource: %s' % (label1, sref) # '%s\n' % label1 + r'{\fontsize{10pt}{3em}\selectfont{}%s}' % sref # else: label2 = label1 plt.title(label2, axes=ax, fontsize=fontsizesub) #draw scenario watermark, if scenario if isScenario: plt.sca(ax) cx, cy = m(clon, clat) plt.text(cx, cy, 'SCENARIO', rotation=45, alpha=0.10, size=72, ha='center', va='center', color='red') #if ds: # Could add this to print "downsampled" on map # plt.text() if k == 1 and rowpan == 1: # adjust single level plot axsize = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted()) ht2 = axsize.height fig.set_figheight(ht2*1.6) else: plt.tight_layout() # Make room for suptitle - tight layout doesn't account for it plt.subplots_adjust(top=0.92) if printparam is True: try: fig = plt.gcf() dictionary = grids['model']['description']['parameters'] paramstring = 'Model parameters: ' halfway = np.ceil(len(dictionary)/2.) for i, key in enumerate(dictionary): if i == halfway and colpan == 1: paramstring += '\n' paramstring += ('%s = %s; ' % (key, dictionary[key])) print(paramstring) fig.text(0.01, 0.015, paramstring, fontsize=fontsizesmallest) plt.draw() except: print('Could not display model parameters') if edict is not None: eventid = edict['eventid'] else: eventid = '' time1 = datetime.datetime.utcnow().strftime('%d%b%Y_%H%M') outfile = os.path.join(outfolder, '%s_%s_%s.pdf' % (eventid, suptitle, time1)) pngfile = os.path.join(outfolder, '%s_%s_%s.png' % (eventid, suptitle, time1)) if savepdf is True: print('Saving map output to %s' % outfile) plt.savefig(outfile, dpi=300) if savepng is True: print('Saving map output to %s' % pngfile) plt.savefig(pngfile) if showplots is True: plt.show() else: plt.close(fig) return newgrids
def getYesPoints(pshapes,proj,dx,nmax,touch_center=True): """ Collect x/y coordinates of all points within hazard coverage polygons at desired resolution. :param pshapes: Sequence of orthographically projected shapes. :param proj: PyProj projection object used to transform input shapes :param dx: Float resolution of grid at which to sample points, must be round number :param nmax: Threshold maximum number of points in total data mesh. :param touch_center: Boolean indicating whether presence of polygon in each grid cell is enough to turn that into a yes pixel. Setting this to false presumes that the dx is relatively large, such that creating a grid at that resolution will not tax the resources of the system. :returns: - numpy 2-D array of X/Y coordinates inside hazard polygons. - number of rows of resulting mesh - number of columns of resulting mesh - numpy array of x coordinate centers of columns - numpy array of y coordinate centers of rows - 1D array of indices where yes pixels are located (use np.unravel_index to unpack to 2D array) """ mxmin = 9e10 mxmax = -9e10 mymin = 9e10 mymax = -9e10 for pshape in pshapes: pxmin,pymin,pxmax,pymax = pshape.bounds if pxmin < mxmin: mxmin = pxmin if pxmax > mxmax: mxmax = pxmax if pymin < mymin: mymin = pymin if pymax > mymax: mymax = pymax # if not touch_center: geodict = GeoDict.createDictFromBox(mxmin,mxmax,mymin,mymax,dx,dx) img = rasterizeShapes(pshapes,geodict) #now get the numpy array of x/y coordinates where covgrid == 1 idx = np.where(img == 1)[0] x,y = np.unravel_index(idx,(geodict.ny,geodict.nx)) yespoints = list(zip(x.flatten(),y.flatten())) nrows = geodict.ny ncols = geodict.nx #Create the sequence of column and row centers xvar = np.arange(geodict.xmin,geodict.xmax+geodict.dx,geodict.dx) yvar = np.arange(geodict.ymin,geodict.ymax+geodict.dy,geodict.dy) else: xvar = np.arange(mxmin,mxmax+dx,dx) yvar = np.arange(mymin,mymax+dx,dx) ncols = len(xvar) nrows = len(yvar) if nmax is not None: if ncols*nrows > nmax: aspect = ncols/nrows ncols = np.sqrt(nmax*aspect) nrows = nmax/ncols ncols = int(ncols) nrows = int(nrows) #re-calculate dx here... tdx = (mxmax-mxmin)/ncols tdy = (mymax-mymin)/nrows dx = np.max([tdx,tdy]) xvar = np.arange(mxmin,mxmax+dx,dx) yvar = np.arange(mymin,mymax+dx,dx) #Get the "yes" points to sample from #here, we're in the situation yespoints = [] idx = [] shapeidx = 0 if pshapes[0].type == 'Polygon': #loop over shapes, projecting each one, then get the sample points for pshape in pshapes: if not shapeidx % 1000: print('Searching polygon %i of %i' % (shapeidx,len(pshapes))) shapeidx += 1 pxmin,pymin,pxmax,pymax = pshape.bounds leftcol = np.where((pxmin - xvar) >= 0) rightcol = np.where((xvar - pxmax) >= 0) if len(leftcol[0]) and len(rightcol[0]): leftcol = leftcol[0].argmax() rightcol = rightcol[0].argmax() bottomrow = np.where((pymin - yvar) >= 0) toprow = np.where((yvar - pymax) >= 0) if len(bottomrow[0]) and len(toprow[0]): bottomrow = bottomrow[0].argmax() toprow = toprow[0][0] xp = np.arange(xvar[leftcol],xvar[rightcol]+dx,dx) yp = np.arange(yvar[bottomrow],yvar[toprow]+dx,dx) xmesh,ymesh = np.meshgrid(xp,yp) xy = list(zip(xmesh.flatten(),ymesh.flatten())) for point in xy: ix = np.where(xvar == point[0]) iy = np.where(yvar == point[1]) if len(ix[0]) and len(iy[0]): ix = ix[0][0] try: iy = iy[0][0] except: foo = 1 if pshape.contains(Point(point)): yespoints.append(point) idx.append(np.ravel_multi_index((iy,ix),(nrows,ncols),mode='raise',order='C')) else: yespoints = [] for pshape in pshapes: yespoints.append(pshape.coords[0]) return (np.array(yespoints),nrows,ncols,xvar,yvar,idx)