def test_get_mean_table(self, idx=0): """ Test the retrieval of the mean amplification tables for a given magnitude and IMT """ rctx = RuptureContext() rctx.mag = 6.0 # PGA expected_table = np.ones([10, 2]) expected_table[:, self.IDX] *= 1.5 np.testing.assert_array_almost_equal( self.amp_table.get_mean_table(imt_module.PGA(), rctx), expected_table) # SA expected_table[:, self.IDX] = 2.0 * np.ones(10) np.testing.assert_array_almost_equal( self.amp_table.get_mean_table(imt_module.SA(0.5), rctx), expected_table) # SA (period interpolation) interpolator = interp1d(np.log10(self.amp_table.periods), np.log10(np.array([1.5, 2.0, 0.5]))) period = 0.3 expected_table[:, self.IDX] = (10.0**interpolator( np.log10(period))) * np.ones(10.) np.testing.assert_array_almost_equal( self.amp_table.get_mean_table(imt_module.SA(period), rctx), expected_table)
def test_retreival_tables_good_no_interp(self): """ Tests the retreival of the IML tables for 'good' conditions without applying magnitude interpolations """ gsim = GMPETable(gmpe_table=self.TABLE_FILE) # PGA np.testing.assert_array_almost_equal( gsim._return_tables(6.0, imt_module.PGA(), "IMLs"), np.array([2., 1., 0.5])) # PGV np.testing.assert_array_almost_equal( gsim._return_tables(6.0, imt_module.PGV(), "IMLs"), np.array([20., 10., 5.]), 5) # SA(1.0) np.testing.assert_array_almost_equal( gsim._return_tables(6.0, imt_module.SA(1.0), "IMLs"), np.array([2.0, 1., 0.5])) # Also for standard deviations np.testing.assert_array_almost_equal( gsim._return_tables(6.0, imt_module.PGA(), "Total"), 0.5 * np.ones(3)) np.testing.assert_array_almost_equal( gsim._return_tables(6.0, imt_module.SA(1.0), "Total"), 0.8 * np.ones(3))
def test_get_amplification_factors(self): """ Tests the amplification tables """ ctx = RuptureContext() ctx.rake = 45.0 ctx.mag = 6.0 # Takes distances at the values found in the table (not checking # distance interpolation) ctx.rjb = np.copy(self.amp_table.distances[:, 0, 0]) # Test Vs30 is 700.0 m/s midpoint between the 400 m/s and 1000 m/s # specified in the table stddevs = [const.StdDev.TOTAL] expected_mean = np.ones_like(ctx.rjb) # Check PGA and PGV mean_amp, sigma_amp = self.amp_table.get_amplification_factors( imt_module.PGA(), ctx, ctx.rjb, stddevs) np.testing.assert_array_almost_equal( mean_amp, midpoint(1.0, 1.5) * expected_mean) np.testing.assert_array_almost_equal(sigma_amp[0], 0.9 * expected_mean) mean_amp, sigma_amp = self.amp_table.get_amplification_factors( imt_module.PGV(), ctx, ctx.rjb, stddevs) np.testing.assert_array_almost_equal( mean_amp, midpoint(1.0, 0.5) * expected_mean) np.testing.assert_array_almost_equal(sigma_amp[0], 0.9 * expected_mean) # Sa (0.5) mean_amp, sigma_amp = self.amp_table.get_amplification_factors( imt_module.SA(0.5), ctx, ctx.rjb, stddevs) np.testing.assert_array_almost_equal( mean_amp, midpoint(1.0, 2.0) * expected_mean) np.testing.assert_array_almost_equal(sigma_amp[0], 0.9 * expected_mean)
def test_get_mean_and_stddevs(self): """ Tests mean and standard deviations without amplification """ gsim = GMPETable(gmpe_table=self.TABLE_FILE) rctx = RuptureContext() rctx.mag = 6.0 dctx = DistancesContext() # Test values at the given distances and those outside range dctx.rjb = np.array([0.5, 1.0, 10.0, 100.0, 500.0]) sctx = SitesContext() stddevs = [const.StdDev.TOTAL] expected_mean = np.array([2.0, 2.0, 1.0, 0.5, 1.0E-20]) # PGA mean, sigma = gsim.get_mean_and_stddevs(sctx, rctx, dctx, imt_module.PGA(), stddevs) np.testing.assert_array_almost_equal(np.exp(mean), expected_mean, 5) np.testing.assert_array_almost_equal(sigma[0], 0.5 * np.ones(5), 5) # SA mean, sigma = gsim.get_mean_and_stddevs(sctx, rctx, dctx, imt_module.SA(1.0), stddevs) np.testing.assert_array_almost_equal(np.exp(mean), expected_mean, 5) np.testing.assert_array_almost_equal(sigma[0], 0.8 * np.ones(5), 5) # PGV mean, sigma = gsim.get_mean_and_stddevs(sctx, rctx, dctx, imt_module.PGV(), stddevs) np.testing.assert_array_almost_equal(np.exp(mean), 10. * expected_mean, 5) np.testing.assert_array_almost_equal(sigma[0], 0.5 * np.ones(5), 5)
def test_get_mean_and_stddevs_good_amplified(self): """ Tests the full execution of the GMPE tables for valid data with amplification """ gsim = GMPETable(gmpe_table=self.TABLE_FILE) rctx = RuptureContext() rctx.mag = 6.0 dctx = DistancesContext() # Test values at the given distances and those outside range dctx.rjb = np.array([0.5, 1.0, 10.0, 100.0, 500.0]) sctx = SitesContext() sctx.vs30 = 100. * np.ones(5) stddevs = [const.StdDev.TOTAL] expected_mean = np.array([20., 20., 10., 5., 1.0E-19]) expected_sigma = 0.25 * np.ones(5) # PGA mean, sigma = gsim.get_mean_and_stddevs(sctx, rctx, dctx, imt_module.PGA(), stddevs) np.testing.assert_array_almost_equal(np.exp(mean), expected_mean, 5) np.testing.assert_array_almost_equal(sigma[0], expected_sigma, 5) # SA mean, sigma = gsim.get_mean_and_stddevs(sctx, rctx, dctx, imt_module.SA(1.0), stddevs) np.testing.assert_array_almost_equal(np.exp(mean), expected_mean, 5) np.testing.assert_array_almost_equal(sigma[0], 0.4 * np.ones(5), 5)
def _setup_table_from_str(self, table, sa_damping): """ Builds the input tables from a string definition """ table = table.strip().splitlines() header = table.pop(0).split() if not header[0].upper() == "IMT": raise ValueError('first column in a table must be IMT') coeff_names = header[1:] for row in table: row = row.split() imt_name = row[0].upper() if imt_name == 'SA': raise ValueError('specify period as float value ' 'to declare SA IMT') imt_coeffs = dict(zip(coeff_names, map(float, row[1:]))) try: sa_period = float(imt_name) except Exception: if not hasattr(imt_module, imt_name): raise ValueError('unknown IMT %r' % imt_name) imt = getattr(imt_module, imt_name)() self.non_sa_coeffs[imt] = imt_coeffs else: if sa_damping is None: raise TypeError('attribute "sa_damping" is required ' 'for tables defining SA') imt = imt_module.SA(sa_period, sa_damping) self.sa_coeffs[imt] = imt_coeffs
def __init__(self, **kwargs): if not 'table' in kwargs: raise TypeError('CoeffsTable requires "table" kwarg') table = kwargs.pop('table').strip().splitlines() sa_damping = kwargs.pop('sa_damping', None) if kwargs: raise TypeError('CoeffsTable got unexpected kwargs: %r' % kwargs) header = table.pop(0).split() if not header[0].upper() == "IMT": raise ValueError('first column in a table must be IMT') coeff_names = header[1:] self.sa_coeffs = {} self.non_sa_coeffs = {} for row in table: row = row.split() imt_name = row[0].upper() if imt_name == 'SA': raise ValueError('specify period as float value ' 'to declare SA IMT') imt_coeffs = dict(zip(coeff_names, map(float, row[1:]))) try: sa_period = float(imt_name) except: if not hasattr(imt_module, imt_name): raise ValueError('unknown IMT %r' % imt_name) imt = getattr(imt_module, imt_name)() self.non_sa_coeffs[imt] = imt_coeffs else: if sa_damping is None: raise TypeError('attribute "sa_damping" is required ' 'for tables defining SA') imt = imt_module.SA(sa_period, sa_damping) self.sa_coeffs[imt] = imt_coeffs
def test_get_mean_and_stddevs_good(self): """ Tests the full execution of the GMPE tables for valid data """ gsim = GMPETable(gmpe_table=self.TABLE_FILE) ctx = RuptureContext() ctx.mag = 6.0 # Test values at the given distances and those outside range ctx.rjb = np.array([0.5, 1.0, 10.0, 100.0, 500.0]) ctx.vs30 = 1000. * np.ones(5) ctx.sids = np.arange(5) stddevs = [const.StdDev.TOTAL] expected_mean = np.array([2.0, 2.0, 1.0, 0.5, 1.0E-20]) expected_sigma = 0.25 * np.ones(5) imts = [imt_module.PGA(), imt_module.SA(1.0), imt_module.PGV()] # PGA mean, sigma = gsim.get_mean_and_stddevs(ctx, ctx, ctx, imts[0], stddevs) np.testing.assert_array_almost_equal(np.exp(mean), expected_mean, 5) np.testing.assert_array_almost_equal(sigma[0], expected_sigma, 5) # SA mean, sigma = gsim.get_mean_and_stddevs(ctx, ctx, ctx, imts[1], stddevs) np.testing.assert_array_almost_equal(np.exp(mean), expected_mean, 5) np.testing.assert_array_almost_equal(sigma[0], 0.4 * np.ones(5), 5) # PGV mean, sigma = gsim.get_mean_and_stddevs(ctx, ctx, ctx, imts[2], stddevs) np.testing.assert_array_almost_equal(np.exp(mean), 10. * expected_mean, 5) np.testing.assert_array_almost_equal(sigma[0], expected_sigma, 5) # StdDev.ALL check contexts.get_mean_stds([gsim], ctx, imts)
def test_retreival_tables_outside_period_range(self): """ Tests that an error is raised when inputting a period value outside the supported range """ gsim = GMPETable(gmpe_table=self.TABLE_FILE) with self.assertRaises(ValueError) as ve: gsim._return_tables(6.0, imt_module.SA(2.5), "IMLs") self.assertEqual( str(ve.exception), "Spectral period 2.500 outside of valid range (0.100 to 2.000)")
def test_calculation_mean(self): DATA_FILE = data / "AMERI2017/A17_Rjb_Homoscedastic_MEAN.csv" stddev_types = [const.StdDev.TOTAL] # Unused here sctx = gsim.base.SitesContext() rctx = gsim.base.RuptureContext() dctx = gsim.base.DistancesContext() with open(DATA_FILE, 'r') as f: # Read periods from header: header = f.readline() periods = header.strip().split(',')[7:] # Periods in s. for line in f: arr_str = line.strip().split(',') arr_str[ 5] = "9999" # Replace result_type string by any float-convertible value arr = np.float_(arr_str) # Setting ground-motion attributes: setattr(rctx, 'mag', arr[0]) setattr(rctx, 'rake', arr[1]) stress_drop = arr[2] setattr(dctx, 'rjb', arr[3]) setattr(sctx, 'vs30', np.array([arr[4]])) damp = arr[6] # Compute ground-motion: gmpe = gsim.ameri_2017.AmeriEtAl2017RjbStressDrop( norm_stress_drop=stress_drop) for k in range(len(periods)): per = periods[k] value = np.log(arr[ 7 + k]) # convert value to ln(SA) with SA in units of g if per == 'pga': P = imt.PGA() else: P = imt.SA(period=np.float_(per), damping=damp) mean = gmpe.get_mean_and_stddevs(sctx, rctx, dctx, P, stddev_types)[0] np.testing.assert_almost_equal(mean, value, decimal=MEAN_DECIMAL)
def test_get_sigma_table(self): """ Test the retrieval of the standard deviation modification tables for a given magnitude and IMT """ rctx = RuptureContext() rctx.mag = 6.0 # PGA expected_table = np.ones([10, 2]) expected_table[:, self.IDX] *= 0.8 stddevs = ["Total"] pga_table = self.amp_table.get_sigma_tables(imt_module.PGA(), rctx, stddevs)[0] np.testing.assert_array_almost_equal(pga_table, expected_table) # SA (for coverage) sa_table = self.amp_table.get_sigma_tables(imt_module.SA(0.3), rctx, stddevs)[0] np.testing.assert_array_almost_equal(sa_table, expected_table)
def test_calculation_std_inter(self): DATA_FILE = (data / "AMERI2017/A17_Repi_Homoscedastic_INTER_EVENT_STDDEV.csv") stddev_types = [const.StdDev.INTER_EVENT] ctx = gsim.base.RuptureContext() with open(DATA_FILE, 'r') as f: # Read periods from header: header = f.readline() periods = header.strip().split(',')[7:] # Periods in s. for line in f: arr_str = line.strip().split(',') arr_str[5] = "9999" # Replace result_type string by any float-convertible value arr = np.float_(arr_str) # Setting ground-motion attributes: setattr(ctx, 'mag', arr[0]) setattr(ctx, 'rake', arr[1]) stress_drop = arr[2] setattr(ctx, 'repi', arr[3]) setattr(ctx, 'vs30', np.array([arr[4]])) damp = arr[6] ctx.sids = [0] # Compute ground-motion: gmpe = gsim.ameri_2017.AmeriEtAl2017RepiStressDrop( norm_stress_drop=stress_drop) for k in range(len(periods)): per = periods[k] value = arr[7 + k] if per == 'pga': P = imt.PGA() else: P = imt.SA(period=np.float_(per), damping=damp) std = gmpe.get_mean_and_stddevs(ctx, ctx, ctx, P, stddev_types)[1][0] np.testing.assert_almost_equal(std, value, decimal=STDDEV_DECIMAL)
def test_retreival_tables_good_interp(self): """ Tests the retreival of the IML tables for 'good' conditions with magnitude interpolations """ gsim = GMPETable(gmpe_table=self.TABLE_FILE) expected_table_pgv = np.array([midpoint(20., 40.), midpoint(10., 20.), midpoint(5., 10.)]) np.testing.assert_array_almost_equal( gsim._return_tables(6.5, imt_module.PGV(), "IMLs"), expected_table_pgv, 5) expected_table_sa1 = np.array([midpoint(2., 4.), midpoint(1., 2.), midpoint(0.5, 1.)]) np.testing.assert_array_almost_equal( gsim._return_tables(6.5, imt_module.SA(1.0), "IMLs"), expected_table_sa1)
def compute_rho_avgsa(per, avg_periods, sctx, rctx, dctx, stddvs_avgsa, bgmpe, corr_type): """ """ # Import libraries from openquake.hazardlib import imt, const, gsim from .modified_akkar_correlation_model import ModifiedAkkarCorrelationModel sum_numeratore = 0 for i1 in avg_periods: rho = [] if corr_type == 'baker_jayaram': rho = gsim.mgmpe.generic_gmpe_avgsa. \ BakerJayaramCorrelationModel([per, i1])(0, 1) if corr_type == 'akkar': rho = ModifiedAkkarCorrelationModel([per, i1])(0, 1) s = [const.StdDev.TOTAL] mean1, std1 = bgmpe().get_mean_and_stddevs(sctx, rctx, dctx, imt.SA(i1), s) sum_numeratore = sum_numeratore + rho * std1[0] denominatore = len(avg_periods) * stddvs_avgsa rho_avgsa = sum_numeratore / denominatore return rho_avgsa
def get_extent(rupture=None, config=None): """ Method to compute map extent from rupture. There are numerous methods for getting the extent: - It can be specified directly in the config file, - it can be hard coded for specific magnitude ranges in the config file, or - it can be based on the MultiGMPE for the event. All methods except for the first requires a rupture object. If no config is provided then a rupture is required and the extent is based on a generic set of active/stable. Args: rupture (Rupture): A ShakeMap Rupture instance. config (ConfigObj): ShakeMap config object. Returns: tuple: lonmin, lonmax, latmin, latmax rounded to the nearest arc-minute.. """ # ------------------------------------------------------------------------- # Check to see what parameters are specified in the extent config # ------------------------------------------------------------------------- spans = {} bounds = [] if config is not None: if 'extent' in config: if 'magnitude_spans' in config['extent']: if len(config['extent']['magnitude_spans']): if isinstance(config['extent']['magnitude_spans'], dict): spans = config['extent']['magnitude_spans'] if 'bounds' in config['extent']: if 'extent' in config['extent']['bounds']: if config['extent']['bounds']['extent'][0] != -999.0: bounds = config['extent']['bounds']['extent'] # ------------------------------------------------------------------------- # Simplest option: extent was specified in the config, use that and exit. # ------------------------------------------------------------------------- if len(bounds): xmin, ymin, xmax, ymax = bounds return (xmin, xmax, ymin, ymax) if not rupture or not isinstance(rupture, Rupture): raise TypeError('get_extent() requires a rupture object if the extent ' 'is not specified in the config object.') # Find the central point origin = rupture.getOrigin() if isinstance(rupture, (QuadRupture, EdgeRupture)): # For an extended rupture, it is the midpoint between the extent of the # verticies lats = rupture.lats lons = rupture.lons # Remove nans lons = lons[~np.isnan(lons)] lats = lats[~np.isnan(lats)] clat = 0.5 * (np.nanmax(lats) + np.nanmin(lats)) clon = 0.5 * (np.nanmax(lons) + np.nanmin(lons)) else: # For a point source, it is just the epicenter clat = origin.lat clon = origin.lon mag = origin.mag # ------------------------------------------------------------------------- # Second simplest option: spans are hardcoded based on magnitude # ------------------------------------------------------------------------- if len(spans): xmin = None xmax = None ymin = None ymax = None for spankey, span in spans.items(): if mag > span[0] and mag <= span[1]: ymin = clat - span[2] / 2 ymax = clat + span[2] / 2 xmin = clon - span[3] / 2 xmax = clon + span[3] / 2 break if xmin is not None: return (xmin, xmax, ymin, ymax) # ------------------------------------------------------------------------- # Use MultiGMPE to get spans # ------------------------------------------------------------------------- if config is not None: gmpe = MultiGMPE.from_config(config) gmice = get_object_from_config('gmice', 'modeling', config) else: # Put in some default values for conf config = { 'extent': { 'mmi': { 'threshold': 4.5, 'mindist': 100, 'maxdist': 1000 } } } # Generic GMPEs choices based only on active vs stable # as defaults... stable = is_stable(origin.lon, origin.lat) if not stable: ASK14 = AbrahamsonEtAl2014() CB14 = CampbellBozorgnia2014() CY14 = ChiouYoungs2014() gmpes = [ASK14, CB14, CY14] site_gmpes = None weights = [1 / 3.0, 1 / 3.0, 1 / 3.0] gmice = WGRW12() else: Fea96 = FrankelEtAl1996MwNSHMP2008() Tea97 = ToroEtAl1997MwNSHMP2008() Sea02 = SilvaEtAl2002MwNSHMP2008() C03 = Campbell2003MwNSHMP2008() TP05 = TavakoliPezeshk2005MwNSHMP2008() AB06p = AtkinsonBoore2006Modified2011() Pea11 = PezeshkEtAl2011() Atk08p = Atkinson2008prime() Sea01 = SomervilleEtAl2001NSHMP2008() gmpes = [ Fea96, Tea97, Sea02, C03, TP05, AB06p, Pea11, Atk08p, Sea01 ] site_gmpes = [AB06p] weights = [0.16, 0.0, 0.0, 0.17, 0.17, 0.3, 0.2, 0.0, 0.0] gmice = AK07() gmpe = MultiGMPE.from_list(gmpes, weights, default_gmpes_for_site=site_gmpes) min_mmi = config['extent']['mmi']['threshold'] default_imt = imt.SA(1.0) sd_types = [const.StdDev.TOTAL] # Distance context dx = DistancesContext() # This imposes minimum/ maximum distances of: # 80 and 800 km; could make this configurable d_min = config['extent']['mmi']['mindist'] d_max = config['extent']['mmi']['maxdist'] dx.rjb = np.logspace(np.log10(d_min), np.log10(d_max), 2000) # Details don't matter for this; assuming vertical surface rupturing fault # with epicenter at the surface. dx.rrup = dx.rjb dx.rhypo = dx.rjb dx.repi = dx.rjb dx.rx = np.zeros_like(dx.rjb) dx.ry0 = np.zeros_like(dx.rjb) dx.rvolc = np.zeros_like(dx.rjb) # Sites context sx = SitesContext() # Set to soft soil conditions sx.vs30 = np.full_like(dx.rjb, 180) sx = MultiGMPE.set_sites_depth_parameters(sx, gmpe) sx.vs30measured = np.full_like(sx.vs30, False, dtype=bool) sx = Sites._addDepthParameters(sx) sx.backarc = np.full_like(sx.vs30, False, dtype=bool) # Rupture context rx = RuptureContext() rx.mag = origin.mag rx.rake = 0.0 # From WC94... rx.width = 10**(-0.76 + 0.27 * rx.mag) rx.dip = 90.0 rx.ztor = origin.depth rx.hypo_depth = origin.depth gmpe_imt_mean, _ = gmpe.get_mean_and_stddevs(sx, rx, dx, default_imt, sd_types) # Convert to MMI gmpe_to_mmi, _ = gmice.getMIfromGM(gmpe_imt_mean, default_imt) # Minimum distance that exceeds threshold MMI? dists_exceed_mmi = dx.rjb[gmpe_to_mmi > min_mmi] if len(dists_exceed_mmi): mindist_km = np.max(dists_exceed_mmi) else: mindist_km = d_min # Get a projection proj = OrthographicProjection(clon - 4, clon + 4, clat + 4, clat - 4) if isinstance(rupture, (QuadRupture, EdgeRupture)): ruptx, rupty = proj(lons, lats) else: ruptx, rupty = proj(clon, clat) xmin = np.nanmin(ruptx) - mindist_km ymin = np.nanmin(rupty) - mindist_km xmax = np.nanmax(ruptx) + mindist_km ymax = np.nanmax(rupty) + mindist_km # Put a limit on range of aspect ratio dx = xmax - xmin dy = ymax - ymin ar = dy / dx if ar > 1.2: # Inflate x dx_target = dy / 1.2 ddx = dx_target - dx xmax = xmax + ddx / 2 xmin = xmin - ddx / 2 if ar < 0.83: # Inflate y dy_target = dx * 0.83 ddy = dy_target - dy ymax = ymax + ddy / 2 ymin = ymin - ddy / 2 lonmin, latmin = proj(np.array([xmin]), np.array([ymin]), reverse=True) lonmax, latmax = proj(np.array([xmax]), np.array([ymax]), reverse=True) # # Round coordinates to the nearest minute -- that should make the # output grid register with common grid resolutions (60c, 30c, # 15c, 7.5c) # logging.debug("Extent: %f, %f, %f, %f" % (lonmin, lonmax, latmin, latmax)) return _round_coord(lonmin[0]), _round_coord(lonmax[0]), \ _round_coord(latmin[0]), _round_coord(latmax[0])
dx.rx = np.array([ztest[i, 10]]) dx.ry0 = np.array([0]) sx.z1pt0 = np.array([ztest[i, 3]]) sx.z2pt5 = np.array([ztest[i, 4]]) # Evaluate GMPE #Unit of measure for Z1.0 is [m] (ASK) #lmean, lsd = gmpeASK.get_mean_and_stddevs(sx, rx, dx, imt.PGV(), stddev_types) #for period1 in period: for ii in range(0, 6): sx.vs30measured = 0 period1 = period[ii] gmpeBSSAdata[i, ii], g = gmpeBSSA.get_mean_and_stddevs( sx, rx, dx, imt.SA(period1), stddev_types) gmpeBSSAstd[i, ii] = g[0][0] gmpeCBdata[i, ii], g = gmpeCB.get_mean_and_stddevs( sx, rx, dx, imt.SA(period1), stddev_types) gmpeCBstd[i, ii] = g[0][0] gmpeCYdata[i, ii], g = gmpeCY.get_mean_and_stddevs( sx, rx, dx, imt.SA(period1), stddev_types) gmpeCYstd[i, ii] = g[0][0] sx.vs30measured = [0] gmpeASKdata[i, ii], g = gmpeASK.get_mean_and_stddevs( sx, rx, dx, imt.SA(period1), stddev_types) gmpeASKstd[i, ii] = g[0][0]
def get_mean_and_stddevs(self, sites, rx, dists, imt, stddev_types): # List of GMPE weights, which is the product of the the branch weights # for the seed models vs the NGA East resampled models as well as the # weights for the indivudual GMPES as defined by Petersen et al. (2019) # # Note that the NGA East resampled models are a function of spectral # period. # # NGA East Seeds (1/3) # ├── B_bca10d (0.06633), wts = 0.333 * 0.06633 = 0.02208789 # ├── B_ab95 (0.02211), wts = 0.333 * 0.02211 = 0.00736263 # ... # NGA East Resampled or "USGS" (2/3) # ├── Model 1 (0.1009 for PGA), wts = 0.667 * 0.1009 = 0.0673003 # ├── Model 2 (0.1606 for PGA), wts = 0.667 * 0.1606 = 0.1071202 # ... # wts = [0] * len(self.gmpes) # Is IMT PGA or PGV? is_pga = imt == IMT.PGA() is_pgv = imt == IMT.PGV() # Is magnitude less than 4? If so, we will need to set it to 4.0 and # then extrapolate the tables at the end. # But... in the brave new world of new OpenQuake, sites, rx, and # dists are all exactly the same object, so when we copy rx to # rup, and change it, as well as when we change the distances # below, we need to do it all in rup, then pass rup as all three # contexts when we call the gmpe.get_mean_and_stddevs() rup = copy.deepcopy(rx) if rup.mag < 4.0: is_small_mag = True delta_mag = rup.mag - 4.0 rup.mag = 4.0 else: is_small_mag = False for i, tp in enumerate(self.ALL_TABLE_PATHS): if 'usgs' in tp: # Get model number from i-th path using regex mod_num = int(re.search(r'\d+', tp).group()) coefs = np.array(self.NGA_EAST_USGS.iloc[mod_num - 1]) # Is the IMT PGA, PGA, or SA? if is_pga: iweight = coefs[-2] elif is_pgv: iweight = coefs[-1] else: # For SA, need to interpolate; we'll use log-period and # linear-weight interpolation. iweight = np.interp( np.log(imt.period), np.log(self.per_array), coefs[self.per_idx_start:self.per_idx_end]) wts[i] = self.NGA_EAST_USGS_WEIGHT * iweight else: # Strip off the cruft to get the string we need to match str_match = tp.replace('nga_east_', '').replace('.hdf5', '') matched = self.NGA_EAST_SEEDS[self.NGA_EAST_SEEDS['model'] == str_match] if len(matched): iweight = self.NGA_EAST_SEEDS[self.NGA_EAST_SEEDS['model'] == str_match].iloc[0, 1] wts[i] = self.NGA_EAST_SEED_WEIGHT * iweight total_gmpe_weights = self.sigma_weights * wts if not np.allclose(np.sum(total_gmpe_weights), 1.0): raise ValueError('Weights must sum to 1.0.') mean = np.full_like(sites.vs30, 0) stddevs = [] for i in range(len(stddev_types)): stddevs.append(np.full_like(sites.vs30, 0)) # Apply max distance to dists.rrup -->> now rup.rrup np.clip(rup.rrup, 0, MAX_RRUP) # # Some models don't have PGV terms, so we will make PSA for them # and then use the conditional conversion to get PGV # if is_pgv: ab2020 = AbrahamsonBhasin2020(rup.mag) vimt = IMT.SA(ab2020.getTref()) # Loop over gmpes for i, gm in enumerate(self.gmpes): if is_pgv: # Is PGV and also not available for gm? try: _ = _return_tables(gm, rup.mag, imt, "IMLs") except KeyError: # # No table for PGV, compute vimt, then convert to PGV # vmean, vstddevs = gm.get_mean_and_stddevs( rup, rup, rup, vimt, stddev_types) tmean, tstddevs = ab2020.getPGVandSTDDEVS( vmean, vstddevs, stddev_types, rup.rrup, rup.vs30) except Exception: logging.error("Unexpected error:", sys.exc_info()[0]) else: # # Table exists for PGV, proceed normally # tmean, tstddevs = gm.get_mean_and_stddevs( rup, rup, rup, imt, stddev_types) else: tmean, tstddevs = gm.get_mean_and_stddevs( rup, rup, rup, imt, stddev_types) mean += tmean * total_gmpe_weights[i] for j, sd in enumerate(tstddevs): stddevs[j] += sd * total_gmpe_weights[i] # Zero out values at distances beyond the range for which NGA East # was defined. -->> was dists.rrup, now rup.rrup mean[rup.rrup > MAX_RRUP] = -999.0 # Do we need to extrapolate for small magnitude factor? if is_small_mag: if is_pga: slopes = np.interp(np.log(rup.rrup), np.log(self.SMALL_M_DIST), self.SMALL_M_SLOPE_PGA) elif is_pgv: slopes = np.interp(np.log(rup.rrup), np.log(self.SMALL_M_DIST), self.SMALL_M_SLOPE_PGV) else: interp_obj = RectBivariateSpline(np.log(self.SMALL_M_DIST), np.log(self.SMALL_M_PER), self.SMALL_M_SLOPE, kx=1, ky=1) slopes = interp_obj.ev(np.log(rup.rrup), np.log(imt.period)) mean = mean + slopes * delta_mag return mean, stddevs
def gmpe_avg(ztest): ''' transforms cybershake dips and Rx Parameters ---------- ztest: 2d numpy array of 12 feature data Returns ------- model_avg: average of base model predictions in ln m/s2 ''' import numpy as np import openquake from openquake.hazardlib.gsim.abrahamson_2014 import AbrahamsonEtAl2014 #ASK from openquake.hazardlib.gsim.campbell_bozorgnia_2014 import CampbellBozorgnia2014 #CB from openquake.hazardlib.gsim.chiou_youngs_2014 import ChiouYoungs2014 #CY from openquake.hazardlib.gsim.boore_2014 import BooreEtAl2014 #BSSA import openquake.hazardlib.imt as imt from openquake.hazardlib.const import StdDev import openquake.hazardlib.gsim.base as base stddev_types = [StdDev.TOTAL] period = [10, 7.5, 5, 4, 3, 2, 1, 0.5, 0.2, 0.1] gmpeBSSAdata = np.zeros((ztest.shape[0], len(period))) gmpeASKdata = np.zeros((ztest.shape[0], len(period))) gmpeCBdata = np.zeros((ztest.shape[0], len(period))) gmpeCYdata = np.zeros((ztest.shape[0], len(period))) gmpeBSSAstd = np.zeros((ztest.shape[0], len(period))) gmpeASKstd = np.zeros((ztest.shape[0], len(period))) gmpeCBstd = np.zeros((ztest.shape[0], len(period))) gmpeCYstd = np.zeros((ztest.shape[0], len(period))) gmpeASK = AbrahamsonEtAl2014() gmpeCB = CampbellBozorgnia2014() gmpeCY = ChiouYoungs2014() gmpeBSSA = BooreEtAl2014() for i in range(ztest.shape[0]): dx = base.DistancesContext() dx.rjb = np.array([ztest[i, 9]]) #dx.rjb = np.logspace(-1, 2, 10) # Magnitude and rake rx = base.RuptureContext() rx.mag = np.array([ztest[i, 0]]) rx.rake = np.array([ztest[i, 5]]) rx.hypo_depth = np.array([ztest[i, 7]]) # Vs30 sx = base.SitesContext() sx.vs30 = np.array([ztest[i, 2]]) sx.vs30measured = 0 dx.rrup = np.array([ztest[i, 1]]) rx.ztor = np.array([ztest[i, 11]]) rx.dip = np.array([ztest[i, 6]]) rx.width = np.array([ztest[i, 8]]) # dx.rx=np.array([rxkeep[i]]) dx.rx = np.array([ztest[i, 10]]) dx.ry0 = np.array([0]) sx.z1pt0 = np.array([ztest[i, 3]]) sx.z2pt5 = np.array([ztest[i, 4]]) # Evaluate GMPE #Unit of measure for Z1.0 is [m] (ASK) #for period1 in period: for ii in range(len(period)): sx.vs30measured = 0 period1 = period[ii] gmpeBSSAdata[i, ii], g = gmpeBSSA.get_mean_and_stddevs( sx, rx, dx, imt.SA(period1), stddev_types) gmpeBSSAstd[i, ii] = g[0][0] gmpeCBdata[i, ii], g = gmpeCB.get_mean_and_stddevs( sx, rx, dx, imt.SA(period1), stddev_types) gmpeCBstd[i, ii] = g[0][0] gmpeCYdata[i, ii], g = gmpeCY.get_mean_and_stddevs( sx, rx, dx, imt.SA(period1), stddev_types) gmpeCYstd[i, ii] = g[0][0] sx.vs30measured = [0] gmpeASKdata[i, ii], g = gmpeASK.get_mean_and_stddevs( sx, rx, dx, imt.SA(period1), stddev_types) gmpeASKstd[i, ii] = g[0][0] model_avg = np.log(9.81 * np.exp( np.mean([gmpeBSSAdata, gmpeCBdata, gmpeCYdata, gmpeASKdata], axis=0))) #outputs ln m/s2 return model_avg
def oq_run( model: Enum, tect_type: Enum, rupture_df: pd.DataFrame, im: str, periods: Sequence[Union[int, float]] = None, **kwargs, ): """Run an openquake model with dataframe model: Enum OQ model name tect_type: Enum One of the tectonic types from ACTIVE_SHALLOW, SUBDUCTION_SLAB and SUBDUCTION_INTERFACE rupture_df: Rupture DF Columns for properties. E.g., vs30, z1pt0, rrup, rjb, mag, rake, dip.... Rows be the separate site-fault pairs But Site information must be identical across the rows, only the faults can be different. im: string intensity measure periods: Sequence[Union[int, float]] for spectral acceleration, openquake tables automatically interpolate values between specified values, fails if outside range kwargs: pass extra (model specific) parameters to models """ model = (OQ_MODELS[model][tect_type]( **kwargs) if not model.name.endswith("_NZ") else OQ_MODELS[model][tect_type](region="NZL", **kwargs)) # Check the given tect_type with its model's tect type trt = model.DEFINED_FOR_TECTONIC_REGION_TYPE if trt == const.TRT.SUBDUCTION_INTERFACE: assert tect_type == TectType.SUBDUCTION_INTERFACE elif trt == const.TRT.SUBDUCTION_INTRASLAB: assert tect_type == TectType.SUBDUCTION_SLAB elif trt == const.TRT.ACTIVE_SHALLOW_CRUST: assert tect_type == TectType.ACTIVE_SHALLOW else: raise ValueError("unknown tectonic region: " + trt) stddev_types = [ std for std in SPT_STD_DEVS if std in model.DEFINED_FOR_STANDARD_DEVIATION_TYPES ] # Make a copy in case the original rupture_df used with other functions rupture_df = rupture_df.copy() # Check if df contains what model requires rupture_ctx_properties = set(rupture_df.columns.values) extra_site_parameters = set( model.REQUIRES_SITES_PARAMETERS).difference(rupture_ctx_properties) if len(extra_site_parameters) > 0: raise ValueError("unknown site property: " + extra_site_parameters) extra_rup_properties = set( model.REQUIRES_RUPTURE_PARAMETERS).difference(rupture_ctx_properties) if len(extra_rup_properties) > 0: raise ValueError("unknown rupture property: " + " ".join(extra_rup_properties)) extra_dist_properties = set( model.REQUIRES_DISTANCES).difference(rupture_ctx_properties) if len(extra_dist_properties) > 0: raise ValueError("unknown distance property: " + " ".join(extra_dist_properties)) # Convert z1pt0 from km to m rupture_df["z1pt0"] *= 1000 # OQ's single new-style context which contains all site, distance and rupture's information rupture_ctx = contexts.RuptureContext( tuple([ # Openquake requiring occurrence_rate attribute to exist ("occurrence_rate", None), # sids is the number of sites provided (OQ term) # This term needs to be repeated for the number of rows in the df ("sids", [1] * rupture_df.shape[0]), *(( column, rupture_df.loc[:, column].values, ) for column in rupture_df.columns.values), ])) if periods is not None: assert imt.SA in model.DEFINED_FOR_INTENSITY_MEASURE_TYPES # use sorted instead of max for full list avail_periods = np.asarray([ im.period for im in (model.COEFFS.sa_coeffs.keys() if not isinstance( model, ( gsim.zhao_2006.ZhaoEtAl2006Asc, gsim.zhao_2006.ZhaoEtAl2006SSlab, gsim.zhao_2006.ZhaoEtAl2006SInter, ), ) else model.COEFFS_ASC.sa_coeffs.keys()) ]) max_period = max(avail_periods) if not hasattr(periods, "__len__"): periods = [periods] results = [] for period in periods: im = imt.SA(period=min(period, max_period)) try: result = oq_mean_stddevs(model, rupture_ctx, im, stddev_types) except KeyError as ke: cause = ke.args[0] # To make sure the KeyError is about missing pSA's period if (isinstance(cause, imt.IMT) and str(cause).startswith("SA") and cause.period > 0.0): # Period is smaller than model's supported min_period E.g., ZA_06 # Interpolate between PGA(0.0) and model's min_period low_result = oq_mean_stddevs(model, rupture_ctx, imt.PGA(), stddev_types) high_period = avail_periods[period <= avail_periods][0] high_result = oq_mean_stddevs(model, rupture_ctx, imt.SA(period=high_period), stddev_types) result = interpolate_with_pga(period, high_period, low_result, high_result) else: # KeyError that we cannot handle logging.exception(ke) raise except Exception as e: # Any other exceptions that we cannot handle logging.exception(e) raise # extrapolate pSA value up based on maximum available period if period > max_period: result.loc[:, result.columns.str.endswith("mean")] += 2 * np.log( max_period / period) # Updating the period from max_period to the given period # E.g with ZA_06, replace 5.0 to period > 5.0 result.columns = result.columns.str.replace(str(max_period), str(period), regex=False) results.append(result) return pd.concat(results, axis=1) else: imc = getattr(imt, im) assert imc in model.DEFINED_FOR_INTENSITY_MEASURE_TYPES return oq_mean_stddevs(model, rupture_ctx, imc(), stddev_types)
def oq_run(model, site, fault, im, period=None, **kwargs): """ Run an openquake model using Empirical_Engine input structures. model: model or value from empirical.util.classdef.GMM or openquake class: GMM.P_20 gsim.parker_2020.ParkerEtAl2020SInter site / fault: instances from empirical.classdef -- A tect_type must be able to be set to retrieve the correct model im: intensity measure name period: for spectral acceleration, openquake tables automatically interpolate values between specified values, fails if outside range kwargs: pass extra (model specific) parameters to models """ if not OQ: raise ImportError("openquake is not installed, models not available") # model can be given multiple ways if type(model).__name__ == "GMM": model = oq_models[model][fault.tect_type](**kwargs) elif type(model).__name__ == "MetaGSIM": model = model(**kwargs) trt = model.DEFINED_FOR_TECTONIC_REGION_TYPE if trt == const.TRT.SUBDUCTION_INTERFACE: assert fault.tect_type == TectType.SUBDUCTION_INTERFACE elif trt == const.TRT.SUBDUCTION_INTRASLAB: assert fault.tect_type == TectType.SUBDUCTION_SLAB elif trt == const.TRT.ACTIVE_SHALLOW_CRUST: assert fault.tect_type == TectType.ACTIVE_SHALLOW else: raise ValueError("unknown tectonic region: " + trt) stddev_types = [] for st in [ const.StdDev.TOTAL, const.StdDev.INTER_EVENT, const.StdDev.INTRA_EVENT ]: if st in model.DEFINED_FOR_STANDARD_DEVIATION_TYPES: stddev_types.append(st) location = Point( 0.0, 0.0, 0.0 ) # Create a dummy location as OQ calculation doesn't use a location oq_site = Site(location) extra_site_parameters = set(model.REQUIRES_SITES_PARAMETERS).difference( list(zip(*SITE_PROPERTIES))[0]) if len(extra_site_parameters) > 0: raise ValueError("unknown site property: " + extra_site_parameters) oq_site = check_properties( site, model, model.REQUIRES_SITES_PARAMETERS, SITE_PROPERTIES, oq_site, np_array=True, ) if hasattr(oq_site, "z1pt0"): oq_site.z1pt0 *= 1000 sites = SiteCollection([oq_site]) extra_rup_properties = set(model.REQUIRES_RUPTURE_PARAMETERS).difference( list(zip(*RUPTURE_PROPERTIES))[0]) if len(extra_rup_properties) > 0: raise ValueError("unknown rupture property: " + " ".join(extra_rup_properties)) rupture = check_properties( fault, model, model.REQUIRES_RUPTURE_PARAMETERS, RUPTURE_PROPERTIES, Properties(), ) # Openquake requiring occurrence_rate attribute to exist rupture.occurrence_rate = None extra_dist_properties = set(model.REQUIRES_DISTANCES).difference( list(zip(*DISTANCE_PROPERTIES))[0]) if len(extra_dist_properties) > 0: raise ValueError("unknown distance property: " + " ".join(extra_dist_properties)) dists = check_properties( site, model, model.REQUIRES_DISTANCES, DISTANCE_PROPERTIES, Properties(), np_array=True, ) if period is not None: assert imt.SA in model.DEFINED_FOR_INTENSITY_MEASURE_TYPES # use sorted instead of max for full list max_period = max([i.period for i in model.COEFFS.sa_coeffs.keys()]) single = False if not hasattr(period, "__len__"): single = True period = [period] results = [] for p in period: imr = imt.SA(period=min(p, max_period)) m, s = oq_mean_stddevs(model, sites, rupture, dists, imr, stddev_types) # interpolate pSA value up based on maximum available period if p > max_period: m = m * (max_period / p)**2 results.append((m, s)) if single: return results[0] return results else: imc = getattr(imt, im) assert imc in model.DEFINED_FOR_INTENSITY_MEASURE_TYPES return oq_mean_stddevs(model, sites, rupture, dists, imc(), stddev_types)
def compute_cs(t_cs, bgmpe, sctx, rctx, dctx, im_type, t_star, rrup, mag, avg_periods, corr_type, im_star, gmpe_input): """ Compute the conditional spectrum according to the procedure outlined in Baker JW, Lee C. An Improved Algorithm for Selecting Ground Motions to Match a Conditional Spectrum. J Earthq Eng 2018;22:708-23. https://doi.org/10.1080/13632469.2016.1264334. When the IM and the GMM are defined for the maximum of the two horizontal components, the The Boore and Kishida (2017) relationship is applied to convert the maximum of the two horizontal components into `RotD50`. This is done only for `PGA` and `SA`. """ import numpy as np import sys from openquake.hazardlib import imt, const, gsim from .compute_avgSA import compute_rho_avgsa from .modified_akkar_correlation_model import ModifiedAkkarCorrelationModel # Use the same periods as the available spectra to construct the # conditional spectrum p = [] s = [const.StdDev.TOTAL] if im_type == 'AvgSA': _ = gsim.get_available_gsims() p = imt.AvgSA() mgmpe = gsim.mgmpe.generic_gmpe_avgsa.GenericGmpeAvgSA \ (gmpe_name=gmpe_input, avg_periods=avg_periods, corr_func=corr_type) mu_im_cond, sigma_im_cond = mgmpe.get_mean_and_stddevs( sctx, rctx, dctx, p, s) else: if im_type == 'PGA': p = imt.PGA() else: p = imt.SA(t_star) s = [const.StdDev.TOTAL] mu_im_cond, sigma_im_cond = bgmpe().get_mean_and_stddevs( sctx, rctx, dctx, p, s) sigma_im_cond = sigma_im_cond[0] if (bgmpe.DEFINED_FOR_INTENSITY_MEASURE_COMPONENT == 'Greater of two horizontal'): if im_type == 'PGA' or im_type == 'SA': from shakelib.conversions.imc.boore_kishida_2017 import \ BooreKishida2017 bk17 = BooreKishida2017(const.IMC.GREATER_OF_TWO_HORIZONTAL, const.IMC.RotD50) mu_im_cond = bk17.convertAmps(p, mu_im_cond, rrup, float(mag)) sigma_im_cond = bk17.convertSigmas(p, sigma_im_cond[0]) else: sys.exit('Error: conversion between intensity measures is not ' 'possible for AvgSA') # Compute how many standard deviations the PSHA differs from # the GMPE value epsilon = (np.log(im_star) - mu_im_cond) / sigma_im_cond mu_im = np.zeros(len(t_cs)) sigma_im = np.zeros(len(t_cs)) rho_t_tstar = np.zeros(len(t_cs)) mu_im_im_cond = np.zeros(len(t_cs)) for i in range(len(t_cs)): # Get the GMPE ouput for a rupture scenario if t_cs[i] == 0.: p = imt.PGA() else: p = imt.SA(t_cs[i]) s = [const.StdDev.TOTAL] mu0, sigma0 = bgmpe().get_mean_and_stddevs(sctx, rctx, dctx, p, s) if (bgmpe.DEFINED_FOR_INTENSITY_MEASURE_COMPONENT == 'Greater of two horizontal'): if im_type == 'PGA' or im_type == 'SA': from shakelib.conversions.imc.boore_kishida_2017 \ import BooreKishida2017 bk17 = BooreKishida2017(const.IMC.GREATER_OF_TWO_HORIZONTAL, const.IMC.RotD50) mu0 = bk17.convertAmps(p, mu0, rrup, float(mag)) sigma0 = bk17.convertSigmas(p, sigma0[0]) mu_im[i] = mu0[0] sigma_im[i] = sigma0[0][0] rho = None if im_type == 'AvgSA': rho = compute_rho_avgsa(t_cs[i], avg_periods, sctx, rctx, dctx, sigma_im_cond, bgmpe, corr_type) rho = rho[0] else: if corr_type == 'baker_jayaram': rho = gsim.mgmpe.generic_gmpe_avgsa. \ BakerJayaramCorrelationModel([t_cs[i], t_star])(0, 1) if corr_type == 'akkar': rho = ModifiedAkkarCorrelationModel([t_cs[i], t_star])(0, 1) rho_t_tstar[i] = rho # Get the value of the CMS mu_im_im_cond[i] = \ mu_im[i] + rho_t_tstar[i] * epsilon[0] * sigma_im[i] # Compute covariances and correlations at all periods cov = np.zeros((len(t_cs), len(t_cs))) for i in np.arange(len(t_cs)): for j in np.arange(len(t_cs)): var1 = sigma_im[i]**2 var2 = sigma_im[j]**2 var_tstar = sigma_im_cond**2 sigma_corr = [] if corr_type == 'baker_jayaram': sigma_corr = gsim.mgmpe.generic_gmpe_avgsa. \ BakerJayaramCorrelationModel([t_cs[i], t_cs[j]])(0, 1) * \ np.sqrt(var1 * var2) if corr_type == 'akkar': sigma_corr = ModifiedAkkarCorrelationModel([t_cs[i], t_cs[j]])(0, 1) * \ np.sqrt(var1 * var2) sigma11 = np.matrix([[var1, sigma_corr], [sigma_corr, var2]]) sigma22 = np.array(var_tstar) sigma12 = np.array([ rho_t_tstar[i] * np.sqrt(var1 * var_tstar), rho_t_tstar[j] * np.sqrt(var_tstar * var2) ]) sigma_cond = sigma11 - sigma12 * 1. / (sigma22) * sigma12.T cov[i, j] = sigma_cond[0, 1] # find covariance values of zero and set them to a small number # so that random number generation can be performed cov[np.absolute(cov) < 1e-10] = 1e-10 stdevs = np.sqrt(np.diagonal(cov)) return mu_im_im_cond, cov, stdevs
def test_pickeable(self): for imt in (imt_module.PGA(), imt_module.SA(0.2)): imt_pik = pickle.dumps(imt, pickle.HIGHEST_PROTOCOL) self.assertEqual(pickle.loads(imt_pik), imt)
def _get_extent_from_multigmpe(rupture, config=None): """ Use MultiGMPE to determine extent """ (clon, clat) = _rupture_center(rupture) origin = rupture.getOrigin() if config is not None: gmpe = MultiGMPE.from_config(config) gmice = get_object_from_config('gmice', 'modeling', config) if imt.SA in gmice.DEFINED_FOR_INTENSITY_MEASURE_TYPES: default_imt = imt.SA(1.0) elif imt.PGV in gmice.DEFINED_FOR_INTENSITY_MEASURE_TYPES: default_imt = imt.PGV() else: default_imt = imt.PGA() else: # Put in some default values for conf config = { 'extent': { 'mmi': { 'threshold': 4.5, 'mindist': 100, 'maxdist': 1000 } } } # Generic GMPEs choices based only on active vs stable # as defaults... stable = is_stable(origin.lon, origin.lat) if not stable: ASK14 = AbrahamsonEtAl2014() CB14 = CampbellBozorgnia2014() CY14 = ChiouYoungs2014() gmpes = [ASK14, CB14, CY14] site_gmpes = None weights = [1/3.0, 1/3.0, 1/3.0] gmice = WGRW12() else: Fea96 = FrankelEtAl1996MwNSHMP2008() Tea97 = ToroEtAl1997MwNSHMP2008() Sea02 = SilvaEtAl2002MwNSHMP2008() C03 = Campbell2003MwNSHMP2008() TP05 = TavakoliPezeshk2005MwNSHMP2008() AB06p = AtkinsonBoore2006Modified2011() Pea11 = PezeshkEtAl2011() Atk08p = Atkinson2008prime() Sea01 = SomervilleEtAl2001NSHMP2008() gmpes = [Fea96, Tea97, Sea02, C03, TP05, AB06p, Pea11, Atk08p, Sea01] site_gmpes = [AB06p] weights = [0.16, 0.0, 0.0, 0.17, 0.17, 0.3, 0.2, 0.0, 0.0] gmice = AK07() gmpe = MultiGMPE.from_list( gmpes, weights, default_gmpes_for_site=site_gmpes) default_imt = imt.SA(1.0) min_mmi = config['extent']['mmi']['threshold'] sd_types = [const.StdDev.TOTAL] # Distance context dx = DistancesContext() # This imposes minimum/ maximum distances of: # 80 and 800 km; could make this configurable d_min = config['extent']['mmi']['mindist'] d_max = config['extent']['mmi']['maxdist'] dx.rjb = np.logspace(np.log10(d_min), np.log10(d_max), 2000) # Details don't matter for this; assuming vertical surface rupturing fault # with epicenter at the surface. dx.rrup = dx.rjb dx.rhypo = dx.rjb dx.repi = dx.rjb dx.rx = np.zeros_like(dx.rjb) dx.ry0 = np.zeros_like(dx.rjb) dx.rvolc = np.zeros_like(dx.rjb) # Sites context sx = SitesContext() # Set to soft soil conditions sx.vs30 = np.full_like(dx.rjb, 180) sx = MultiGMPE.set_sites_depth_parameters(sx, gmpe) sx.vs30measured = np.full_like(sx.vs30, False, dtype=bool) sx = Sites._addDepthParameters(sx) sx.backarc = np.full_like(sx.vs30, False, dtype=bool) # Rupture context rx = RuptureContext() rx.mag = origin.mag rx.rake = 0.0 # From WC94... rx.width = 10**(-0.76 + 0.27*rx.mag) rx.dip = 90.0 rx.ztor = origin.depth rx.hypo_depth = origin.depth gmpe_imt_mean, _ = gmpe.get_mean_and_stddevs( sx, rx, dx, default_imt, sd_types) # Convert to MMI gmpe_to_mmi, _ = gmice.getMIfromGM(gmpe_imt_mean, default_imt) # Minimum distance that exceeds threshold MMI? dists_exceed_mmi = dx.rjb[gmpe_to_mmi > min_mmi] if len(dists_exceed_mmi): mindist_km = np.max(dists_exceed_mmi) else: mindist_km = d_min # Get a projection proj = OrthographicProjection(clon - 4, clon + 4, clat + 4, clat - 4) if isinstance(rupture, (QuadRupture, EdgeRupture)): ruptx, rupty = proj( rupture.lons[~np.isnan(rupture.lons)], rupture.lats[~np.isnan(rupture.lats)] ) else: ruptx, rupty = proj(clon, clat) xmin = np.nanmin(ruptx) - mindist_km ymin = np.nanmin(rupty) - mindist_km xmax = np.nanmax(ruptx) + mindist_km ymax = np.nanmax(rupty) + mindist_km # Put a limit on range of aspect ratio dx = xmax - xmin dy = ymax - ymin ar = dy / dx if ar > 1.2: # Inflate x dx_target = dy / 1.2 ddx = dx_target - dx xmax = xmax + ddx / 2 xmin = xmin - ddx / 2 if ar < 0.83: # Inflate y dy_target = dx * 0.83 ddy = dy_target - dy ymax = ymax + ddy / 2 ymin = ymin - ddy / 2 lonmin, latmin = proj(np.array([xmin]), np.array([ymin]), reverse=True) lonmax, latmax = proj(np.array([xmax]), np.array([ymax]), reverse=True) # # Round coordinates to the nearest minute -- that should make the # output grid register with common grid resolutions (60c, 30c, # 15c, 7.5c) # logging.debug("Extent: %f, %f, %f, %f" % (lonmin, lonmax, latmin, latmax)) return _round_coord(lonmin[0]), _round_coord(lonmax[0]), \ _round_coord(latmin[0]), _round_coord(latmax[0])
from shakelib.gmpe.nga_east import NGAEast home_dir = os.path.dirname(os.path.abspath(__file__)) data_dir = os.path.join(home_dir, 'nga_east_data') stddev_types = [StdDev.TOTAL] gmpe = NGAEast() dx = base.DistancesContext() dx.rrup = np.logspace(-1, np.log10(2000), 100) rx = base.RuptureContext() sx = base.SitesContext() IMTS = [imt.PGA(), imt.PGV(), imt.SA(0.3), imt.SA(1.0), imt.SA(3.0)] MAGS = [3, 5, 6, 7] VS30 = [180, 380, 760, 2000] def update_results(): # To build the data for testing result = {} for i in IMTS: ikey = i.__str__() result[ikey] = {} for mag in MAGS: rx.mag = mag result[ikey][str(mag)] = {}
def test_scr_rlme(): old_gmpe = set_gmpe('stable_continental_nshmp2014_rlme') spec_file = pkg_resources.resource_filename( 'scenarios', os.path.join('data', 'configspec.conf')) validator = get_custom_validator() config = ConfigObj(os.path.join(os.path.expanduser('~'), 'scenarios.conf'), configspec=spec_file) tmp = pkg_resources.resource_filename( 'scenarios', os.path.join('..', 'data', 'gmpe_sets.conf')) config.merge(ConfigObj(tmp, configspec=spec_file)) tmp = pkg_resources.resource_filename( 'scenarios', os.path.join('..', 'data', 'modules.conf')) config.merge(ConfigObj(tmp, configspec=spec_file)) results = config.validate(validator) if results != True: config_error(config, results) # MultiGMPE from config config = config.dict() gmpe = MultiGMPE.from_config(config) # Input stuff IMT = imt.SA(1.0) rctx = RuptureContext() dctx = DistancesContext() sctx = SitesContext() rctx.rake = 0.0 rctx.dip = 90.0 rctx.ztor = 0.0 rctx.mag = 8.0 rctx.width = 10.0 rctx.hypo_depth = 8.0 dctx.rjb = np.logspace(1, np.log10(800), 100) dctx.rrup = dctx.rjb dctx.rhypo = dctx.rjb dctx.rx = dctx.rjb dctx.ry0 = dctx.rjb sctx.vs30 = np.ones_like(dctx.rjb) * 275.0 sctx.vs30measured = np.full_like(dctx.rjb, False, dtype='bool') sctx = MultiGMPE.set_sites_depth_parameters(sctx, gmpe) # Evaluate conf_lmean, dummy = gmpe.get_mean_and_stddevs(sctx, rctx, dctx, IMT, [const.StdDev.TOTAL]) target_lmean = np.array([ 0.10556736, 0.0839267, 0.06189444, 0.03945984, 0.01661264, -0.006657, -0.03035844, -0.05450058, -0.07909179, -0.10413995, -0.1296524, -0.15563655, -0.1821091, -0.20909381, -0.23661405, -0.26469259, -0.29335086, -0.32257956, -0.35232905, -0.38254639, -0.41317807, -0.44417017, -0.47549552, -0.5071888, -0.53929293, -0.57185042, -0.60490345, -0.63848027, -0.67255251, -0.70707712, -0.74201096, -0.77731091, -0.81293906, -0.84889737, -0.88520644, -0.92188724, -0.95899471, -0.99699613, -1.03583184, -1.07530664, -1.11531737, -1.15576129, -1.19653696, -1.23757689, -1.2772327, -1.2915098, -1.30576498, -1.32001713, -1.33429606, -1.3486727, -1.36322545, -1.37803346, -1.39317668, -1.40677752, -1.42081409, -1.43538898, -1.45056417, -1.46640223, -1.48327111, -1.50656497, -1.53368548, -1.56645985, -1.59991327, -1.63399401, -1.66867278, -1.7039438, -1.73980246, -1.77624473, -1.81326727, -1.85087166, -1.889066, -1.92784814, -1.96721442, -2.0071855, -2.04779304, -2.08909259, -2.13114448, -2.17401045, -2.21775376, -2.26243406, -2.30808979, -2.35475487, -2.40246494, -2.4512575, -2.50117075, -2.55223495, -2.60447754, -2.65792811, -2.71261851, -2.61732716, -2.67007323, -2.72399057, -2.77918054, -2.83574666, -2.89379416, -2.95340501, -3.01462691, -3.07750731, -3.14209631, -3.20844679 ]) np.testing.assert_allclose(conf_lmean, target_lmean, atol=1e-6) # Redo for 3 sec so some GMPEs are filtered out IMT = imt.SA(3.0) gmpe = MultiGMPE.from_config(config, filter_imt=IMT) conf_lmean, dummy = gmpe.get_mean_and_stddevs(sctx, rctx, dctx, IMT, [const.StdDev.TOTAL]) target_lmean = np.array([ -1.26636973, -1.289514, -1.31300386, -1.33683936, -1.36102084, -1.38554902, -1.41042497, -1.43565015, -1.46122642, -1.48715602, -1.51344154, -1.54008586, -1.56709215, -1.59446375, -1.62220409, -1.65031664, -1.6788048, -1.70767178, -1.7369205, -1.76655351, -1.79657287, -1.82698005, -1.85777587, -1.88896039, -1.92053288, -1.95249175, -1.98483453, -2.01755788, -2.05065755, -2.08412844, -2.11796463, -2.15215943, -2.18670547, -2.22159473, -2.25681869, -2.29236835, -2.32823441, -2.36453464, -2.40140834, -2.43883442, -2.47679132, -2.51525752, -2.55421156, -2.59363211, -2.63112832, -2.63336521, -2.63582817, -2.6385319, -2.64147962, -2.64466761, -2.64809268, -2.65175214, -2.6556438, -2.65976592, -2.66411721, -2.66869673, -2.67350386, -2.67853821, -2.68413311, -2.69604497, -2.7124745, -2.73590549, -2.75964098, -2.78367044, -2.80798539, -2.8325853, -2.85746998, -2.88263948, -2.90809408, -2.93383429, -2.95986073, -2.98617306, -3.01275705, -3.03961495, -3.06675608, -3.09419043, -3.12192861, -3.14998191, -3.17836228, -3.20708239, -3.23615561, -3.26559604, -3.29541858, -3.32563888, -3.35627343, -3.38733956, -3.41885548, -3.4508403, -3.48331409, -3.56476842, -3.59987076, -3.63573296, -3.67238872, -3.70987332, -3.74822369, -3.78747847, -3.82767809, -3.86886488, -3.91108308, -3.95437899 ]) np.testing.assert_allclose(conf_lmean, target_lmean, atol=1e-6) # Clean up set_gmpe(old_gmpe)