Example #1
0
def _disaggregate(cmaker,
                  sitecol,
                  ctxs,
                  iml2,
                  eps3,
                  pne_mon=performance.Monitor(),
                  gmf_mon=performance.Monitor()):
    # disaggregate (separate) PoE in different contributions
    # returns AccumDict with keys (poe, imt) and mags, dists, lons, lats
    acc = dict(pnes=[], mags=[], dists=[], lons=[], lats=[])
    try:
        gsim = cmaker.gsim_by_rlzi[iml2.rlzi]
    except KeyError:
        return pack(acc, 'mags dists lons lats pnes'.split())
    for rctx, dctx in ctxs:
        [dist] = dctx.rrup
        if gsim.minimum_distance and dist < gsim.minimum_distance:
            dist = gsim.minimum_distance
        acc['mags'].append(rctx.mag)
        acc['lons'].append(dctx.lon)
        acc['lats'].append(dctx.lat)
        acc['dists'].append(dist)
        with gmf_mon:
            mean_std = get_mean_std(sitecol, rctx, dctx, iml2.imts,
                                    [gsim])[..., 0]  # (2, N, M)
        with pne_mon:
            iml = numpy.array([
                to_distribution_values(lvl, imt)
                for imt, lvl in zip(iml2.imts, iml2)
            ])  # shape (M, P)
            pne = _disaggregate_pne(rctx, mean_std, iml, *eps3)
            acc['pnes'].append(pne)
    return pack(acc, 'mags dists lons lats pnes'.split())
Example #2
0
def _disaggregate(cmaker,
                  sitecol,
                  rupdata,
                  indices,
                  iml2,
                  eps3,
                  pne_mon=performance.Monitor()):
    # disaggregate (separate) PoE in different contributions
    # returns AccumDict with keys (poe, imt) and mags, dists, lons, lats
    [sid] = sitecol.sids
    acc = AccumDict(accum=[],
                    mags=[],
                    dists=[],
                    lons=[],
                    lats=[],
                    M=len(iml2.imts),
                    P=len(iml2.poes_disagg))
    try:
        gsim = cmaker.gsim_by_rlzi[iml2.rlzi]
    except KeyError:
        return pack(acc, 'mags dists lons lats P M'.split())
    maxdist = cmaker.maximum_distance(cmaker.trt)
    fildist = rupdata[cmaker.filter_distance + '_']
    for ridx, sidx in enumerate(indices):
        if sidx == -1:  # no contribution for this site
            continue
        dist = fildist[ridx][sidx]
        if dist >= maxdist:
            continue
        elif gsim.minimum_distance and dist < gsim.minimum_distance:
            dist = gsim.minimum_distance
        rctx = contexts.RuptureContext()
        for par in rupdata:
            setattr(rctx, par, rupdata[par][ridx])
        dctx = contexts.DistancesContext(
            (param, getattr(rctx, param + '_')[[sidx]])
            for param in cmaker.REQUIRES_DISTANCES).roundup(
                gsim.minimum_distance)
        acc['mags'].append(rctx.mag)
        acc['lons'].append(rctx.lon_[sidx])
        acc['lats'].append(rctx.lat_[sidx])
        acc['dists'].append(dist)
        with pne_mon:
            for m, imt in enumerate(iml2.imts):
                for p, poe in enumerate(iml2.poes_disagg):
                    iml = iml2[m, p]
                    pne = disaggregate_pne(gsim, rctx, sitecol, dctx, imt, iml,
                                           *eps3)
                    acc[p, m].append(pne)
    return pack(acc, 'mags dists lons lats P M'.split())
Example #3
0
def collect_bin_data(sources,
                     sitecol,
                     cmaker,
                     iml4,
                     truncation_level,
                     n_epsilons,
                     monitor=Monitor()):
    """
    :param sources: a list of sources
    :param sitecol: a SiteCollection instance
    :param cmaker: a ContextMaker instance
    :param iml4: an ArrayWrapper of intensities of shape (N, R, M, P)
    :param truncation_level: the truncation level
    :param n_epsilons: the number of epsilons
    :param monitor: a Monitor instance
    :returns: a dictionary (poe, imt, rlzi) -> probabilities of shape (N, E)
    """
    # NB: instantiating truncnorm is slow and calls the infamous "doccer"
    truncnorm = scipy.stats.truncnorm(-truncation_level, truncation_level)
    epsilons = numpy.linspace(truncnorm.a, truncnorm.b, n_epsilons + 1)
    acc = AccumDict(accum=[])
    for source in sources:
        with cmaker.ir_mon:
            ruptures = list(source.iter_ruptures())
        try:
            acc += cmaker.disaggregate(sitecol, ruptures, iml4, truncnorm,
                                       epsilons, monitor)
        except Exception as err:
            etype, err, tb = sys.exc_info()
            msg = 'An error occurred with source id=%s. Error: %s'
            msg %= (source.source_id, err)
            raise_(etype, msg, tb)
    return pack(acc, 'mags dists lons lats'.split())
Example #4
0
def _disaggregate(cmaker,
                  sitecol,
                  rupdata,
                  indices,
                  iml2,
                  eps3,
                  pne_mon=performance.Monitor(),
                  gmf_mon=performance.Monitor()):
    # disaggregate (separate) PoE in different contributions
    # returns AccumDict with keys (poe, imt) and mags, dists, lons, lats
    [sid] = sitecol.sids
    acc = dict(pnes=[], mags=[], dists=[], lons=[], lats=[])
    try:
        gsim = cmaker.gsim_by_rlzi[iml2.rlzi]
    except KeyError:
        return pack(acc, 'mags dists lons lats pnes'.split())
    maxdist = cmaker.maximum_distance(cmaker.trt)
    fildist = rupdata[cmaker.filter_distance + '_']
    for ridx, sidx in enumerate(indices):
        if sidx == -1:  # no contribution for this site
            continue
        dist = fildist[ridx][sidx]
        if dist >= maxdist:
            continue
        elif gsim.minimum_distance and dist < gsim.minimum_distance:
            dist = gsim.minimum_distance
        rctx = contexts.RuptureContext(
            (par, val[ridx]) for par, val in rupdata.items())
        dctx = contexts.DistancesContext(
            (param, getattr(rctx, param + '_')[[sidx]])
            for param in cmaker.REQUIRES_DISTANCES)
        acc['mags'].append(rctx.mag)
        acc['lons'].append(rctx.lon_[sidx])
        acc['lats'].append(rctx.lat_[sidx])
        acc['dists'].append(dist)
        with gmf_mon:
            mean_std = get_mean_std(sitecol, rctx, dctx, iml2.imts,
                                    [gsim])[..., 0]  # (2, N, M)
        with pne_mon:
            iml = numpy.array([
                to_distribution_values(lvl, imt)
                for imt, lvl in zip(iml2.imts, iml2)
            ])  # shape (M, P)
            pne = _disaggregate_pne(rctx, mean_std, iml, *eps3)
            acc['pnes'].append(pne)
    return pack(acc, 'mags dists lons lats pnes'.split())
Example #5
0
def compute_disagg(src_filter, sources, cmaker, imldict, trt_names, bin_edges,
                   oqparam, monitor):
    # see https://bugs.launchpad.net/oq-engine/+bug/1279247 for an explanation
    # of the algorithm used
    """
    :param src_filter:
        a :class:`openquake.hazardlib.calc.filter.SourceFilter` instance
    :param sources:
        list of hazardlib source objects
    :param cmaker:
        a :class:`openquake.hazardlib.gsim.base.ContextMaker` instance
    :param imldict:
        a list of dictionaries poe, gsim, imt, rlzi -> iml
    :param dict trt_names:
        a tuple of names for the given tectonic region type
    :param bin_egdes:
        a dictionary site_id -> edges
    :param oqparam:
        the parameters in the job.ini file
    :param monitor:
        monitor of the currently running job
    :returns:
        a dictionary of probability arrays, with composite key
        (sid, rlz.id, poe, imt, iml, trt_names).
    """
    sitecol = src_filter.sitecol
    trt_num = dict((trt, i) for i, trt in enumerate(trt_names))
    result = {}  # sid, rlz.id, poe, imt, iml, trt_names -> array

    collecting_mon = monitor('collecting bins')
    arranging_mon = monitor('arranging bins')

    for i, site in enumerate(sitecol):
        sid = sitecol.sids[i]
        # edges as wanted by disagg._arrange_data_in_bins
        try:
            edges = bin_edges[sid] + (trt_names, )
        except KeyError:
            # bin_edges for a given site are missing if the site is far away
            continue

        with collecting_mon:
            acc = disagg.collect_bins_data(
                trt_num, sources, site, cmaker, imldict[i],
                oqparam.truncation_level, oqparam.num_epsilon_bins,
                monitor('disaggregate_pne', measuremem=False))
            bindata = pack(acc, 'mags dists lons lats trti'.split())
            if not bindata:
                continue

        with arranging_mon:
            for (poe, imt, iml, rlzi), pmf in disagg.arrange_data_in_bins(
                    bindata, edges, 'pmf', arranging_mon).items():
                result[sid, rlzi, poe, imt, iml, trt_names] = pmf
        result['cache_info'] = arranging_mon.cache_info
    return result
Example #6
0
def collect_bin_data(ruptures, sitecol, cmaker, iml4,
                     truncation_level, n_epsilons, monitor=Monitor()):
    """
    :param ruptures: a list of ruptures
    :param sitecol: a SiteCollection instance
    :param cmaker: a ContextMaker instance
    :param iml4: an ArrayWrapper of intensities of shape (N, R, M, P)
    :param truncation_level: the truncation level
    :param n_epsilons: the number of epsilons
    :param monitor: a Monitor instance
    :returns: a dictionary (poe, imt, rlzi) -> probabilities of shape (N, E)
    """
    # NB: instantiating truncnorm is slow and calls the infamous "doccer"
    truncnorm = scipy.stats.truncnorm(-truncation_level, truncation_level)
    epsilons = numpy.linspace(truncnorm.a, truncnorm.b, n_epsilons + 1)
    acc = cmaker.disaggregate(
        sitecol, ruptures, iml4, truncnorm, epsilons, monitor)
    return pack(acc, 'mags dists lons lats'.split())
Example #7
0
def collect_bin_data(ruptures, sitecol, cmaker, iml4,
                     truncation_level, n_epsilons, monitor=Monitor()):
    """
    :param ruptures: a list of ruptures
    :param sitecol: a SiteCollection instance
    :param cmaker: a ContextMaker instance
    :param iml4: an ArrayWrapper of intensities of shape (N, R, M, P)
    :param truncation_level: the truncation level
    :param n_epsilons: the number of epsilons
    :param monitor: a Monitor instance
    :returns: a dictionary (poe, imt, rlzi) -> probabilities of shape (N, E)
    """
    # NB: instantiating truncnorm is slow and calls the infamous "doccer"
    truncnorm = scipy.stats.truncnorm(-truncation_level, truncation_level)
    epsilons = numpy.linspace(truncnorm.a, truncnorm.b, n_epsilons + 1)
    acc = cmaker.disaggregate(
        sitecol, ruptures, iml4, truncnorm, epsilons, monitor)
    return pack(acc, 'mags dists lons lats'.split())
Example #8
0
def disaggregation(sources,
                   site,
                   imt,
                   iml,
                   gsim_by_trt,
                   truncation_level,
                   n_epsilons,
                   mag_bin_width,
                   dist_bin_width,
                   coord_bin_width,
                   source_filter=filters.source_site_noop_filter):
    """
    Compute "Disaggregation" matrix representing conditional probability of an
    intensity mesaure type ``imt`` exceeding, at least once, an intensity
    measure level ``iml`` at a geographical location ``site``, given rupture
    scenarios classified in terms of:

    - rupture magnitude
    - Joyner-Boore distance from rupture surface to site
    - longitude and latitude of the surface projection of a rupture's point
      closest to ``site``
    - epsilon: number of standard deviations by which an intensity measure
      level deviates from the median value predicted by a GSIM, given the
      rupture parameters
    - rupture tectonic region type

    In other words, the disaggregation matrix allows to compute the probability
    of each scenario with the specified properties (e.g., magnitude, or the
    magnitude and distance) to cause one or more exceedences of a given hazard
    level.

    For more detailed information about the disaggregation, see for instance
    "Disaggregation of Seismic Hazard", Paolo Bazzurro, C. Allin Cornell,
    Bulletin of the Seismological Society of America, Vol. 89, pp. 501-520,
    April 1999.

    :param sources:
        Seismic source model, as for
        :mod:`PSHA <openquake.hazardlib.calc.hazard_curve>` calculator it
        should be an iterator of seismic sources.
    :param site:
        :class:`~openquake.hazardlib.site.Site` of interest to calculate
        disaggregation matrix for.
    :param imt:
        Instance of :mod:`intensity measure type <openquake.hazardlib.imt>`
        class.
    :param iml:
        Intensity measure level. A float value in units of ``imt``.
    :param gsim_by_trt:
        Tectonic region type to GSIM objects mapping.
    :param truncation_level:
        Float, number of standard deviations for truncation of the intensity
        distribution.
    :param n_epsilons:
        Integer number of epsilon histogram bins in the result matrix.
    :param mag_bin_width:
        Magnitude discretization step, width of one magnitude histogram bin.
    :param dist_bin_width:
        Distance histogram discretization step, in km.
    :param coord_bin_width:
        Longitude and latitude histograms discretization step,
        in decimal degrees.
    :param source_filter:
        Optional source-site filter function. See
        :mod:`openquake.hazardlib.calc.filters`.

    :returns:
        A tuple of two items. First is itself a tuple of bin edges information
        for (in specified order) magnitude, distance, longitude, latitude,
        epsilon and tectonic region types.

        Second item is 6d-array representing the full disaggregation matrix.
        Dimensions are in the same order as bin edges in the first item
        of the result tuple. The matrix can be used directly by pmf-extractor
        functions.
    """
    trts = sorted(set(src.tectonic_region_type for src in sources))
    trt_num = dict((trt, i) for i, trt in enumerate(trts))
    rlzs_by_gsim = {gsim_by_trt[trt]: [0] for trt in trts}
    cmaker = ContextMaker(rlzs_by_gsim, source_filter.integration_distance)
    imldict = make_imldict(rlzs_by_gsim, {str(imt): [iml]}, {str(imt): iml})
    bdata = collect_bins_data(trt_num, sources, site, cmaker, imldict,
                              truncation_level, n_epsilons)
    bd = pack(bdata, 'mags dists lons lats trti'.split())
    if len(bd.mags) == 0:
        warnings.warn(
            'No ruptures have contributed to the hazard at site %s' % site,
            RuntimeWarning)
        return None, None

    mag_bins = mag_bin_width * numpy.arange(
        int(numpy.floor(bd.mags.min() / mag_bin_width)),
        int(numpy.ceil(bd.mags.max() / mag_bin_width) + 1))

    dist_bins = dist_bin_width * numpy.arange(
        int(numpy.floor(bd.dists.min() / dist_bin_width)),
        int(numpy.ceil(bd.dists.max() / dist_bin_width) + 1))

    bb = (bd.lons.min(), bd.lons.min(), bd.lats.max(), bd.lats.max())
    lon_bins, lat_bins = lon_lat_bins(bb, coord_bin_width)

    eps_bins = numpy.linspace(-truncation_level, truncation_level,
                              n_epsilons + 1)

    bin_edges = (mag_bins, dist_bins, lon_bins, lat_bins, eps_bins, trts)

    [matrix] = arrange_data_in_bins(bd, bin_edges, 'matrix').values()
    return bin_edges, matrix