def getSitesContext(self, lldict=None, rock_vs30=None): """ Create a SitesContext object by sampling the current Sites object. Args: lldict: Either - None, in which case the SitesContext for the complete Sites grid is returned, or - A location dictionary (elements are 'lats' and 'lons' and each is a numpy array). Each element must have the same shape. In this case the SitesContext for these locaitons is returned. rock_vs30: Either - None, in which case the SitesContext will reflect the Vs30 grid in the Sites instance, or - A float for the rock Vs30 value, in which case the SitesContext will be constructed for this constant Vs30 value. Returns: SitesContext object. Raises: ShakeLibException: When lat/lon input sequences do not share dimensionality. """ # noqa sctx = SitesContext() if lldict is not None: lats = lldict['lats'] lons = lldict['lons'] latshape = lats.shape lonshape = lons.shape if latshape != lonshape: msg = 'Input lat/lon arrays must have the same dimensions' raise ShakeLibException(msg) if rock_vs30 is not None: tmp = self._Vs30.getValue( lats, lons, default=self._defaultVs30) sctx.vs30 = np.ones_like(tmp) * rock_vs30 else: sctx.vs30 = self._Vs30.getValue( lats, lons, default=self._defaultVs30) sctx.lats = lats sctx.lons = lons sctx.sids = np.array(range(np.size(lons))).reshape(lons.shape) else: sctx.lons = self._lons.copy() sctx.lats = self._lats.copy() if rock_vs30 is not None: sctx.vs30 = np.full_like(self._Vs30.getData(), rock_vs30) else: sctx.vs30 = self._Vs30.getData().copy() sctx.sids = \ np.array( range( np.size(sctx.lons)* np.size(sctx.lats))).reshape(sctx.vs30.shape) Sites._addDepthParameters(sctx) # For ShakeMap purposes, vs30 measured is always Fales sctx.vs30measured = np.zeros_like(sctx.vs30, dtype=bool) # Backarc should be a numpy array if lldict is not None: tgd = self._Vs30.getGeoDict() backarcgrid = Grid2D(self._backarc, tgd) sctx.backarc = backarcgrid.getValue(lats, lons, default=False) else: sctx.backarc = self._backarc.copy() return sctx
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() size = 2000 # 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), size) # 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.sids = np.array(range(size)) sx.vs30 = np.full(size, 180.0) set_sites_depth_parameters(sx, gmpe) sx.vs30measured = np.full(size, False, dtype=bool) sx.backarc = np.full(size, 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])