#!/usr/bin/env python
import copy
from importlib import import_module
import numpy as np
from openquake.hazardlib.gsim.base import GMPE
from openquake.hazardlib.imt import PGA, PGV, SA
from openquake.hazardlib import const
from shakelib.conversions.imt.newmark_hall_1982 import NewmarkHall1982
from shakelib.conversions.imc.beyer_bommer_2006 import BeyerBommer2006
from shakelib.sites import Sites
[docs]class MultiGMPE(GMPE):
"""
Implements a GMPE that is the combination of multiple GMPEs.
To do
* Allow site to be based on a model that isn't a GMPE (e.g.,
Borcherdt).
"""
DEFINED_FOR_TECTONIC_REGION_TYPE = None
DEFINED_FOR_INTENSITY_MEASURE_TYPES = None
DEFINED_FOR_INTENSITY_MEASURE_COMPONENT = None
DEFINED_FOR_STANDARD_DEVIATION_TYPES = None
REQUIRES_SITES_PARAMETERS = None
REQUIRES_RUPTURE_PARAMETERS = None
REQUIRES_DISTANCES = None
[docs] def get_mean_and_stddevs(self, sites, rup, dists, imt, stddev_types):
"""
See superclass `method <http://docs.openquake.org/oq-hazardlib/master/gsim/index.html#openquake.hazardlib.gsim.base.GroundShakingIntensityModel.get_mean_and_stddevs>`__.
""" # noqa
# Evaluate MultiGMPE:
lnmu, lnsd = self.__get_mean_and_stddevs(
sites, rup, dists, imt, stddev_types)
# Check for large-distance cutoff/weights
if hasattr(self, 'CUTOFF_DISTANCE'):
lnmu_large, lnsd_large = self.__get_mean_and_stddevs(
sites, rup, dists, imt, stddev_types, large_dist=True)
# Stomp on lnmu and lnsd at large distances
dist_cutoff = self.CUTOFF_DISTANCE
lnmu[dists.rjb > dist_cutoff] = lnmu_large[dists.rjb > dist_cutoff]
for i in range(len(lnsd)):
lnsd[i][dists.rjb > dist_cutoff] = \
lnsd_large[i][dists.rjb > dist_cutoff]
return lnmu, lnsd
def __get_mean_and_stddevs(self, sites, rup, dists, imt, stddev_types,
large_dist=False):
# ---------------------------------------------------------------------
# Sort out which set of weights to use
# ---------------------------------------------------------------------
if large_dist is False:
wts = self.WEIGHTS
else:
wts = self.WEIGHTS_LARGE_DISTANCE
# ---------------------------------------------------------------------
# Sort out shapes of sites and dists elements
# ---------------------------------------------------------------------
shapes = []
for k, v in sites.__dict__.items():
if (k is not 'lons') and (k is not 'lats'):
shapes.append(v.shape)
for k, v in dists.__dict__.items():
if (k is not 'lons') and (k is not 'lats'):
shapes.append(v.shape)
shapeset = set(shapes)
if len(shapeset) != 1:
raise Exception(
'All sites and dists elements must have same shape.')
else:
orig_shape = list(shapeset)[0]
# Need to turn all 2D arrays into 1D arrays because of
# inconsistencies in how arrays are handled in OpenQuake.
for k, v in dists.__dict__.items():
if (k is not 'lons') and (k is not 'lats'):
dists.__dict__[k] = np.reshape(dists.__dict__[k], (-1,))
for k, v in sites.__dict__.items():
if (k is not 'lons') and (k is not 'lats'):
sites.__dict__[k] = np.reshape(sites.__dict__[k], (-1,))
# ---------------------------------------------------------------------
# These are arrays to hold the weighted combination of the GMPEs
# ---------------------------------------------------------------------
lnmu = np.zeros_like(sites.vs30)
sd_avail = self.DEFINED_FOR_STANDARD_DEVIATION_TYPES
if not sd_avail.issuperset(set(stddev_types)):
raise Exception("Requested an unavailable stddev_type.")
lnsd2 = [np.zeros_like(sites.vs30) for a in stddev_types]
for i in range(len(self.GMPES)):
# -----------------------------------------------------------------
# Loop over GMPE list
# -----------------------------------------------------------------
gmpe = self.GMPES[i]
sites = MultiGMPE.set_sites_depth_parameters(sites, gmpe)
# -----------------------------------------------------------------
# Evaluate GMPEs
# -----------------------------------------------------------------
gmpe_imts = [imt.__name__ for imt in
gmpe.DEFINED_FOR_INTENSITY_MEASURE_TYPES]
if (isinstance(imt, PGV)) and ("PGV" not in gmpe_imts):
# -------------------------------------------------------------
# If IMT is PGV and PGV is not given by the GMPE, then
# convert from PSA10.
# -------------------------------------------------------------
if self.HAS_SITE[i] is True:
psa10, psa10sd = gmpe.get_mean_and_stddevs(
sites, rup, dists, SA(1.0), stddev_types)
else:
lamps = self.get_site_factors(
sites, rup, dists, SA(1.0), default=True)
psa10, psa10sd = gmpe.get_mean_and_stddevs(
sites, rup, dists, SA(1.0), stddev_types)
psa10 = psa10 + lamps
lmean, lsd = NewmarkHall1982.psa102pgv(psa10, psa10sd[0])
else:
if self.HAS_SITE[i] is True:
lmean, lsd = gmpe.get_mean_and_stddevs(
sites, rup, dists, imt, stddev_types)
else:
lamps = self.get_site_factors(
sites, rup, dists, imt, default=True)
lmean, lsd = gmpe.get_mean_and_stddevs(
sites, rup, dists, imt, stddev_types)
lmean = lmean + lamps
# -----------------------------------------------------------------
# Convertions due to component definition
# -----------------------------------------------------------------
imc_in = gmpe.DEFINED_FOR_INTENSITY_MEASURE_COMPONENT
imc_out = self.DEFINED_FOR_INTENSITY_MEASURE_COMPONENT
lmean = BeyerBommer2006.ampIMCtoIMC(lmean, imc_in, imc_out, imt)
for j in range(len(lnsd2)):
lsd[j] = BeyerBommer2006.sigmaIMCtoIMC(
lsd[j], imc_in, imc_out, imt)
# -----------------------------------------------------------------
# Compute weighted mean and sd
# -----------------------------------------------------------------
lnmu = lnmu + wts[i] * lmean
# Note: the lnsd2 calculation isn't complete until we drop out of
# this loop and substract lnmu**2
for j in range(len(lnsd2)):
lnsd2[j] = lnsd2[j] + wts[i] * (lmean**2 + lsd[j]**2)
for j in range(len(lnsd2)):
lnsd2[j] = lnsd2[j] - lnmu**2
lnsd = [np.sqrt(a) for a in lnsd2]
# Undo reshapes of inputs
for k, v in dists.__dict__.items():
if (k is not 'lons') and (k is not 'lats'):
dists.__dict__[k] = np.reshape(dists.__dict__[k], orig_shape)
for k, v in sites.__dict__.items():
if (k is not 'lons') and (k is not 'lats'):
sites.__dict__[k] = np.reshape(sites.__dict__[k], orig_shape)
# Reshape output
lnmu = np.reshape(lnmu, orig_shape)
for i in range(len(lnsd)):
lnsd[i] = np.reshape(lnsd[i], orig_shape)
return lnmu, lnsd
[docs] @classmethod
def from_config(cls, conf, filter_imt=None, verbose=False):
"""
Construct a MultiGMPE from a config file.
Args:
conf (dict): Dictionary of config options.
filter_imt (IMT): An optional IMT to filter/reweight the GMPE list.
verbose (bool): Print verbose output for debugging.
Returns:
MultiGMPE object.
"""
IMC = conf['component_modules'][conf['interp']['component']]
selected_gmpe = conf['modeling']['gmpe']
if verbose is True:
print('selected_gmpe: %s' % selected_gmpe)
print('IMC: %s' % IMC)
# ---------------------------------------------------------------------
# Allow for selected_gmpe to be found in either conf['gmpe_sets'] or
# conf['gmpe_modules'], if it is a GMPE set, then all entries must be
# either a GMPE or a GMPE set (cannot have a GMPE set that is a mix of
# GMPEs and GMPE sets).
# ---------------------------------------------------------------------
if selected_gmpe in conf['gmpe_sets'].keys():
selected_gmpe_sets = conf['gmpe_sets'][selected_gmpe]['gmpes']
gmpe_set_weights = \
[float(w) for w in conf['gmpe_sets'][selected_gmpe]['weights']]
if verbose is True:
print('selected_gmpe_sets: %s' % selected_gmpe_sets)
print('gmpe_set_weights: %s' % gmpe_set_weights)
# -----------------------------------------------------------------
# If it is a GMPE set, does it contain GMPEs or GMPE sets?
# -----------------------------------------------------------------
set_of_gmpes = all([s in conf['gmpe_modules'] for s in
selected_gmpe_sets])
set_of_sets = all([s in conf['gmpe_sets'] for s in
selected_gmpe_sets])
if set_of_sets is True:
mgmpes = []
for s in selected_gmpe_sets:
mgmpes.append(cls.__multigmpe_from_gmpe_set(
conf, s, filter_imt=filter_imt, verbose=verbose))
out = MultiGMPE.from_list(mgmpes, gmpe_set_weights, imc=IMC)
elif set_of_gmpes is True:
out = cls.__multigmpe_from_gmpe_set(
conf,
selected_gmpe,
filter_imt=filter_imt,
verbose=verbose)
else:
raise Exception("%s must consist exclusively of keys in "
"conf['gmpe_modules'] or conf['gmpe_sets']"
% selected_gmpe)
elif selected_gmpe in conf['gmpe_modules'].keys():
modinfo = conf['gmpe_modules'][selected_gmpe]
mod = import_module(modinfo[1])
tmpclass = getattr(mod, modinfo[0])
out = MultiGMPE.from_list([tmpclass()], [1.0], imc=IMC)
else:
raise Exception("conf['modeling']['gmpe'] must be a key in "
"conf['gmpe_modules'] or conf['gmpe_sets']")
out.DESCRIPTION = selected_gmpe
return out
def __multigmpe_from_gmpe_set(conf, set_name, filter_imt=None,
verbose=False):
"""
Private method for constructing a MultiGMPE from a set_name.
Args:
conf (ConfigObj): A ShakeMap config object.
filter_imt (IMT): An optional IMT to filter/reweight the GMPE list.
set_name (str): Set name; must correspond to a key in
conf['set_name'].
Returns:
MultiGMPE.
"""
IMC = conf['component_modules'][conf['interp']['component']]
selected_gmpes = conf['gmpe_sets'][set_name]['gmpes']
selected_gmpe_weights = \
[float(w) for w in conf['gmpe_sets'][set_name]['weights']]
# Check for large distance GMPEs
if 'weights_large_dist' in conf['gmpe_sets'][set_name].keys():
if not conf['gmpe_sets'][set_name]['weights_large_dist']:
selected_weights_large_dist = None
else:
selected_weights_large_dist = \
[float(w) for w in
conf['gmpe_sets'][set_name]['weights_large_dist']]
else:
selected_weights_large_dist = None
if 'dist_cutoff' in conf['gmpe_sets'][set_name].keys():
if np.isnan(conf['gmpe_sets'][set_name]['dist_cutoff']):
selected_dist_cutoff = None
else:
selected_dist_cutoff = \
float(conf['gmpe_sets'][set_name]['dist_cutoff'])
else:
selected_dist_cutoff = None
if 'site_gmpes' in conf['gmpe_sets'][set_name].keys():
if not conf['gmpe_sets'][set_name]['site_gmpes']:
selected_site_gmpes = None
else:
selected_site_gmpes = \
conf['gmpe_sets'][set_name]['site_gmpes']
else:
selected_site_gmpes = None
if 'weights_site_gmpes' in conf['gmpe_sets'][set_name].keys():
if not conf['gmpe_sets'][set_name]['weights_site_gmpes']:
selected_weights_site_gmpes = None
else:
selected_weights_site_gmpes = \
conf['gmpe_sets'][set_name]['weights_site_gmpes']
else:
selected_weights_site_gmpes = None
# ---------------------------------------------------------------------
# Import GMPE modules and initialize classes into list
# ---------------------------------------------------------------------
gmpes = []
for g in selected_gmpes:
mod = import_module(conf['gmpe_modules'][g][1])
tmpclass = getattr(mod, conf['gmpe_modules'][g][0])
gmpes.append(tmpclass())
# ---------------------------------------------------------------------
# Filter out GMPEs not applicable to this period
# ---------------------------------------------------------------------
if filter_imt is not None:
filtered_gmpes, filtered_wts = filter_gmpe_list(
gmpes, selected_gmpe_weights, filter_imt)
else:
filtered_gmpes, filtered_wts = gmpes, selected_gmpe_weights
# ---------------------------------------------------------------------
# Import site GMPEs
# ---------------------------------------------------------------------
if selected_site_gmpes is not None:
if isinstance(selected_site_gmpes, str):
selected_site_gmpes = [selected_site_gmpes]
site_gmpes = []
for g in selected_site_gmpes:
mod = import_module(conf['gmpe_modules'][g][1])
tmpclass = getattr(mod, conf['gmpe_modules'][g][0])
site_gmpes.append(tmpclass())
else:
site_gmpes = None
# ---------------------------------------------------------------------
# Filter out site GMPEs not applicable to this period
# ---------------------------------------------------------------------
if site_gmpes is not None:
if filter_imt is not None:
filtered_site_gmpes, filtered_site_wts = filter_gmpe_list(
site_gmpes, selected_weights_site_gmpes, filter_imt)
else:
filtered_site_gmpes = copy.copy(site_gmpes)
filtered_site_wts = copy.copy(selected_weights_site_gmpes)
else:
filtered_site_gmpes = None
filtered_site_wts = None
# ---------------------------------------------------------------------
# Construct MultiGMPE
# ---------------------------------------------------------------------
if verbose is True:
print(' filtered_gmpes: %s' % filtered_gmpes)
print(' filtered_wts: %s' % filtered_wts)
mgmpe = MultiGMPE.from_list(
filtered_gmpes, filtered_wts,
default_gmpes_for_site=filtered_site_gmpes,
default_gmpes_for_site_weights=filtered_site_wts,
imc=IMC)
# ---------------------------------------------------------------------
# Append large-distance info if specified
# ---------------------------------------------------------------------
if selected_dist_cutoff is not None:
if filter_imt is not None:
filtered_gmpes_ld, filtered_wts_ld = filter_gmpe_list(
gmpes, selected_weights_large_dist, filter_imt)
else:
filtered_wts_ld = copy.copy(selected_weights_large_dist)
mgmpe.CUTOFF_DISTANCE = copy.copy(selected_dist_cutoff)
mgmpe.WEIGHTS_LARGE_DISTANCE = copy.copy(filtered_wts_ld)
return mgmpe
[docs] @classmethod
def from_list(cls, gmpes, weights,
imc=const.IMC.GREATER_OF_TWO_HORIZONTAL,
default_gmpes_for_site=None,
default_gmpes_for_site_weights=None,
reference_vs30=760):
"""
Construct a MultiGMPE instance from lists of GMPEs and weights.
Args:
gmpes (list): List of OpenQuake
`GMPE <http://docs.openquake.org/oq-hazardlib/master/gsim/index.html#built-in-gsims>`__
instances.
weights (list): List of weights; must sum to 1.0.
imc: Requested intensity measure component. Must be one listed
`here <http://docs.openquake.org/oq-hazardlib/master/const.html?highlight=imc#openquake.hazardlib.const.IMC>`__.
The amplitudes returned by the GMPEs will be converted to this
IMT. Default is 'GREATER_OF_TWO_HORIZONTAL', which is used by
ShakeMap. See discussion in
`this section <http://usgs.github.io/shakemap/tg_choice_of_parameters.html#use-of-peak-values-rather-than-mean>`__
of the ShakeMap manual.
default_gmpes_for_site (list):
Optional list of OpenQuake GMPE instance to use as a site term
for any of the GMPEs that do not have a site term.
Notes:
* We do not check for consistency in the reference rock
defintion, so the user nees to be aware of this issue and
holds responsibiilty for ensuring compatibility.
* We check whether or not a GMPE has a site term by c
hecking the REQUIRES_SITES_PARAMETERS slot for vs30.
default_gmpes_for_site_weights: Weights for default_gmpes_for_site.
Must sum to one and be same length as default_gmpes_for_site.
If None, then weights are set to be equal.
reference_vs30:
Reference rock Vs30 in m/s. We do not check that this matches
the reference rock in the GMPEs so this is the responsibility
of the user.
""" # noqa
# ---------------------------------------------------------------------
# Check that GMPE weights sum to 1.0:
# ---------------------------------------------------------------------
if np.abs(np.sum(weights) - 1.0) > 1e-7:
raise Exception('Weights must sum to one.')
# ---------------------------------------------------------------------
# Check that length of GMPE weights equals length of gmpe list
# ---------------------------------------------------------------------
if len(weights) != len(gmpes):
raise Exception(
'Length of weights must match length of GMPE list.')
# ---------------------------------------------------------------------
# Check that gmpes is a list of OQ GMPE instances
# ---------------------------------------------------------------------
for g in gmpes:
if not isinstance(g, GMPE):
raise Exception("\"%s\" is not a GMPE instance." % g)
self = cls()
self.GMPES = gmpes
self.WEIGHTS = weights
# ---------------------------------------------------------------------
# Combine the intensity measure types. This is problematic:
# - Logically, we should only include the intersection of the sets
# of imts for the different GMPEs.
# - In practice, this is not feasible because most GMPEs in CEUS and
# subduction zones do not have PGV.
# - So instead we will use the union of the imts and then convert
# to get the missing imts later in get_mean_and_stddevs.
# ---------------------------------------------------------------------
imts = [g.DEFINED_FOR_INTENSITY_MEASURE_TYPES for g in gmpes]
self.DEFINED_FOR_INTENSITY_MEASURE_TYPES = set.union(*imts)
# ---------------------------------------------------------------------
# For VirtualIPE class, we also want to know if ALL of the GMPEs are
# defined for PGV, in which case we will convert from PGV to MI,
# otherwise use PGA or Sa.
# ---------------------------------------------------------------------
haspgv = [PGV in g.DEFINED_FOR_INTENSITY_MEASURE_TYPES for g in gmpes]
self.ALL_GMPES_HAVE_PGV = all(haspgv)
# ---------------------------------------------------------------------
# Store intensity measure types for conversion in get_mean_and_stddevs.
# ---------------------------------------------------------------------
self.IMCs = [g.DEFINED_FOR_INTENSITY_MEASURE_COMPONENT for g in gmpes]
# ---------------------------------------------------------------------
# Store the component
# ---------------------------------------------------------------------
self.DEFINED_FOR_INTENSITY_MEASURE_COMPONENT = imc
# ---------------------------------------------------------------------
# Intersection of GMPE standard deviation types
# ---------------------------------------------------------------------
stdlist = [set(g.DEFINED_FOR_STANDARD_DEVIATION_TYPES) for g in gmpes]
self.DEFINED_FOR_STANDARD_DEVIATION_TYPES = \
set.intersection(*stdlist)
# ---------------------------------------------------------------------
# Need union of site parameters, but it is complicated by the
# different depth parameter flavors.
# ---------------------------------------------------------------------
sitepars = [g.REQUIRES_SITES_PARAMETERS for g in gmpes]
self.REQUIRES_SITES_PARAMETERS = set.union(*sitepars)
# ---------------------------------------------------------------------
# Construct a list of whether or not each GMPE has a site term
# ---------------------------------------------------------------------
self.HAS_SITE = ['vs30' in g.REQUIRES_SITES_PARAMETERS for g in gmpes]
# ---------------------------------------------------------------------
# Checks and sort out defaults
# ---------------------------------------------------------------------
# things to check if default_gmpes_for_site is provided
if default_gmpes_for_site is not None:
# check that default_gmpe_for_site are OQ GMPEs or None
for g in default_gmpes_for_site:
if not isinstance(g, GMPE):
raise Exception("\"%s\" is not a GMPE instance." % g)
# apply default weights if necessary
if default_gmpes_for_site_weights is None:
n = len(default_gmpes_for_site)
default_gmpes_for_site_weights = [1 / n] * n
# Things to check if one or more GMPE does not have a site term
if not all(self.HAS_SITE):
# Raise an exception if no default site is provided
if default_gmpes_for_site is None:
raise Exception('Must provide default_gmpes_for_site if one or'
' more GMPE does not have site term.')
# If weights are unspecified, use equal weight
if default_gmpes_for_site_weights is None:
default_gmpes_for_site_weights = \
[1 / len(default_gmpes_for_site)] * \
len(default_gmpes_for_site)
# check that length of default_gmpe_for_site matches length of
# default_gmpe_for_site_weights
if len(default_gmpes_for_site_weights) != \
len(default_gmpes_for_site):
raise Exception('Length of default_gmpes_for_site_weights '
'must match length of default_gmpes_for_site '
'list.')
# check weights sum to one if needed
if not all(self.HAS_SITE):
if np.sum(default_gmpes_for_site_weights) != 1.0:
raise Exception('default_gmpes_for_site_weights must sum'
' to one.')
# Note: if ALL of the GMPEs do not have a site term (requiring Vs30),
# then REQUIRES_SITES_PARAMETERS for the MultiGMPE will not
# include Vs30 even though it will be needed to compute the
# default site term. So if the site checks have passed to this
# point, we should add Vs30 to the set of required site pars:
self.REQUIRES_SITES_PARAMETERS = set.union(
self.REQUIRES_SITES_PARAMETERS, set(['vs30']))
self.DEFAULT_GMPES_FOR_SITE = default_gmpes_for_site
self.DEFAULT_GMPES_FOR_SITE_WEIGHTS = default_gmpes_for_site_weights
self.REFERENCE_VS30 = reference_vs30
# ---------------------------------------------------------------------
# Union of rupture parameters
# ---------------------------------------------------------------------
ruppars = [g.REQUIRES_RUPTURE_PARAMETERS for g in gmpes]
self.REQUIRES_RUPTURE_PARAMETERS = set.union(*ruppars)
# ---------------------------------------------------------------------
# Union of distance parameters
# ---------------------------------------------------------------------
distpars = [g.REQUIRES_DISTANCES for g in gmpes]
self.REQUIRES_DISTANCES = set.union(*distpars)
return self
[docs] def get_site_factors(self, sites, rup, dists, imt, default=False):
"""
Method for computing site amplification factors from the defalut GMPE
to be applied to GMPEs which do not have a site term.
**NOTE** Amps are calculated in natural log units and so the ln(amp)
is returned.
Args:
sites (SitesContext): Instance of SitesContext.
rup (RuptureContext): Instance of RuptureContext.
dists (DistancesContext): Instance of DistancesContext.
imt: An instance openquake.hazardlib.imt.
default (bool): Boolean of whether or not to return the
amplificaiton factors for the gmpes or default_gmpes_for_site.
This argument is primarily only intended to be used internally
for when we just need to access the default amplifications to
apply to those GMPEs that do not have site terms.
Returns:
Site amplifications in natural log units.
"""
# ---------------------------------------------------------------------
# Make reference sites context
# ---------------------------------------------------------------------
ref_sites = copy.deepcopy(sites)
ref_sites.vs30 = np.ones_like(sites.vs30) * self.REFERENCE_VS30
# ---------------------------------------------------------------------
# If default True, construct new MultiGMPE with default GMPE/weights
# ---------------------------------------------------------------------
if default is True:
tmp = MultiGMPE.from_list(
self.DEFAULT_GMPES_FOR_SITE,
self.DEFAULT_GMPES_FOR_SITE_WEIGHTS,
self.DEFINED_FOR_INTENSITY_MEASURE_COMPONENT)
# ---------------------------------------------------------------------
# If default False, just use self
# ---------------------------------------------------------------------
else:
tmp = self
lmean, lsd = tmp.get_mean_and_stddevs(
sites, rup, dists, imt,
list(tmp.DEFINED_FOR_STANDARD_DEVIATION_TYPES))
lmean_ref, lsd = tmp.get_mean_and_stddevs(
ref_sites, rup, dists, imt,
list(tmp.DEFINED_FOR_STANDARD_DEVIATION_TYPES))
lamps = lmean - lmean_ref
return lamps
[docs] @staticmethod
def set_sites_depth_parameters(sites, gmpe):
"""
Need to select the appropriate z1pt0 value for different GMPEs.
Note that these are required site parameters, so even though
OQ has these equations built into the class in most cases.
I have submitted an issue to OQ requesting subclasses of these
methods that do not require the depth parameters in the
SitesContext to make this easier.
Args:
sites:1 An OQ sites context.
gmpe: An OQ GMPE instance.
Returns:
An OQ sites context with the depth parameters set for the
requested GMPE.
"""
sites = Sites._addDepthParameters(sites)
if gmpe == 'AbrahamsonEtAl2014()':
sites.z1pt0 = sites.z1pt0_ask14_cal
if gmpe == 'ChiouYoungs2014()':
# Also BooreEtAl2014() if using subclass with depth parameter
sites.z1pt0 = sites.z1pt0_cy14_cal
if gmpe == 'CampbellBozorgnia2014()':
sites.z2pt5 = sites.z2pt5_cb14_cal
if gmpe == 'ChiouYoungs2008()':
sites.z1pt0 = sites.z1pt0_cy08
if gmpe == 'CampbellBozorgnia2008()':
sites.z2pt5 = sites.z2pt5_cb07
return sites
[docs]def filter_gmpe_list(gmpes, wts, imt):
"""
Method to remove GMPEs from the GMPE list that are not applicable
to a specific IMT. Rescales the weights to sum to one.
Args:
gmpes (list): List of GMPE instances.
wts (list): List of floats indicating the weight of the GMPEs.
imt (IMT): OQ IMT to filter GMPE list for.
Returns:
tuple: List of GMPE instances and list of weights.
"""
if wts is None:
n = len(gmpes)
wts = [1 / n] * n
per_max = [np.max(get_gmpe_sa_periods(g)) for g in gmpes]
per_min = [np.min(get_gmpe_sa_periods(g)) for g in gmpes]
if imt == PGA():
sgmpe = [g for g in gmpes if imt in
get_gmpe_coef_table(g).non_sa_coeffs]
swts = [w for g, w in zip(gmpes, wts) if imt in
get_gmpe_coef_table(g).non_sa_coeffs]
elif imt == PGV():
sgmpe = []
swts = []
for i in range(len(gmpes)):
if (imt in get_gmpe_coef_table(gmpes[i]).non_sa_coeffs) or\
(per_max[i] >= 1.0 and per_min[i] <= 1.0):
sgmpe.append(gmpes[i])
swts.append(wts[i])
else:
per = imt.period
sgmpe = []
swts = []
for i in range(len(gmpes)):
if (per_max[i] >= per and per_min[i] <= per):
sgmpe.append(gmpes[i])
swts.append(wts[i])
if len(sgmpe) == 0:
raise Exception('No applicable GMPEs from GMPE list for %s' % imt)
# Scale weights to sum to one
swts = np.array(swts)
swts = swts / np.sum(swts)
return sgmpe, swts
[docs]def get_gmpe_sa_periods(gmpe):
"""
Method to extract the SA periods defined by a GMPE.
Args:
gmpe (GMPE): A GMPE instance.
Retunrs:
list: List of periods.
"""
ctab = get_gmpe_coef_table(gmpe).sa_coeffs
ilist = list(ctab.keys())
per = [i.period for i in ilist]
return per
[docs]def get_gmpe_coef_table(gmpe):
"""
Method for finding the (or "a") GMPE table.
Notes:
* The reason for the complexity here is that there can be multiple
coefficient tables, and some of them may not have the sa_coeffs
attribute, which is the main reason for getting the table.
* We are also assuming that if there are more than one coefficient
table, the range of periods will be the same across all of the
tables.
Args:
gmpe (GMPE): An OQ GMPE instance.
Returns:
The associated coefficient table.
"""
stuff = gmpe.__dir__()
coef_list = [s for s in stuff if 'COEFFS' in s]
for coef_sel in coef_list:
cobj = getattr(gmpe, coef_sel)
if "sa_coeffs" in cobj.__dir__():
return cobj
raise Exception("GMPE %s does not contain sa_coeffs attribute." % gmpe)