예제 #1
0
    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
예제 #2
0
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])