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 hazus_liq(shakefile, config, uncertfile=None, saveinputs=False, modeltype=None, displmodel=None, probtype=None, bounds=None): """ Method for computing the probability of liquefaction using the Hazus method using the Wills et al. (2015) Vs30 map of California to define the susceptibility classes and the Fan et al. global water table model. """ layers = config['hazus_liq_cal']['layers'] vs30_file = layers['vs30']['file'] wtd_file = layers['watertable']['file'] shkgdict = ShakeGrid.getFileGeoDict(shakefile) fgeodict = GMTGrid.getFileGeoDict(vs30_file)[0] #--------------------------------------------------------------------------- # Loading #--------------------------------------------------------------------------- shakemap = ShakeGrid.load(shakefile, fgeodict, resample=True, method='linear', doPadding=True) PGA = shakemap.getLayer('pga').getData() / 100 # convert to g griddict, eventdict, specdict, fields, uncertainties = getHeaderData( shakefile) mag = eventdict['magnitude'] # Correction factor for moment magnitudes other than M=7.5 k_m = 0.0027 * mag**3 - 0.0267 * mag**2 - 0.2055 * mag + 2.9188 #--------------------------------------------------------------------------- # Susceptibility from Vs30 #--------------------------------------------------------------------------- vs30_grid = GMTGrid.load(vs30_file) vs30 = vs30_grid.getData() p_ml = np.zeros_like(vs30) a = np.zeros_like(vs30) b = np.zeros_like(vs30) for k, v in config['hazus_liq_cal']['parameters'].items(): ind = np.where(vs30 == float(v[0])) if v[1] == "VH": p_ml[ind] = 0.25 a[ind] = 9.09 b[ind] = -0.82 if v[1] == "H": p_ml[ind] = 0.2 a[ind] = 7.67 b[ind] = -0.92 if v[1] == "M": p_ml[ind] = 0.1 a[ind] = 6.67 b[ind] = -1.0 if v[1] == "L": p_ml[ind] = 0.05 a[ind] = 5.57 b[ind] = -1.18 if v[1] == "VL": p_ml[ind] = 0.02 a[ind] = 4.16 b[ind] = -1.08 # Conditional liquefaction probability for a given susceptibility category # at a specified PGA p_liq_pga = a * PGA + b p_liq_pga = p_liq_pga.clip(min=0, max=1) #--------------------------------------------------------------------------- # Water table #--------------------------------------------------------------------------- wtd_grid = GMTGrid.load(wtd_file, fgeodict, resample=True, method=layers['watertable']['interpolation'], doPadding=True) tmp = wtd_grid._data tmp = np.nan_to_num(tmp) # Convert to ft wt_ft = tmp * 3.28084 # Correction factor for groundwater depths other than five feet k_w = 0.022 * wt_ft + 0.93 #--------------------------------------------------------------------------- # Combine to get conditional liquefaction probability #--------------------------------------------------------------------------- p_liq_sc = p_liq_pga * p_ml / k_m / k_w #--------------------------------------------------------------------------- # Turn output and inputs into into grids and put in maplayers dictionary #--------------------------------------------------------------------------- maplayers = collections.OrderedDict() temp = shakemap.getShakeDict() shakedetail = '%s_ver%s' % (temp['shakemap_id'], temp['shakemap_version']) modelsref = config['hazus_liq_cal']['shortref'] modellref = config['hazus_liq_cal']['longref'] modeltype = 'Hazus/Wills' maplayers['model'] = { 'grid': GDALGrid(p_liq_sc, fgeodict), 'label': 'Probability', 'type': 'output', 'description': { 'name': modelsref, 'longref': modellref, 'units': 'coverage', 'shakemap': shakedetail, 'parameters': { 'modeltype': modeltype } } } if saveinputs is True: maplayers['pga'] = { 'grid': GDALGrid(PGA, fgeodict), 'label': 'PGA (g)', 'type': 'input', 'description': { 'units': 'g', 'shakemap': shakedetail } } maplayers['vs30'] = { 'grid': GDALGrid(vs30, fgeodict), 'label': 'Vs30 (m/s)', 'type': 'input', 'description': { 'units': 'm/s' } } maplayers['wtd'] = { 'grid': GDALGrid(wtd_grid._data, fgeodict), 'label': 'wtd (m)', 'type': 'input', 'description': { 'units': 'm' } } return maplayers
def statsCoverage(modelgrid, inventorygrid, bins=None, showplots=True, saveplots=False, filepath=None): """TO DO - FIND MORE TESTS THAT ARE EASY TO COMPARE WITH EACH OTHER Compute stats and make comparison plots specific to models that output areal coverage like Godt et al 2008 :param modelgrid: Grid2D object of model results :param inventorygrid: Grid2D object of areal coverage of inventory computed on same grid as modelgrid using, for example, computeCoverage :param bins: bin edges to use for various binning and threshold statistical calculations. if None bins = np.linspace(0, np.max((inv.max(), model.max())), 11) :param showplots: if True, will display the plots :param saveplots: if True, will save the plots :param filepath: Filepath for saved plots, if None, will save in current directory. Files are named with test name and time stamp :returns: * results: dictionary of results of tests. {'Compare coverage': dictionary, 'RMS': float, 'RMS_nonzero': float, 'Percent in bin': dictionary, 'Direct Comparison': dictionary]} * invminusmod: Grid2D object of difference between inventory and model (inventory - model) """ inv = inventorygrid.getData() model = modelgrid.getData() invminusmod = GDALGrid(inv - model, inventorygrid.getGeoDict()) plt.ioff() # Make statistical comparisons results = {} if bins is None: bins = np.linspace(0, np.max((inv.max(), model.max())), 11) fig = plt.figure() ax = fig.add_subplot(111) ax.hist((model, inv), bins=bins) ax.set_yscale('log') ax.legend(('Model', 'Inventory')) ax.set_ylabel('Total # of cells') ax.set_xlabel('Predicted coverage bin') results['Direct Comparison'] = { 'bins': bins, 'model': model, 'inventory': inv } # Statistical comparison perc = [] areatot = [] for i, bin in enumerate(bins[:-1]): idx = (model > bin) & (model <= bins[i + 1]) areain = inv[idx] totalin = sum((areain > bin) & (areain <= bins[i + 1])) perc.append(float(totalin) / len(idx) * 100) areatot.append(np.mean(areain)) areatot = np.nan_to_num(areatot) binvec = [] for i in range(len(bins[:-1])): binvec.append(bins[i] + (bins[i + 1] - bins[i]) / 2) fig1 = plt.figure() ax1 = fig1.add_subplot(111) ax1.plot(binvec, perc, 'o-') ax1.set_ylabel('% in right bin') ax1.set_xlabel('Predicted coverage bin') ax1.set_title('Actual coverage in predicted bin') results['Percent in bin'] = {'bincenters': binvec, 'perc': perc} fig2 = plt.figure() ax2 = fig2.add_subplot(111) ax2.plot(binvec, areatot, 'o-') ax2.plot([0., 1.], [0., 1.], '--', color='gray') ax2.set_ylabel('Actual coverage') ax2.set_xlabel('Predicted coverage') ax2.set_title('Actual vs. Predicted coverage') results['Compare coverage'] = {'bincenters': binvec, 'areatot': areatot} if showplots is True: plt.show() if saveplots is True: if filepath is None: filepath = os.getcwd() import datetime time1 = datetime.datetime.utcnow().strftime('%d%b%Y_%H%M') fig.savefig(os.path.join(filepath, 'Direct_compare_%s.pdf' % (time1, ))) fig1.savefig( os.path.join(filepath, 'Percent_in_bin_%s.pdf' % (time1, ))) fig2.savefig( os.path.join(filepath, 'Compare_coverage_%s.pdf' % (time1, ))) # RMS idx = np.union1d(model.nonzero()[0], inv.nonzero()[0]) results['RMS'] = np.sqrt((model - inv)**2).mean() print(('RMS: %0.3f' % results['RMS'])) results['RMS_nonzero'] = np.sqrt((model[idx] - inv[idx])**2).mean() print(('RMS_nonzero: %0.3f' % results['RMS_nonzero'])) return invminusmod, results
def godt2008(shakefile, config, uncertfile=None, saveinputs=False, displmodel=None, bounds=None, slopediv=100., codiv=10., numstd=None, trimfile=None): """ This function runs the Godt and others (2008) global method for a given ShakeMap. The Factor of Safety is calculated using infinite slope analysis assumuing dry conditions. The method uses threshold newmark displacement and estimates areal coverage by doing the calculations for each slope quantile. Args: shakefile (str): Path to shakemap xml file. config (ConfigObj): ConfigObj of config file containing inputs required for running the model uncertfile (str): Path to shakemap uncertainty xml file (optional). saveinputs (bool): Whether or not to return the model input layers, False (default) returns only the model output (one layer). displmodel (str): Newmark displacement regression model to use * ``'J_PGA'`` (default) -- PGA-based model, equation 6 from Jibson (2007). * ``'J_PGA_M'`` -- PGA and M-based model, equation 7 from Jibson (2007). * ``'RS_PGA_M'`` -- PGA and M-based model from from Rathje and Saygili (2009). * ``'RS_PGA_PGV'`` -- PGA and PGV-based model, equation 6 from Saygili and Rathje (2008). bounds (dict): Optional dictionary with keys 'xmin', 'xmax', 'ymin', 'ymax' that defines a subset of the shakemap area to compute. slopediv (float): Divide slope by this number to get slope in degrees (Verdin datasets need to be divided by 100). codiv (float): Divide cohesion input layer by this number (For Godt method, need to divide by 10 because that is how it was calibrated). numstd (float): Number of (+/-) standard deviations to use if uncertainty is computed (uncertfile must be supplied). trimfile (str): shapefile of earth's land masses to trim offshore areas of model Returns: dict: Dictionary containing output and input layers (if saveinputs=True): .. code-block:: python { 'grid': mapio grid2D object, 'label': 'label for colorbar and top line of subtitle', 'type': 'output or input to model', 'description': {'name': 'short reference of model', 'longref': 'full model reference', 'units': 'units of output', 'shakemap': 'information about shakemap used', 'event_id': 'shakemap event id', 'parameters': 'dictionary of model parameters used' } } Raises: NameError: when unable to parse the config correctly (probably a formatting issue in the configfile) or when unable to find the shakefile (Shakemap filepath) -- these cause program to end. """ # TODO: # - Add 'all' -- averages Dn from all four equations, add term to # convert PGA and PGV to Ia and use other equations, add Ambraseys and # Menu (1988) option. # Empty refs slopesref = 'unknown' slopelref = 'unknown' cohesionlref = 'unknown' cohesionsref = 'unknown' frictionsref = 'unknown' frictionlref = 'unknown' modellref = 'unknown' modelsref = 'unknown' # See if trimfile exists if trimfile is not None: if not os.path.exists(trimfile): print('trimfile defined does not exist: %s\n' 'Ocean will not be trimmed' % trimfile) trimfile = None if os.path.splitext(trimfile)[1] != '.shp': print('trimfile must be a shapefile, ocean will not be trimmed') trimfile = None # Parse config try: # May want to add error handling so if refs aren't given, just # includes unknown slopefilepath = config['godt_2008']['layers']['slope']['filepath'] slopeunits = config['godt_2008']['layers']['slope']['units'] cohesionfile = config['godt_2008']['layers']['cohesion']['file'] cohesionunits = config['godt_2008']['layers']['cohesion']['units'] frictionfile = config['godt_2008']['layers']['friction']['file'] frictionunits = config['godt_2008']['layers']['friction']['units'] thick = float(config['godt_2008']['parameters']['thick']) uwt = float(config['godt_2008']['parameters']['uwt']) nodata_cohesion = \ float(config['godt_2008']['parameters']['nodata_cohesion']) nodata_friction = \ float(config['godt_2008']['parameters']['nodata_friction']) dnthresh = float(config['godt_2008']['parameters']['dnthresh']) fsthresh = float(config['godt_2008']['parameters']['fsthresh']) acthresh = float(config['godt_2008']['parameters']['acthresh']) try: slopemin = float(config['godt_2008']['parameters']['slopemin']) except: slopemin = 0.01 print('No slopemin found in config file, using 0.01 deg ' 'for slope minimum') except Exception as e: raise NameError('Could not parse configfile, %s' % e) if displmodel is None: try: displmodel = config['godt_2008']['parameters']['displmodel'] except: print('No regression model specified, using default of J_PGA_M') displmodel = 'J_PGA_M' # TO DO: ADD ERROR CATCHING ON UNITS, MAKE SURE THEY ARE WHAT THEY SHOULD # BE FOR THIS MODEL try: # Try to fetch source information from config modelsref = config['godt_2008']['shortref'] modellref = config['godt_2008']['longref'] slopesref = config['godt_2008']['layers']['slope']['shortref'] slopelref = config['godt_2008']['layers']['slope']['longref'] cohesionsref = config['godt_2008']['layers']['cohesion']['shortref'] cohesionlref = config['godt_2008']['layers']['cohesion']['longref'] frictionsref = config['godt_2008']['layers']['friction']['shortref'] frictionlref = config['godt_2008']['layers']['friction']['longref'] except: print('Was not able to retrieve all references from config file. ' 'Continuing') # Figure out how/if need to cut anything geodict = ShakeGrid.getFileGeoDict(shakefile) # , adjust='res') if bounds is not None: # Make sure bounds are within ShakeMap Grid if geodict.xmin < geodict.xmax: # only if signs are not opposite if (geodict.xmin > bounds['xmin'] or geodict.xmax < bounds['xmax'] or geodict.ymin > bounds['ymin'] or geodict.ymax < bounds['ymax']): print('Specified bounds are outside shakemap area, using ' 'ShakeMap bounds instead.') bounds = None if bounds is not None: tempgdict = GeoDict.createDictFromBox(bounds['xmin'], bounds['xmax'], bounds['ymin'], bounds['ymax'], geodict.dx, geodict.dy, inside=False) # If Shakemap geodict crosses 180/-180 line, fix geodict so things don't break if geodict.xmin > geodict.xmax: if tempgdict.xmin < 0: geodict._xmin -= 360. else: geodict._xmax += 360. geodict = geodict.getBoundsWithin(tempgdict) basegeodict, firstcol = GDALGrid.getFileGeoDict( os.path.join(slopefilepath, 'slope_min.bil')) if basegeodict == geodict: sampledict = geodict else: sampledict = basegeodict.getBoundsWithin(geodict) # Do we need to subdivide baselayer? if 'divfactor' in config['godt_2008'].keys(): divfactor = float(config['godt_2008']['divfactor']) if divfactor != 1.: # adjust sampledict so everything will be resampled (cut one cell # of each edge so will be inside bounds) newxmin = sampledict.xmin - sampledict.dx/2. + \ sampledict.dx/(2.*divfactor) + sampledict.dx newymin = sampledict.ymin - sampledict.dy/2. + \ sampledict.dy/(2.*divfactor) + sampledict.dy newxmax = sampledict.xmax + sampledict.dx/2. - \ sampledict.dx/(2.*divfactor) - sampledict.dx newymax = sampledict.ymax + sampledict.dy/2. - \ sampledict.dy/(2.*divfactor) - sampledict.dy newdx = sampledict.dx / divfactor newdy = sampledict.dy / divfactor sampledict = GeoDict.createDictFromBox(newxmin, newxmax, newymin, newymax, newdx, newdy, inside=True) tmpdir = tempfile.mkdtemp() # Load in ShakeMap and get new geodictionary temp = ShakeGrid.load(shakefile) # , adjust='res') junkfile = os.path.join(tmpdir, 'temp.bil') GDALGrid.copyFromGrid(temp.getLayer('pga')).save(junkfile) pga = quickcut(junkfile, sampledict, precise=True, method='bilinear') os.remove(junkfile) GDALGrid.copyFromGrid(temp.getLayer('pgv')).save(junkfile) pgv = quickcut(junkfile, sampledict, precise=True, method='bilinear') os.remove(junkfile) # Update geodictionary sampledict = pga.getGeoDict() t2 = temp.getEventDict() M = t2['magnitude'] event_id = t2['event_id'] shakedict = temp.getShakeDict() del (temp) # read in uncertainty if present if uncertfile is not None: try: temp = ShakeGrid.load(uncertfile) # , adjust='res') GDALGrid.copyFromGrid(temp.getLayer('stdpga')).save(junkfile) uncertpga = quickcut(junkfile, sampledict, precise=True, method='bilinear', override=True) os.remove(junkfile) GDALGrid.copyFromGrid(temp.getLayer('stdpgv')).save(junkfile) uncertpgv = quickcut(junkfile, sampledict, precise=True, method='bilinear', override=True) os.remove(junkfile) except: print('Could not read uncertainty file, ignoring uncertainties') uncertfile = None if numstd is None: numstd = 1. # Read in all the slope files, divide all by 100 to get to slope in # degrees (because input files are multiplied by 100.) slopes = [] quantiles = [ 'slope_min.bil', 'slope10.bil', 'slope30.bil', 'slope50.bil', 'slope70.bil', 'slope90.bil', 'slope_max.bil' ] for quant in quantiles: tmpslp = quickcut(os.path.join(slopefilepath, quant), sampledict) tgd = tmpslp.getGeoDict() if tgd != sampledict: raise Exception('Input layers are not aligned to same geodict') else: slopes.append(tmpslp.getData() / slopediv) slopestack = np.dstack(slopes) # Change any zero slopes to a very small number to avoid dividing by # zero later slopestack[slopestack == 0] = 1e-8 # Read in the cohesion and friction files and duplicate layers so they # are same shape as slope structure tempco = quickcut(cohesionfile, sampledict, method='near') tempco = tempco.getData()[:, :, np.newaxis] / codiv cohesion = np.repeat(tempco, 7, axis=2) cohesion[cohesion == -999.9] = nodata_cohesion cohesion = np.nan_to_num(cohesion) cohesion[cohesion == 0] = nodata_cohesion tempfric = quickcut(frictionfile, sampledict, method='near') tempfric = tempfric.getData().astype(float)[:, :, np.newaxis] friction = np.repeat(tempfric, 7, axis=2) friction[friction == -9999] = nodata_friction friction = np.nan_to_num(friction) friction[friction == 0] = nodata_friction # Do the calculations using Jibson (2007) PGA only model for Dn FS = (cohesion / (uwt * thick * np.sin(slopestack * (np.pi / 180.))) + np.tan(friction * (np.pi / 180.)) / np.tan(slopestack * (np.pi / 180.))) FS[FS < fsthresh] = fsthresh # Compute critical acceleration, in g # This gives ac in g, equations that multiply by g give ac in m/s2 Ac = (FS - 1) * np.sin(slopestack * (np.pi / 180.)).astype(float) Ac[Ac < acthresh] = acthresh # Get PGA in g (PGA is %g in ShakeMap, convert to g) PGA = np.repeat(pga.getData()[:, :, np.newaxis] / 100., 7, axis=2).astype(float) if 'PGV' in displmodel: # Load in PGV also, in cm/sec PGV = np.repeat(pgv.getData()[:, :, np.newaxis], 7, axis=2).astype(float) else: PGV = None if uncertfile is not None: stdpga = np.repeat(uncertpga.getData()[:, :, np.newaxis], 7, axis=2).astype(float) stdpgv = np.repeat(uncertpgv.getData()[:, :, np.newaxis], 7, axis=2).astype(float) # estimate PGA +- 1std PGAmin = np.exp(np.log(PGA * 100) - numstd * stdpga) / 100 PGAmax = np.exp(np.log(PGA * 100) + numstd * stdpga) / 100 if 'PGV' in displmodel: PGVmin = np.exp(np.log(PGV) - numstd * stdpgv) PGVmax = np.exp(np.log(PGV) + numstd * stdpgv) else: PGVmin = None PGVmax = None # Ignore errors so still runs when Ac > PGA, just leaves nan instead # of crashing. np.seterr(invalid='ignore') Dn, logDnstd, logtype = NMdisp(Ac, PGA, model=displmodel, M=M, PGV=PGV) if uncertfile is not None: Dnmin, logDnstdmin, logtype = NMdisp(Ac, PGAmin, model=displmodel, M=M, PGV=PGVmin) Dnmax, logDnstdmax, logtype = NMdisp(Ac, PGAmax, model=displmodel, M=M, PGV=PGVmax) PROB = Dn.copy() PROB[PROB < dnthresh] = 0. PROB[PROB >= dnthresh] = 1. PROB = np.sum(PROB, axis=2) if uncertfile is not None: PROBmin = Dnmin.copy() PROBmin[PROBmin <= dnthresh] = 0. PROBmin[PROBmin > dnthresh] = 1. PROBmin = np.sum(PROBmin, axis=2) PROBmax = Dnmax.copy() PROBmax[PROBmax <= dnthresh] = 0. PROBmax[PROBmax > dnthresh] = 1. PROBmax = np.sum(PROBmax, axis=2) PROB[PROB == 1.] = 0.01 PROB[PROB == 2.] = 0.10 PROB[PROB == 3.] = 0.30 PROB[PROB == 4.] = 0.50 PROB[PROB == 5.] = 0.70 PROB[PROB == 6.] = 0.90 PROB[PROB == 7.] = 0.99 if uncertfile is not None: PROBmin[PROBmin == 1.] = 0.01 PROBmin[PROBmin == 2.] = 0.10 PROBmin[PROBmin == 3.] = 0.30 PROBmin[PROBmin == 4.] = 0.50 PROBmin[PROBmin == 5.] = 0.70 PROBmin[PROBmin == 6.] = 0.90 PROBmin[PROBmin == 7.] = 0.99 PROBmax[PROBmax == 1.] = 0.01 PROBmax[PROBmax == 2.] = 0.10 PROBmax[PROBmax == 3.] = 0.30 PROBmax[PROBmax == 4.] = 0.50 PROBmax[PROBmax == 5.] = 0.70 PROBmax[PROBmax == 6.] = 0.90 PROBmax[PROBmax == 7.] = 0.99 if slopemin is not None: PROB[slopestack[:, :, 6] <= slopemin] = 0. # uncert too if uncertfile is not None: PROBmin[slopestack[:, :, 6] <= slopemin] = 0. PROBmax[slopestack[:, :, 6] <= slopemin] = 0. # Turn output and inputs into into grids and put in mapLayers dictionary maplayers = collections.OrderedDict() shakedetail = '%s_ver%s' % (shakedict['shakemap_id'], shakedict['shakemap_version']) description = { 'name': modelsref, 'longref': modellref, 'units': 'Proportion of Area Affected', 'shakemap': shakedetail, 'event_id': event_id, 'parameters': { 'displmodel': displmodel, 'thickness_m': thick, 'unitwt_kNm3': uwt, 'dnthresh_cm': dnthresh, 'acthresh_g': acthresh, 'fsthresh': fsthresh, 'modeltype': 'Landslide' } } PROBgrid = GDALGrid(PROB, sampledict) if trimfile is not None: PROBgrid = trim_ocean(PROBgrid, trimfile) maplayers['model'] = { 'grid': PROBgrid, 'label': 'Landslide - Proportion of Area Affected', 'type': 'output', 'description': description } if uncertfile is not None: PROBmingrid = GDALGrid(PROBmin, sampledict) PROBmaxgrid = GDALGrid(PROBmax, sampledict) if trimfile is not None: PROBmingrid = trim_ocean(PROBmingrid, trimfile) PROBmaxgrid = trim_ocean(PROBmaxgrid, trimfile) maplayers['modelmin'] = { 'grid': PROBmingrid, 'label': 'Landslide Probability-%1.2fstd' % numstd, 'type': 'output', 'description': description } maplayers['modelmax'] = { 'grid': PROBmaxgrid, 'label': 'Landslide Probability+%1.2fstd' % numstd, 'type': 'output', 'description': description } if saveinputs is True: maplayers['pga'] = { 'grid': GDALGrid(PGA[:, :, 0], sampledict), 'label': 'PGA (g)', 'type': 'input', 'description': { 'units': 'g', 'shakemap': shakedetail } } if 'PGV' in displmodel: maplayers['pgv'] = { 'grid': GDALGrid(PGV[:, :, 0], sampledict), 'label': 'PGV (cm/s)', 'type': 'input', 'description': { 'units': 'cm/s', 'shakemap': shakedetail } } maplayers['minFS'] = { 'grid': GDALGrid(np.min(FS, axis=2), sampledict), 'label': 'Min Factor of Safety', 'type': 'input', 'description': { 'units': 'unitless' } } maplayers['max slope'] = { 'grid': GDALGrid(slopestack[:, :, -1], sampledict), 'label': r'Maximum slope ($^\circ$)', 'type': 'input', 'description': { 'units': 'degrees', 'name': slopesref, 'longref': slopelref } } maplayers['cohesion'] = { 'grid': GDALGrid(cohesion[:, :, 0], sampledict), 'label': 'Cohesion (kPa)', 'type': 'input', 'description': { 'units': 'kPa (adjusted)', 'name': cohesionsref, 'longref': cohesionlref } } maplayers['friction angle'] = { 'grid': GDALGrid(friction[:, :, 0], sampledict), 'label': r'Friction angle ($^\circ$)', 'type': 'input', 'description': { 'units': 'degrees', 'name': frictionsref, 'longref': frictionlref } } if uncertfile is not None: maplayers['pgamin'] = { 'grid': GDALGrid(PGAmin[:, :, 0], sampledict), 'label': 'PGA - %1.2fstd (g)' % numstd, 'type': 'input', 'description': { 'units': 'g', 'shakemap': shakedetail } } maplayers['pgamax'] = { 'grid': GDALGrid(PGAmax[:, :, 0], sampledict), 'label': 'PGA + %1.2fstd (g)' % numstd, 'type': 'input', 'description': { 'units': 'g', 'shakemap': shakedetail } } if 'PGV' in displmodel: if uncertfile is not None: maplayers['pgvmin'] = { 'grid': GDALGrid(PGVmin[:, :, 0], sampledict), 'label': 'PGV - %1.2fstd (cm/s)' % numstd, 'type': 'input', 'description': { 'units': 'cm/s', 'shakemap': shakedetail } } maplayers['pgvmax'] = { 'grid': GDALGrid(PGVmax[:, :, 0], sampledict), 'label': 'PGV + %1.2fstd (cm/s)' % numstd, 'type': 'input', 'description': { 'units': 'cm/s', 'shakemap': shakedetail } } shutil.rmtree(tmpdir) return maplayers
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 makeTestData(): # make test layers and config files (model, and mapping) Xmod = ['friction', 'slope', 'vs30', 'cti1', 'precip'] terms = ['friction', 'slope/100.', 'log(vs30)', 'cti1', 'precipMONTH'] coefficients = [0.3, 2.1, -0.5, 0.01, 1.0] Xhaz = ['susceptibility'] Xgod = ['cohesion', 'friction', 'slope'] Xcla = ['cohesion', 'friction', 'slope', 'watertable'] configModel = OrderedDict() configHazus = OrderedDict() configGodt = OrderedDict() configClassic = OrderedDict() # Work on model configs #LOGISTIC configModel.setdefault('test_model', {}) configModel['test_model'].setdefault('shortref', 'Name et al. year') configModel['test_model'].setdefault('longref', 'full reference') configModel['test_model'].setdefault('layers', {}) configModel['test_model'].setdefault('interpolations', {}) configModel['test_model'].setdefault('terms', {}) configModel['test_model'].setdefault('coefficients', {})['b0'] = '3.5' configModel['test_model'].setdefault( 'display_options', { 'lims': { 'model': 'np.linspace(0., 0.4, 10)' }, 'colors': { 'default': 'cm.inferno', 'alpha': '0.7', 'model': 'cm.jet' }, 'logscale': { 'model': 'False' }, 'maskthresholds': { 'model': '0.001' } }) configModel['test_model']['gfeype'] = 'landslide' configModel['test_model']['baselayer'] = 'slope' configModel['test_model']['slopemin'] = 5. configModel['test_model']['slopemax'] = 90. configModel['test_model']['display_options'].setdefault( 'pga', { 'lims': 'None', 'colors': 'cm.jet', 'logscale': 'True' }) configModel['test_model']['display_options'].setdefault( 'pgv', { 'lims': 'None', 'colors': 'cm.jet', 'logscale': 'False' }) # HAZUS configHazus.setdefault('hazus', {}) configHazus['hazus'].setdefault('shortref', 'Name et al. year') configHazus['hazus'].setdefault('longref', 'full reference') configHazus['hazus']['gfeype'] = 'landslide' configHazus['hazus'].setdefault('layers', {}) configHazus['hazus'].setdefault('parameters', {'dnthresh': 5.}) configHazus['hazus'].setdefault( 'display_options', { 'lims': { 'model': 'np.linspace(0., 0.4, 10)' }, 'colors': { 'default': 'cm.inferno', 'alpha': '0.7', 'model': 'cm.jet' }, 'logscale': { 'model': 'False' }, 'maskthresholds': { 'model': '0.001' } }) configHazus['hazus']['display_options'].setdefault('susceptibility', { 'lims': 'None', 'colors': 'cm.jet', 'logscale': 'True' }) # GODT configGodt.setdefault('godt_2008', {}) configGodt['godt_2008'].setdefault('shortref', 'Name et al. year') configGodt['godt_2008'].setdefault('longref', 'full reference') configGodt['godt_2008']['gfeype'] = 'landslide' configGodt['godt_2008'].setdefault('layers', {}) configGodt['godt_2008'].setdefault( 'parameters', { 'thick': '2.4', 'uwt': '15.7', 'nodata_cohesion': '1.0', 'nodata_friction': '26.', 'dnthresh': '5.', 'fsthresh': '1.01', 'acthresh': '0.05' }) configGodt['godt_2008'].setdefault( 'display_options', { 'lims': { 'model': 'np.linspace(0., 0.4, 10)' }, 'colors': { 'default': 'cm.inferno', 'alpha': '0.7', 'model': 'cm.jet' }, 'logscale': { 'model': 'False' }, 'maskthresholds': { 'model': '0.001' } }) configGodt['godt_2008']['display_options'].setdefault( 'pga', { 'lims': 'None', 'colors': 'cm.jet', 'logscale': 'True' }) # NEWMARK configClassic.setdefault('classic_newmark', {}) configClassic['classic_newmark'].setdefault('shortref', 'Name et al. year') configClassic['classic_newmark'].setdefault('longref', 'full reference') configClassic['classic_newmark']['gfeype'] = 'landslide' configClassic['classic_newmark'].setdefault('layers', {}) configClassic['classic_newmark'].setdefault( 'parameters', { 'thick': '2.4', 'uwt': '15.7', 'nodata_cohesion': '1.0', 'nodata_friction': '26.', 'dnthresh': '5.', 'fsthresh': '1.01', 'acthresh': '0.05', 'slopethresh': '5.', 'm': '0.5' }) configClassic['classic_newmark'].setdefault( 'display_options', { 'lims': { 'model': 'np.linspace(0., 0.4, 10)' }, 'colors': { 'default': 'cm.inferno', 'alpha': '0.7', 'model': 'cm.jet' }, 'logscale': { 'model': 'False' }, 'maskthresholds': { 'model': '0.001' } }) configClassic['classic_newmark']['display_options'].setdefault( 'pga', { 'lims': 'None', 'colors': 'cm.jet', 'logscale': 'True' }) for k, items in enumerate(Xmod): coef = 'b%1d' % (k + 1) # make a GDALGrid object testgrid = GDALGrid(eval(items), geodict) # Save the file if items == 'precip': try: os.mkdir('test_precip') except: pass filename = 'test_precip/prec_Jan.bil' # Only make January for testing else: filename = 'test_%s.bil' % (items) testgrid.save(filename, format='EHdr') # add to test config file configModel['test_model']['layers'].update({ items: { 'file': filename.split('/')[0], 'units': units[items], 'longref': 'longref', 'shortref': 'shortref' } }) configModel['test_model']['interpolations'].update({items: 'nearest'}) configModel['test_model']['terms'].update({coef: terms[k]}) configModel['test_model']['coefficients'].update( {coef: coefficients[k]}) configModel['test_model']['display_options']['lims'].update( {items: 'None'}) configModel['test_model']['display_options']['colors'].update( {items: 'None'}) configModel['test_model']['display_options']['logscale'].update( {items: 'False'}) configModel['test_model']['display_options']['maskthresholds'].update( {items: 'None'}) for k, items in enumerate(Xhaz): # Save the file if not already saved filename = 'test_%s.bil' % (items) if items == 'susceptibility': testgrid = GDALGrid(eval(items), susgeodict) testgrid.save(filename, format='EHdr') # add to test config file configHazus['hazus']['layers'].update({ items: { 'file': filename, 'units': units[items], 'longref': 'longref', 'shortref': 'shortref' } }) configHazus['hazus']['display_options']['lims'].update({items: 'None'}) configHazus['hazus']['display_options']['colors'].update( {items: 'None'}) configHazus['hazus']['display_options']['logscale'].update( {items: 'False'}) configHazus['hazus']['display_options']['maskthresholds'].update( {items: 'None'}) for k, items in enumerate(Xgod): # make a GDALGrid object if items == 'slope': testgrid = GDALGrid(eval('slopeGodt'), geodict) else: testgrid = GDALGrid(eval(items), geodict) # Save the file filename = 'test_%s.bil' % (items) word = 'file' if items == 'slope': word = 'filepath' try: os.mkdir('test_slope_quantiles_godt') except: pass for j, slp in enumerate(slopequants): filename = 'test_slope_quantiles_godt/slope%s.bil' % ( slopequantnames[j]) # Only make January for testing temp = GDALGrid(eval('slopeGodt') * slopequants[j], geodict) temp.save(filename, format='EHdr') filename = 'test_slope_quantiles_godt' elif items == 'cohesion': testgrid.save(filename, format='EHdr') # add to test config file configGodt['godt_2008']['layers'].update({ items: { word: filename, 'units': units[items], 'longref': 'longref', 'shortref': 'shortref' } }) configGodt['godt_2008']['display_options']['lims'].update( {items: 'None'}) configGodt['godt_2008']['display_options']['colors'].update( {items: 'None'}) configGodt['godt_2008']['display_options']['logscale'].update( {items: 'False'}) configGodt['godt_2008']['display_options']['maskthresholds'].update( {items: 'None'}) for k, items in enumerate(Xcla): # make a GDALGrid object testgrid = GDALGrid(eval(items), geodict) # Save the file filename = 'test_%s.bil' % (items) if items == 'watertable': testgrid.save(filename, format='EHdr') # add to test config file configClassic['classic_newmark']['layers'].update({ items: { 'file': filename, 'units': units[items], 'longref': 'longref', 'shortref': 'shortref' } }) configClassic['classic_newmark']['display_options']['lims'].update( {items: 'None'}) configClassic['classic_newmark']['display_options']['colors'].update( {items: 'None'}) configClassic['classic_newmark']['display_options']['logscale'].update( {items: 'False'}) configClassic['classic_newmark']['display_options'][ 'maskthresholds'].update({items: 'None'}) # Make test_shakegrid and test_uncert eventDict = OrderedDict([ ('event_id', 'test'), ('lon', 0.5), ('lat', 0.5), ('event_timestamp', datetime(2000, 1, 5, 0, 30, 55)), ('event_network', 'na'), ('magnitude', 6.0), ('event_description', 'Test event'), ('depth', 5.0) ]) shakeDict = OrderedDict([('process_timestamp', datetime(2000, 1, 6, 20, 38, 19)), ('event_id', 'test'), ('shakemap_version', 2), ('code_version', '1 billion'), ('shakemap_event_type', 'TEST'), ('map_status', 'TEST'), ('shakemap_id', 'test'), ('shakemap_originator', 'na')]) uncertaintyDict = {} layers1 = {'pga': pga, 'pgv': pgv} shakegrid = ShakeGrid(layers1, geodict, eventDict, shakeDict, uncertaintyDict) shakegrid.save('test_shakegrid.xml') layers2 = {'stdpga': stdpga, 'stdpgv': stdpgv} uncertgrid = ShakeGrid(layers2, geodict, eventDict, shakeDict, uncertaintyDict) uncertgrid.save('test_uncert.xml') layers3 = {'pga': pga1, 'pgv': pgv1} shakegrid = ShakeGrid(layers3, geodict1, eventDict, shakeDict, uncertaintyDict) shakegrid.save('test_shakegrid_bounds.xml') C = ConfigObj(configModel) C.filename = 'testconfig_logimodel.ini' C.write() C = ConfigObj(configHazus) C.filename = 'testconfig_hazus.ini' C.write() C = ConfigObj(configClassic) C.filename = 'testconfig_classic.ini' C.write() C = ConfigObj(configGodt) C.filename = 'testconfig_godt.ini' C.write() configMap = OrderedDict({ 'dem': { 'file': 'None' }, 'roads': { 'file': 'None' }, 'cities': { 'file': 'None' }, 'ocean': { 'file': 'None' }, 'colors': { 'roadcolor': '808080', 'countrycolor': '474747', 'watercolor': 'B8EEFF' } }) C = ConfigObj(configMap) C.filename = 'testconfig_map.ini' C.write()
def holzer_liq(shakefile, config, uncertfile=None, saveinputs=False, modeltype=None, displmodel=None, probtype=None, bounds=None): """ Method for computing the probability of liquefaction using the Holzer method using the Wills et al. (2015) Vs30 map of California to define the susceptibility classes and the Fan et al. global water table model. """ layers = config['holzer_liq_cal']['layers'] vs30_file = layers['vs30']['file'] wtd_file = layers['watertable']['file'] shkgdict = ShakeGrid.getFileGeoDict(shakefile) fgeodict = GMTGrid.getFileGeoDict(vs30_file)[0] #--------------------------------------------------------------------------- # Loading info #--------------------------------------------------------------------------- shakemap = ShakeGrid.load(shakefile, fgeodict, resample=True, method='linear', doPadding=True) PGA = shakemap.getLayer('pga').getData() / 100 # convert to g griddict, eventdict, specdict, fields, uncertainties = getHeaderData( shakefile) mag = eventdict['magnitude'] #--------------------------------------------------------------------------- # Logistic funciton parameters from Vs30 #--------------------------------------------------------------------------- vs30_grid = GMTGrid.load(vs30_file) vs30 = vs30_grid.getData() a0 = np.zeros_like(vs30) b0 = np.zeros_like(vs30) c0 = np.zeros_like(vs30) a1 = np.zeros_like(vs30) b1 = np.zeros_like(vs30) c1 = np.zeros_like(vs30) for k, v in config['holzer_liq_cal']['parameters'].items(): ind = np.where(vs30 == float(v[0])) a0[ind] = v[1] b0[ind] = v[2] c0[ind] = v[3] a1[ind] = v[4] b1[ind] = v[5] c1[ind] = v[6] #--------------------------------------------------------------------------- # Water table #--------------------------------------------------------------------------- wtd_grid = GMTGrid.load(wtd_file, fgeodict, resample=True, method=layers['watertable']['interpolation'], doPadding=True) tmp = wtd_grid._data tmp = np.nan_to_num(tmp) # Compute water weights w0, w1 = get_water_weights(tmp) #--------------------------------------------------------------------------- # Compute probability of liquefaction #--------------------------------------------------------------------------- prob0 = get_prob(PGA, a0, b0, c0, mag) prob1 = get_prob(PGA, a1, b1, c1, mag) prob = prob0 * w0 + prob1 * w1 #--------------------------------------------------------------------------- # Turn output and inputs into into grids and put in maplayers dictionary #--------------------------------------------------------------------------- maplayers = collections.OrderedDict() temp = shakemap.getShakeDict() shakedetail = '%s_ver%s' % (temp['shakemap_id'], temp['shakemap_version']) modelsref = config['holzer_liq_cal']['shortref'] modellref = config['holzer_liq_cal']['longref'] modeltype = 'Holzer/Wills' maplayers['model'] = { 'grid': GDALGrid(prob, fgeodict), 'label': 'Probability', 'type': 'output', 'description': { 'name': modelsref, 'longref': modellref, 'units': 'coverage', 'shakemap': shakedetail, 'parameters': { 'modeltype': modeltype } } } if saveinputs is True: maplayers['pga'] = { 'grid': GDALGrid(PGA, fgeodict), 'label': 'PGA (g)', 'type': 'input', 'description': { 'units': 'g', 'shakemap': shakedetail } } maplayers['vs30'] = { 'grid': GDALGrid(vs30, fgeodict), 'label': 'Vs30 (m/s)', 'type': 'input', 'description': { 'units': 'm/s' } } maplayers['wtd'] = { 'grid': GDALGrid(wtd_grid._data, fgeodict), 'label': 'wtd (m)', 'type': 'input', 'description': { 'units': 'm' } } return maplayers
def slhrf_liq(shakefile, config, uncertfile=None, saveinputs=False, modeltype=None, displmodel=None, probtype=None, bounds=None): """ Method for computing the probability of liquefaction using the SLHRF, primarily relying on the Wills et al. (2015) Vs30 map of California and Hydrosheds distance to rivers. """ layers = config['slhrf_liq_cal']['layers'] vs30_file = layers['vs30']['file'] elev_file = layers['elev']['file'] dc_file = layers['dc']['file'] dr_file = layers['dr']['file'] fgeodict = GMTGrid.getFileGeoDict(vs30_file)[0] #--------------------------------------------------------------------------- # Read in data layers #--------------------------------------------------------------------------- shakemap = ShakeGrid.load(shakefile, fgeodict, resample=True, method='linear', doPadding=True) PGA = shakemap.getLayer('pga').getData()/100 # convert to g griddict,eventdict,specdict,fields,uncertainties = getHeaderData(shakefile) mag = eventdict['magnitude'] vs30_grid = GMTGrid.load(vs30_file) vs30 = vs30_grid.getData() elev = GDALGrid.load(elev_file, fgeodict, resample=True, method=layers['elev']['interpolation'], doPadding = True).getData() dc = GDALGrid.load(dc_file, fgeodict, resample=True, method=layers['dc']['interpolation'], doPadding = True).getData() dr = GDALGrid.load(dr_file, fgeodict, resample=True, method=layers['dr']['interpolation'], doPadding = True).getData() dw = np.minimum(dr, dc) #--------------------------------------------------------------------------- # Evaluate the different factors #--------------------------------------------------------------------------- Fgeo = np.zeros_like(vs30) for k,v in config['slhrf_liq_cal']['parameters'].items(): ind = np.where(vs30 == float(v[0])) Fgeo[ind] = float(v[1]) Fz = z_factor(elev) Fmag = mag_factor(mag) Fpga = pga_factor(PGA) Fdw = dw_factor(dw) Fnehrp = nehrp_factor(vs30) #--------------------------------------------------------------------------- # Combine factors #--------------------------------------------------------------------------- SLHRF = Fz * Fmag * Fpga * Fdw * Fgeo * Fnehrp # Transform into a 'probability' prob = 0.4 * (1 - np.exp(-0.2 * SLHRF**2) ) #--------------------------------------------------------------------------- # Turn output and inputs into into grids and put in maplayers dictionary #--------------------------------------------------------------------------- maplayers = collections.OrderedDict() temp = shakemap.getShakeDict() shakedetail = '%s_ver%s' % (temp['shakemap_id'], temp['shakemap_version']) modelsref = config['slhrf_liq_cal']['shortref'] modellref = config['slhrf_liq_cal']['longref'] modeltype = 'SLHRF/Wills' maplayers['model'] = {'grid': GDALGrid(prob, fgeodict), 'label': 'Probability', 'type': 'output', 'description': {'name': modelsref, 'longref': modellref, 'units': 'coverage', 'shakemap': shakedetail, 'parameters': {'modeltype': modeltype} } } if saveinputs is True: maplayers['slhrf'] = {'grid': GDALGrid(SLHRF, fgeodict), 'label': 'SLHRF', 'type': 'input', 'description': {'units': 'none'}} maplayers['pga'] = {'grid': GDALGrid(PGA, fgeodict), 'label': 'PGA (g)', 'type': 'input', 'description': {'units': 'g', 'shakemap': shakedetail}} maplayers['vs30'] = {'grid': GDALGrid(vs30, fgeodict), 'label': 'Vs30 (m/s)', 'type': 'input', 'description': {'units': 'm/s'}} maplayers['dw'] = {'grid': GDALGrid(dw, fgeodict), 'label': 'dw (km)', 'type': 'input', 'description': {'units': 'km'}} maplayers['elev'] = {'grid': GDALGrid(elev, fgeodict), 'label': 'elev (m)', 'type': 'input', 'description': {'units': 'm'}} maplayers['FPGA'] = {'grid': GDALGrid(Fpga, fgeodict), 'label': 'Fpga', 'type': 'input', 'description': {'units': 'none'}} maplayers['FDW'] = {'grid': GDALGrid(Fdw, fgeodict), 'label': 'Fdw', 'type': 'input', 'description': {'units': 'none'}} maplayers['FGEO'] = {'grid': GDALGrid(Fgeo, fgeodict), 'label': 'Fgeo', 'type': 'input', 'description': {'units': 'none'}} maplayers['FZ'] = {'grid': GDALGrid(Fz, fgeodict), 'label': 'Fz', 'type': 'input', 'description': {'units': 'none'}} maplayers['FNEHRP'] = {'grid': GDALGrid(Fnehrp, fgeodict), 'label': 'Fnehrp', 'type': 'input', 'description': {'units': 'none'}} return maplayers