def ucerf_classical(rupset_idx, ucerf_source, src_filter, gsims, monitor):
    """
    :param rupset_idx:
        indices of the rupture sets
    :param ucerf_source:
        an object taking the place of a source for UCERF
    :param src_filter:
        a source filter returning the sites affected by the source
    :param gsims:
        a list of GSIMs
    :param monitor:
        a monitor instance
    :returns:
        a ProbabilityMap
    """
    t0 = time.time()
    truncation_level = monitor.oqparam.truncation_level
    imtls = monitor.oqparam.imtls
    ucerf_source.src_filter = src_filter  # so that .iter_ruptures() work
    grp_id = ucerf_source.src_group_id
    mag = ucerf_source.mags[rupset_idx].max()
    ridx = set()
    for idx in rupset_idx:
        ridx.update(ucerf_source.get_ridx(idx))
    ucerf_source.rupset_idx = rupset_idx
    ucerf_source.num_ruptures = nruptures = len(rupset_idx)

    # prefilter the sites close to the rupture set
    s_sites = ucerf_source.get_rupture_sites(ridx, src_filter, mag)
    if s_sites is None:  # return an empty probability map
        pm = ProbabilityMap(len(imtls.array), len(gsims))
        acc = AccumDict({grp_id: pm})
        acc.calc_times = {
            ucerf_source.source_id:
            numpy.array([nruptures, 0, time.time() - t0, 1])
        }
        acc.eff_ruptures = {grp_id: 0}
        return acc

    # compute the ProbabilityMap
    cmaker = ContextMaker(gsims, src_filter.integration_distance)
    imtls = DictArray(imtls)
    ctx_mon = monitor('make_contexts', measuremem=False)
    poe_mon = monitor('get_poes', measuremem=False)
    pmap = cmaker.poe_map(ucerf_source, s_sites, imtls, truncation_level,
                          ctx_mon, poe_mon)
    nsites = len(s_sites)
    acc = AccumDict({grp_id: pmap})
    acc.calc_times = {
        ucerf_source.source_id:
        numpy.array([nruptures * nsites, nsites,
                     time.time() - t0, 1])
    }
    acc.eff_ruptures = {grp_id: ucerf_source.num_ruptures}
    return acc
def build_ruptures(sources, src_filter, param, monitor):
    """
    :param sources: a list with a single UCERF source
    :param param: extra parameters
    :param monitor: a Monitor instance
    :returns: an AccumDict grp_id -> EBRuptures
    """
    [src] = sources
    res = AccumDict()
    res.calc_times = []
    sampl_mon = monitor('sampling ruptures', measuremem=True)
    res.trt = DEFAULT_TRT
    background_sids = src.get_background_sids(src_filter)
    samples = getattr(src, 'samples', 1)
    n_occ = AccumDict(accum=0)
    t0 = time.time()
    with sampl_mon:
        for sam_idx in range(samples):
            for ses_idx, ses_seed in param['ses_seeds']:
                seed = sam_idx * TWO16 + ses_seed
                rups, occs = generate_event_set(src, background_sids,
                                                src_filter, ses_idx, seed)
                for rup, occ in zip(rups, occs):
                    n_occ[rup] += occ
    tot_occ = sum(n_occ.values())
    dic = {'eff_ruptures': {src.src_group_id: src.num_ruptures}}
    eb_ruptures = [
        EBRupture(rup, src.id, src.src_group_id, n, samples)
        for rup, n in n_occ.items()
    ]
    dic['rup_array'] = stochastic.get_rup_array(eb_ruptures, src_filter)
    dt = time.time() - t0
    n = len(src_filter.sitecol)
    dic['calc_times'] = {src.id: numpy.array([tot_occ, n, dt], F32)}
    return dic
Beispiel #3
0
 def execute(self):
     """
     Run in parallel `core_func(sources, sitecol, monitor)`, by
     parallelizing on the sources according to their weight and
     tectonic region type.
     """
     monitor = self.monitor.new(self.core_func.__name__)
     monitor.oqparam = self.oqparam
     sources = self.csm.get_sources()
     zc = zero_curves(len(self.sitecol.complete), self.oqparam.imtls)
     zerodict = AccumDict((key, zc) for key in self.rlzs_assoc)
     zerodict.calc_times = []
     zerodict.bb_dict = {
         (smodel.ordinal, site.id): BoundingBox(smodel.ordinal, site.id)
         for site in self.sitecol
         for smodel in self.csm.source_models
     } if self.oqparam.poes_disagg else {}
     curves_by_trt_gsim = parallel.apply_reduce(
         self.core_func.__func__,
         (sources, self.sitecol, 0, self.rlzs_assoc, monitor),
         agg=self.agg_dicts, acc=zerodict,
         concurrent_tasks=self.oqparam.concurrent_tasks,
         weight=operator.attrgetter('weight'),
         key=operator.attrgetter('trt_model_id'))
     store_source_chunks(self.datastore)
     return curves_by_trt_gsim
Beispiel #4
0
def classical(group, src_filter, gsims, param, monitor=Monitor()):
    """
    Compute the hazard curves for a set of sources belonging to the same
    tectonic region type for all the GSIMs associated to that TRT.
    The arguments are the same as in :func:`calc_hazard_curves`, except
    for ``gsims``, which is a list of GSIM instances.

    :returns:
        a dictionary {grp_id: pmap} with attributes .grp_ids, .calc_times,
        .eff_ruptures
    """
    if getattr(group, 'src_interdep', None) == 'mutex':
        mutex_weight = {
            src.source_id: weight
            for src, weight in zip(group.sources, group.srcs_weights)
        }
    else:
        mutex_weight = None
    grp_ids = set()
    for src in group:
        grp_ids.update(src.src_group_ids)
    maxdist = src_filter.integration_distance
    with GroundShakingIntensityModel.forbid_instantiation():
        imtls = param['imtls']
        trunclevel = param.get('truncation_level')
        cmaker = ContextMaker(gsims, maxdist)
        ctx_mon = monitor('make_contexts', measuremem=False)
        poe_mon = monitor('get_poes', measuremem=False)
        pmap = AccumDict({
            grp_id: ProbabilityMap(len(imtls.array), len(gsims))
            for grp_id in grp_ids
        })
        # AccumDict of arrays with 4 elements weight, nsites, calc_time, split
        pmap.calc_times = AccumDict(accum=numpy.zeros(4))
        pmap.eff_ruptures = AccumDict()  # grp_id -> num_ruptures
        for src, s_sites in src_filter(group):  # filter now
            t0 = time.time()
            indep = group.rup_interdep == 'indep' if mutex_weight else True
            poemap = cmaker.poe_map(src, s_sites, imtls, trunclevel, ctx_mon,
                                    poe_mon, indep)
            if mutex_weight:  # mutex sources
                weight = mutex_weight[src.source_id]
                for sid in poemap:
                    pcurve = pmap[group.id].setdefault(sid, 0)
                    pcurve += poemap[sid] * weight
            elif poemap:
                for grp_id in src.src_group_ids:
                    pmap[grp_id] |= poemap
            src_id = src.source_id.split(':', 1)[0]
            pmap.calc_times[src_id] += numpy.array(
                [src.weight, len(s_sites),
                 time.time() - t0, 1])
            # storing the number of contributing ruptures too
            pmap.eff_ruptures += {
                grp_id: getattr(poemap, 'eff_ruptures', 0)
                for grp_id in src.src_group_ids
            }
        if mutex_weight and group.grp_probability is not None:
            pmap[group.id] *= group.grp_probability
        return pmap
def build_ruptures(sources, src_filter, param, monitor):
    """
    :param sources: a list with a single UCERF source
    :param param: extra parameters
    :param monitor: a Monitor instance
    :returns: an AccumDict grp_id -> EBRuptures
    """
    [src] = sources
    res = AccumDict()
    res.calc_times = []
    sampl_mon = monitor('sampling ruptures', measuremem=True)
    res.trt = DEFAULT_TRT
    background_sids = src.get_background_sids(src_filter)
    samples = getattr(src, 'samples', 1)
    n_occ = AccumDict(accum=0)
    t0 = time.time()
    with sampl_mon:
        for sam_idx in range(samples):
            for ses_idx, ses_seed in param['ses_seeds']:
                seed = sam_idx * TWO16 + ses_seed
                rups, occs = generate_event_set(
                    src, background_sids, src_filter, ses_idx, seed)
                for rup, occ in zip(rups, occs):
                    n_occ[rup] += occ
    tot_occ = sum(n_occ.values())
    dic = {'eff_ruptures': {src.src_group_id: src.num_ruptures}}
    eb_ruptures = [EBRupture(rup, src.id, src.src_group_id, n, samples)
                   for rup, n in n_occ.items()]
    dic['rup_array'] = stochastic.get_rup_array(eb_ruptures, src_filter)
    dt = time.time() - t0
    dic['calc_times'] = {src.id: numpy.array([tot_occ, dt], F32)}
    return dic
Beispiel #6
0
def compute_hazard(sources_or_ruptures, src_filter, rlzs_by_gsim, param,
                   monitor):
    """
    Compute events, ruptures, gmfs and hazard curves
    """
    res = AccumDict()
    with monitor('building ruptures', measuremem=True):
        if isinstance(sources_or_ruptures, RuptureGetter):
            grp_id = sources_or_ruptures.grp_id
            res['ruptures'] = {}
            ruptures = list(sources_or_ruptures)
            sitecol = src_filter
        else:
            grp_id = sources_or_ruptures[0].src_group_id
            dic = sample_ruptures(sources_or_ruptures, src_filter,
                                  rlzs_by_gsim, param, monitor)
            ruptures = dic['eb_ruptures']
            res.num_events = dic['num_events']
            res.calc_times = dic['calc_times']
            res.eff_ruptures = {grp_id: dic['num_ruptures']}
            res['ruptures'] = {grp_id: ruptures}
            res.num_ruptures = len(ruptures)
            sitecol = src_filter.sitecol
    res['num_ruptures'] = len(ruptures)
    getter = GmfGetter(rlzs_by_gsim, ruptures, sitecol, param['oqparam'],
                       param['min_iml'], param['samples'])
    res.update(getter.compute_gmfs_curves(monitor))
    if param['oqparam'].save_ruptures is False:
        res.events = get_events(ruptures)
        res['ruptures'] = {}
    return res
    def execute(self):
        """
        Run in parallel `core_task(sources, sitecol, monitor)`, by
        parallelizing on the sources according to their weight and
        tectonic region type.
        """
        monitor = self.monitor(self.core_task.__name__)
        monitor.oqparam = oq = self.oqparam
        self.src_filter = SourceFilter(self.sitecol, oq.maximum_distance)
        self.nsites = []
        acc = AccumDict({
            grp_id: ProbabilityMap(len(oq.imtls.array), len(gsims))
            for grp_id, gsims in self.gsims_by_grp.items()
        })
        acc.calc_times = {}
        acc.eff_ruptures = AccumDict()  # grp_id -> eff_ruptures
        acc.bb_dict = {}  # just for API compatibility
        param = dict(imtls=oq.imtls, truncation_level=oq.truncation_level)
        for sm in self.csm.source_models:  # one branch at the time
            grp_id = sm.ordinal
            gsims = self.gsims_by_grp[grp_id]
            [[ucerf_source]] = sm.src_groups
            ucerf_source.nsites = len(self.sitecol)
            self.csm.infos[ucerf_source.source_id] = source.SourceInfo(
                ucerf_source)
            logging.info('Getting the background point sources')
            bckgnd_sources = ucerf_source.get_background_sources(
                self.src_filter)

            # since there are two kinds of tasks (background and rupture_set)
            # we divide the concurrent_tasks parameter by 2;
            # notice the "or 1" below, to avoid issues when
            # self.oqparam.concurrent_tasks is 0 or 1
            ct2 = (self.oqparam.concurrent_tasks // 2) or 1

            # parallelize on the background sources, small tasks
            args = (bckgnd_sources, self.src_filter, gsims, param, monitor)
            bg_res = parallel.Starmap.apply(classical,
                                            args,
                                            name='background_sources_%d' %
                                            grp_id,
                                            concurrent_tasks=ct2)

            # parallelize by rupture subsets
            rup_sets = numpy.arange(ucerf_source.num_ruptures)
            taskname = 'ucerf_classical_%d' % grp_id
            acc = parallel.Starmap.apply(
                ucerf_classical,
                (rup_sets, ucerf_source, self.src_filter, gsims, monitor),
                concurrent_tasks=ct2,
                name=taskname).reduce(self.agg_dicts, acc)

            # compose probabilities from background sources
            for pmap in bg_res:
                acc[grp_id] |= pmap[grp_id]

        with self.monitor('store source_info', autoflush=True):
            self.store_source_info(self.csm.infos, acc)
        return acc  # {grp_id: pmap}
def compute_ruptures(branch_info, ucerf, sitecol, oqparam, monitor):
    """
    Returns the ruptures as a TRT set
    :param str branch_info:
        Tuple of (ltbr, branch_id, branch_weight)
    :param ucerf:
        Instance of the UCERFSESControl object
    :param sitecol:
        Site collection :class:`openquake.hazardlib.site.SiteCollection`
    :param oqparam:
        Instance of :class:`openquake.commonlib.oqvalidation.OqParam`
    :param monitor:
        Instance of :class:`openquake.baselib.performance.Monitor`
    :returns:
        Dictionary of rupture instances associated to a TRT ID
    """
    integration_distance = oqparam.maximum_distance[DEFAULT_TRT]
    res = AccumDict()
    res.calc_times = AccumDict()
    serial = 1
    filter_mon = monitor('update_background_site_filter', measuremem=False)
    event_mon = monitor('sampling ruptures', measuremem=False)
    for src_group_id, (ltbrid, branch_id, _) in enumerate(branch_info):
        t0 = time.time()
        with filter_mon:
            ucerf.update_background_site_filter(sitecol, integration_distance)

        # set the seed before calling generate_event_set
        numpy.random.seed(oqparam.random_seed + src_group_id)
        ses_ruptures = []
        for ses_idx in range(1, oqparam.ses_per_logic_tree_path + 1):
            with event_mon:
                rups, n_occs = ucerf.generate_event_set(
                    branch_id, sitecol, integration_distance)
            for i, rup in enumerate(rups):
                rup.seed = oqparam.random_seed  # to think
                rrup = rup.surface.get_min_distance(sitecol.mesh)
                r_sites = sitecol.filter(rrup <= integration_distance)
                if r_sites is None:
                    continue
                indices = r_sites.indices
                events = []
                for j in range(n_occs[i]):
                    # NB: the first 0 is a placeholder for the eid that will be
                    # set later, in EventBasedRuptureCalculator.post_execute;
                    # the second 0 is the sampling ID
                    events.append((0, ses_idx, j, 0))
                if len(events):
                    ses_ruptures.append(
                        event_based.EBRupture(
                            rup, indices,
                            numpy.array(events, event_based.event_dt),
                            ucerf.source_id, src_group_id, serial))
                    serial += 1
        dt = time.time() - t0
        res.calc_times[src_group_id] = (ltbrid, dt)
        res[src_group_id] = ses_ruptures
    res.trt = DEFAULT_TRT
    return res
Beispiel #9
0
 def zerodict(self):
     """
     Initial accumulator, a dictionary (trt_id, gsim) -> curves
     """
     zd = AccumDict()
     zd.calc_times = []
     zd.eff_ruptures = AccumDict()
     return zd
Beispiel #10
0
 def zerodict(self):
     """
     Initial accumulator, a dictionary (grp_id, gsim) -> curves
     """
     zd = AccumDict()
     zd.calc_times = []
     zd.eff_ruptures = AccumDict()
     return zd
def compute_ruptures(sources, src_filter, gsims, param, monitor):
    """
    :param sources: a list with a single UCERF source
    :param src_filter: a SourceFilter instance
    :param gsims: a list of GSIMs
    :param param: extra parameters
    :param monitor: a Monitor instance
    :returns: an AccumDict grp_id -> EBRuptures
    """
    [src] = sources
    res = AccumDict()
    res.calc_times = AccumDict()
    serial = 1
    sampl_mon = monitor('sampling ruptures', measuremem=True)
    filt_mon = monitor('filtering ruptures', measuremem=False)
    res.trt = DEFAULT_TRT
    t0 = time.time()
    ebruptures = []
    background_sids = src.get_background_sids(src_filter)
    sitecol = src_filter.sitecol
    idist = src_filter.integration_distance
    for sample in range(param['samples']):
        for ses_idx, ses_seed in param['ses_seeds']:
            seed = sample * event_based.TWO16 + ses_seed
            with sampl_mon:
                rups, n_occs = src.generate_event_set(background_sids,
                                                      src_filter, seed)
            with filt_mon:
                for rup, n_occ in zip(rups, n_occs):
                    rup.seed = seed
                    try:
                        r_sites, rrup = idist.get_closest(sitecol, rup)
                    except FarAwayRupture:
                        continue
                    indices = (numpy.arange(len(r_sites))
                               if r_sites.indices is None else r_sites.indices)
                    events = []
                    for _ in range(n_occ):
                        events.append((0, src.src_group_id, ses_idx, sample))
                    if events:
                        evs = numpy.array(events, calc.event_dt)
                        ebruptures.append(
                            calc.EBRupture(rup, indices, evs, serial))
                        serial += 1
    res.num_events = event_based.set_eids(ebruptures)
    res[src.src_group_id] = ebruptures
    res.calc_times[src.src_group_id] = {
        src.source_id:
        numpy.array([src.weight, len(sitecol),
                     time.time() - t0, 1])
    }
    if not param['save_ruptures']:
        res.events_by_grp = {
            grp_id: event_based.get_events(res[grp_id])
            for grp_id in res
        }
    res.eff_ruptures = {src.src_group_id: src.num_ruptures}
    return res
Beispiel #12
0
def classical(group, src_filter, gsims, param, monitor=Monitor()):
    """
    Compute the hazard curves for a set of sources belonging to the same
    tectonic region type for all the GSIMs associated to that TRT.
    The arguments are the same as in :func:`calc_hazard_curves`, except
    for ``gsims``, which is a list of GSIM instances.

    :returns:
        a dictionary {grp_id: pmap} with attributes .grp_ids, .calc_times,
        .eff_ruptures
    """
    grp_ids = set()
    for src in group:
        if not src.num_ruptures:
            # src.num_ruptures is set when parsing the XML, but not when
            # the source is instantiated manually, so it is set here
            src.num_ruptures = src.count_ruptures()
        grp_ids.update(src.src_group_ids)
    maxdist = src_filter.integration_distance
    imtls = param['imtls']
    trunclevel = param.get('truncation_level')
    cmaker = ContextMaker(gsims, maxdist, param, monitor)
    pmap = AccumDict({
        grp_id: ProbabilityMap(len(imtls.array), len(gsims))
        for grp_id in grp_ids
    })
    # AccumDict of arrays with 3 elements weight, nsites, calc_time
    pmap.calc_times = AccumDict(accum=numpy.zeros(3, numpy.float32))
    pmap.eff_ruptures = AccumDict()  # grp_id -> num_ruptures
    src_mutex = param.get('src_interdep') == 'mutex'
    rup_mutex = param.get('rup_interdep') == 'mutex'
    for src, s_sites in src_filter(group):  # filter now
        t0 = time.time()
        try:
            poemap = cmaker.poe_map(src, s_sites, imtls, trunclevel,
                                    not rup_mutex)
        except Exception as err:
            etype, err, tb = sys.exc_info()
            msg = '%s (source id=%s)' % (str(err), src.source_id)
            raise etype(msg).with_traceback(tb)
        if src_mutex:  # mutex sources, there is a single group
            for sid in poemap:
                pcurve = pmap[src.src_group_id].setdefault(sid, 0)
                pcurve += poemap[sid] * src.mutex_weight
        elif poemap:
            for gid in src.src_group_ids:
                pmap[gid] |= poemap
        pmap.calc_times[src.id] += numpy.array(
            [src.weight, len(s_sites),
             time.time() - t0])
        # storing the number of contributing ruptures too
        pmap.eff_ruptures += {
            gid: getattr(poemap, 'eff_ruptures', 0)
            for gid in src.src_group_ids
        }
    if src_mutex and param.get('grp_probability'):
        pmap[src.src_group_id] *= param['grp_probability']
    return pmap
Beispiel #13
0
 def zerodict(self):
     """
     Initial accumulator, a dictionary trt_model_id -> list of ruptures
     """
     smodels = self.rlzs_assoc.csm_info.source_models
     zd = AccumDict((tm.id, []) for smodel in smodels
                    for tm in smodel.trt_models)
     zd.calc_times = []
     return zd
Beispiel #14
0
def compute_ruptures(branch_info, source, sitecol, oqparam, monitor):
    """
    Returns the ruptures as a TRT set
    :param str branch_info:
        Tuple of (ltbr, branch_id, branch_weight)
    :param source:
        Instance of the UCERFSESControl object
    :param sitecol:
        Site collection :class: openquake.hazardlib.site.SiteCollection
    :param info:
        Instance of the :class: openquake.commonlib.source.CompositionInfo
    :returns:
        Dictionary of rupture instances associated to a TRT ID
    """
    integration_distance = oqparam.maximum_distance[DEFAULT_TRT]
    res = AccumDict()
    res.calc_times = AccumDict()
    serial = 1
    filter_mon = monitor('update_background_site_filter', measuremem=False)
    event_mon = monitor('sampling ruptures', measuremem=False)
    for trt_model_id, (ltbrid, branch_id, _) in enumerate(branch_info):
        t0 = time.time()
        with filter_mon:
            source.update_background_site_filter(sitecol, integration_distance)

        # set the seed before calling generate_event_set
        numpy.random.seed(oqparam.random_seed + trt_model_id)
        ses_ruptures = []
        for ses_idx in range(1, oqparam.ses_per_logic_tree_path + 1):
            with event_mon:
                rups, n_occs = source.generate_event_set(
                    branch_id, sitecol, integration_distance)
            for i, rup in enumerate(rups):
                rup.seed = oqparam.random_seed  # to think
                rrup = rup.surface.get_min_distance(sitecol.mesh)
                r_sites = sitecol.filter(rrup <= integration_distance)
                if r_sites is None:
                    continue
                indices = r_sites.indices
                events = []
                for j in range(n_occs[i]):
                    # NB: the first 0 is a placeholder for the eid that will be
                    # set later, in EventBasedRuptureCalculator.post_execute;
                    # the second 0 is the sampling ID
                    events.append((0, ses_idx, j, 0))
                if len(events):
                    ses_ruptures.append(
                        event_based.EBRupture(
                            rup, indices,
                            numpy.array(events, event_based.event_dt),
                            source.source_id, trt_model_id, serial))
                    serial += 1
        dt = time.time() - t0
        res.calc_times[trt_model_id] = (ltbrid, dt)
        res[trt_model_id] = ses_ruptures
    res.trt = DEFAULT_TRT
    return res
Beispiel #15
0
 def zerodict(self):
     """
     Initial accumulator, a dictionary (grp_id, gsim) -> curves
     """
     zd = AccumDict()
     zd.calc_times = []
     zd.eff_ruptures = AccumDict()
     self.grp_trt = self.csm_info.grp_trt()
     return zd
Beispiel #16
0
def ucerf_classical_hazard_by_branch(branchnames, ucerf_source, src_group_id,
                                     src_filter, gsims, monitor):
    """
    :param branchnames:
        a list of branch names
    :param ucerf_source:
        a source-like object for the UCERF model
    :param src_group_id:
        an ordinal number for the source
    :param source filter:
        a filter returning the sites affected by the source
    :param gsims:
        a list of GSIMs
    :param monitor:
        a monitor instance
    :returns:
        an AccumDict rlz -> curves
    """
    truncation_level = monitor.oqparam.truncation_level
    imtls = monitor.oqparam.imtls
    trt = ucerf_source.tectonic_region_type
    max_dist = monitor.oqparam.maximum_distance[trt]
    dic = AccumDict()
    dic.bbs = []
    dic.calc_times = []
    for branchname in branchnames:
        # Two step process here - the first generates the hazard curves from
        # the rupture sets
        monitor.eff_ruptures = 0
        # Apply the initial rupture to site filtering
        rupset_idx = ucerf_source.get_rupture_indices(branchname)
        rupset_idx, s_sites = \
            ucerf_source.filter_sites_by_distance_from_rupture_set(
                rupset_idx, src_filter.sitecol, max_dist)

        if len(s_sites):
            dic[src_group_id] = hazard_curves_per_rupture_subset(
                rupset_idx, ucerf_source, src_filter, imtls, gsims,
                truncation_level, bbs=dic.bbs, monitor=monitor)

        else:
            dic[src_group_id] = ProbabilityMap(len(imtls.array), len(gsims))
        dic.calc_times += monitor.calc_times  # added by pmap_from_grp
        dic.eff_ruptures = {src_group_id: monitor.eff_ruptures}  # idem
        logging.info('Branch %s', branchname)
        # Get the background point sources
        background_sids = ucerf_source.get_background_sids(
            src_filter.sitecol, max_dist)
        bckgnd_sources = ucerf_source.get_background_sources(background_sids)
        if bckgnd_sources:
            pmap = pmap_from_grp(
                bckgnd_sources, src_filter, imtls, gsims, truncation_level,
                bbs=dic.bbs, monitor=monitor)
            dic[src_group_id] |= pmap
            dic.eff_ruptures[src_group_id] += monitor.eff_ruptures
            dic.calc_times += monitor.calc_times
    return dic
Beispiel #17
0
def compute_hazard(sources, src_filter, rlzs_by_gsim, param, monitor):
    """
    :param sources: a list with a single UCERF source
    :param src_filter: a SourceFilter instance
    :param rlzs_by_gsim: a dictionary gsim -> rlzs
    :param param: extra parameters
    :param monitor: a Monitor instance
    :returns: an AccumDict grp_id -> EBRuptures
    """
    [src] = sources
    res = AccumDict()
    res.calc_times = []
    serial = 1
    sampl_mon = monitor('sampling ruptures', measuremem=True)
    filt_mon = monitor('filtering ruptures', measuremem=False)
    res.trt = DEFAULT_TRT
    ebruptures = []
    background_sids = src.get_background_sids(src_filter)
    sitecol = src_filter.sitecol
    cmaker = ContextMaker(rlzs_by_gsim, src_filter.integration_distance)
    for sample in range(param['samples']):
        for ses_idx, ses_seed in param['ses_seeds']:
            seed = sample * TWO16 + ses_seed
            with sampl_mon:
                rups, n_occs = generate_event_set(src, background_sids,
                                                  src_filter, seed)
            with filt_mon:
                for rup, n_occ in zip(rups, n_occs):
                    rup.serial = serial
                    try:
                        rup.sctx, rup.dctx = cmaker.make_contexts(sitecol, rup)
                        indices = rup.sctx.sids
                    except FarAwayRupture:
                        continue
                    events = []
                    for _ in range(n_occ):
                        events.append((0, src.src_group_id, ses_idx, sample))
                    if events:
                        evs = numpy.array(events, stochastic.event_dt)
                        ebruptures.append(EBRupture(rup, src.id, indices, evs))
                        serial += 1
    res.num_events = len(stochastic.set_eids(ebruptures))
    res['ruptures'] = {src.src_group_id: ebruptures}
    if param['save_ruptures']:
        res.ruptures_by_grp = {src.src_group_id: ebruptures}
    else:
        res.events_by_grp = {
            src.src_group_id: event_based.get_events(ebruptures)
        }
    res.eff_ruptures = {src.src_group_id: src.num_ruptures}
    if param.get('gmf'):
        getter = getters.GmfGetter(rlzs_by_gsim, ebruptures, sitecol,
                                   param['oqparam'], param['min_iml'],
                                   param['samples'])
        res.update(getter.compute_gmfs_curves(monitor))
    return res
Beispiel #18
0
 def zerodict(self):
     """
     Initial accumulator, a dictionary (grp_id, gsim) -> curves
     """
     zd = AccumDict()
     zd.calc_times = []
     zd.eff_ruptures = AccumDict()
     self.eid = collections.Counter()  # sm_id -> event_id
     self.sm_by_grp = self.csm.info.get_sm_by_grp()
     return zd
Beispiel #19
0
def count_eff_ruptures(sources, sitecol, gsims, monitor):
    """
    Count the number of ruptures contained in the given sources and return
    a dictionary src_group_id -> num_ruptures. All sources belong to the
    same tectonic region type.
    """
    acc = AccumDict()
    acc.grp_id = sources[0].src_group_id
    acc.calc_times = []
    acc.eff_ruptures = {acc.grp_id: sum(src.num_ruptures for src in sources)}
    return acc
Beispiel #20
0
def classical(sources, sitecol, siteidx, rlzs_assoc, monitor):
    """
    :param sources:
        a non-empty sequence of sources of homogeneous tectonic region type
    :param sitecol:
        a SiteCollection instance
    :param siteidx:
        index of the first site (0 if there is a single tile)
    :param rlzs_assoc:
        a RlzsAssoc instance
    :param monitor:
        a monitor instance
    :returns:
        an AccumDict rlz -> curves
    """
    truncation_level = monitor.oqparam.truncation_level
    imtls = monitor.oqparam.imtls
    trt_model_id = sources[0].trt_model_id
    # sanity check: the trt_model must be the same for all sources
    for src in sources[1:]:
        assert src.trt_model_id == trt_model_id
    gsims = rlzs_assoc.gsims_by_trt_id[trt_model_id]
    trt = sources[0].tectonic_region_type
    try:
        max_dist = monitor.oqparam.maximum_distance[trt]
    except KeyError:
        max_dist = monitor.oqparam.maximum_distance['default']

    dic = AccumDict()
    dic.siteslice = slice(siteidx, siteidx + len(sitecol))
    if monitor.oqparam.poes_disagg:
        sm_id = rlzs_assoc.get_sm_id(trt_model_id)
        dic.bbs = [BoundingBox(sm_id, sid) for sid in sitecol.sids]
    else:
        dic.bbs = []
    # NB: the source_site_filter below is ESSENTIAL for performance inside
    # hazard_curves_per_trt, since it reduces the full site collection
    # to a filtered one *before* doing the rupture filtering
    curves_by_gsim = hazard_curves_per_trt(
        sources,
        sitecol,
        imtls,
        gsims,
        truncation_level,
        source_site_filter=source_site_distance_filter(max_dist),
        maximum_distance=max_dist,
        bbs=dic.bbs,
        monitor=monitor)
    dic.calc_times = monitor.calc_times  # added by hazard_curves_per_trt
    dic.eff_ruptures = {trt_model_id: monitor.eff_ruptures}  # idem
    for gsim, curves in zip(gsims, curves_by_gsim):
        dic[trt_model_id, str(gsim)] = curves
    return dic
Beispiel #21
0
 def zerodict(self):
     """
     Initial accumulator, a dict grp_id -> ProbabilityMap(L, G)
     """
     csm_info = self.csm.info
     zd = AccumDict()
     num_levels = len(self.oqparam.imtls.array)
     for grp in self.csm.src_groups:
         num_gsims = len(csm_info.gsim_lt.get_gsims(grp.trt))
         zd[grp.id] = ProbabilityMap(num_levels, num_gsims)
     zd.calc_times = []
     zd.eff_ruptures = AccumDict()  # grp_id -> eff_ruptures
     return zd
Beispiel #22
0
 def zerodict(self):
     """
     Initial accumulator, a dictionary (trt_id, gsim) -> curves
     """
     zc = zero_curves(len(self.sitecol.complete), self.oqparam.imtls)
     zd = AccumDict((key, zc) for key in self.rlzs_assoc)
     zd.calc_times = []
     zd.eff_ruptures = AccumDict()  # trt_id -> eff_ruptures
     zd.bb_dict = {
         (smodel.ordinal, site.id): BoundingBox(smodel.ordinal, site.id)
         for site in self.sitecol for smodel in self.csm.source_models
     } if self.oqparam.poes_disagg else {}
     return zd
Beispiel #23
0
    def execute(self):
        """
        Split the computation by tiles which are run in parallel.
        """
        acc = AccumDict(
            {trt_gsim: zero_curves(len(self.sitecol), self.oqparam.imtls)
             for trt_gsim in self.rlzs_assoc})
        acc.calc_times = []
        acc.n = len(self.sitecol)
        hint = math.ceil(acc.n / self.oqparam.sites_per_tile)
        tiles = self.sitecol.split_in_tiles(hint)
        logging.info('Generating %d tiles of %d sites each',
                     len(tiles), len(tiles[0]))
        sources = self.csm.get_sources()
        rlzs_assoc = self.csm.get_rlzs_assoc()
        ctasks = self.oqparam.concurrent_tasks or 1
        maxweight = math.ceil(self.csm.weight / ctasks)
        siteidx = 0
        tmanagers = []
        maximum_distance = self.oqparam.maximum_distance
        # try to produce more tasks than self.oqparam.concurrent_tasks
        num_blocks = math.ceil(self.MORE_TASKS * ctasks / len(tiles))
        splitmap = {}
        for i, tile in enumerate(tiles, 1):
            monitor = self.monitor.new()
            monitor.oqparam = self.oqparam
            with self.monitor('filtering sources per tile', autoflush=True):
                filtered_sources = [
                    src for src in sources
                    if src.filter_sites_by_distance_to_source(
                        maximum_distance, tile) is not None]
                if not filtered_sources:
                    continue
            blocks = split_in_blocks(
                split_sources(sources, maxweight, splitmap), num_blocks,
                weight=operator.attrgetter('weight'),
                key=operator.attrgetter('trt_model_id'))
            tm = parallel.starmap(
                classical,
                ((blk, tile, siteidx, rlzs_assoc, monitor) for blk in blocks),
                name='tile_%d/%d' % (i, len(tiles)))
            tmanagers.append(tm)
            siteidx += len(tile)

        logging.info('Total number of tasks submitted: %d',
                     sum(len(tm.results) for tm in tmanagers))
        for tm in tmanagers:
            tm.reduce(self.agg_dicts, acc)
        self.rlzs_assoc = self.csm.get_rlzs_assoc(
            partial(is_effective_trt_model, acc))
        return acc
def compute_ruptures(sources, src_filter, gsims, param, monitor):
    """
    :param sources: a list with a single UCERF source
    :param src_filter: a SourceFilter instance
    :param gsims: a list of GSIMs
    :param param: extra parameters
    :param monitor: a Monitor instance
    :returns: an AccumDict grp_id -> EBRuptures
    """
    [src] = sources
    res = AccumDict()
    res.calc_times = []
    serial = 1
    sampl_mon = monitor('sampling ruptures', measuremem=True)
    filt_mon = monitor('filtering ruptures', measuremem=False)
    res.trt = DEFAULT_TRT
    ebruptures = []
    background_sids = src.get_background_sids(src_filter)
    sitecol = src_filter.sitecol
    cmaker = ContextMaker(gsims, src_filter.integration_distance)
    for sample in range(param['samples']):
        for ses_idx, ses_seed in param['ses_seeds']:
            seed = sample * TWO16 + ses_seed
            with sampl_mon:
                rups, n_occs = generate_event_set(src, background_sids,
                                                  src_filter, seed)
            with filt_mon:
                for rup, n_occ in zip(rups, n_occs):
                    rup.serial = serial
                    rup.seed = seed
                    try:
                        rup.sctx, rup.dctx = cmaker.make_contexts(sitecol, rup)
                        indices = rup.sctx.sids
                    except FarAwayRupture:
                        continue
                    events = []
                    for _ in range(n_occ):
                        events.append((0, src.src_group_id, ses_idx, sample))
                    if events:
                        evs = numpy.array(events, stochastic.event_dt)
                        ebruptures.append(EBRupture(rup, indices, evs))
                        serial += 1
    res.num_events = len(stochastic.set_eids(ebruptures))
    res[src.src_group_id] = ebruptures
    if not param['save_ruptures']:
        res.events_by_grp = {
            grp_id: event_based.get_events(res[grp_id])
            for grp_id in res
        }
    res.eff_ruptures = {src.src_group_id: src.num_ruptures}
    return res
def compute_hazard(sources, src_filter, rlzs_by_gsim, param, monitor):
    """
    :param sources: a list with a single UCERF source
    :param src_filter: a SourceFilter instance
    :param rlzs_by_gsim: a dictionary gsim -> rlzs
    :param param: extra parameters
    :param monitor: a Monitor instance
    :returns: an AccumDict grp_id -> EBRuptures
    """
    [src] = sources
    res = AccumDict()
    res.calc_times = []
    serial = 1
    sampl_mon = monitor('sampling ruptures', measuremem=True)
    filt_mon = monitor('filtering ruptures', measuremem=False)
    res.trt = DEFAULT_TRT
    background_sids = src.get_background_sids(src_filter)
    sitecol = src_filter.sitecol
    cmaker = ContextMaker(rlzs_by_gsim, src_filter.integration_distance)
    num_ses = param['ses_per_logic_tree_path']
    samples = getattr(src, 'samples', 1)
    n_occ = AccumDict(accum=numpy.zeros((samples, num_ses), numpy.uint16))
    with sampl_mon:
        for sam_idx in range(samples):
            for ses_idx, ses_seed in param['ses_seeds']:
                seed = sam_idx * TWO16 + ses_seed
                rups, occs = generate_event_set(src, background_sids,
                                                src_filter, seed)
                for rup, occ in zip(rups, occs):
                    n_occ[rup][sam_idx, ses_idx] = occ
                    rup.serial = serial
                    serial += 1
    with filt_mon:
        rlzs = numpy.concatenate(list(rlzs_by_gsim.values()))
        ebruptures = stochastic.build_eb_ruptures(src, rlzs, num_ses, cmaker,
                                                  sitecol, n_occ.items())
    res.num_events = sum(ebr.multiplicity for ebr in ebruptures)
    res['ruptures'] = {src.src_group_id: ebruptures}
    if param['save_ruptures']:
        res.ruptures_by_grp = {src.src_group_id: ebruptures}
    else:
        res.events_by_grp = {
            src.src_group_id: event_based.get_events(ebruptures)
        }
    res.eff_ruptures = {src.src_group_id: src.num_ruptures}
    if param.get('gmf'):
        getter = getters.GmfGetter(rlzs_by_gsim, ebruptures, sitecol,
                                   param['oqparam'], param['min_iml'], samples)
        res.update(getter.compute_gmfs_curves(monitor))
    return res
Beispiel #26
0
 def zerodict(self):
     """
     Initial accumulator, a dictionary (trt_id, gsim) -> curves
     """
     zc = zero_curves(len(self.sitecol.complete), self.oqparam.imtls)
     zd = AccumDict((key, zc) for key in self.rlzs_assoc)
     zd.calc_times = []
     zd.eff_ruptures = AccumDict()  # trt_id -> eff_ruptures
     zd.bb_dict = {
         (smodel.ordinal, site.id): BoundingBox(smodel.ordinal, site.id)
         for site in self.sitecol
         for smodel in self.csm.source_models
     } if self.oqparam.poes_disagg else {}
     return zd
Beispiel #27
0
def compute_ruptures(sources, src_filter, gsims, monitor):
    """
    :param sources:
        List of commonlib.source.Source tuples
    :param src_filter:
        a source site filter
    :param gsims:
        a list of GSIMs for the current tectonic region model
    :param monitor:
        monitor instance
    :returns:
        a dictionary src_group_id -> [Rupture instances]
    """
    # NB: by construction each block is a non-empty list with
    # sources of the same src_group_id
    grp_id = sources[0].src_group_id
    trt = sources[0].tectonic_region_type
    eb_ruptures = []
    calc_times = []
    rup_mon = monitor('filtering ruptures', measuremem=False)
    num_samples = monitor.samples
    num_events = 0

    # Compute and save stochastic event sets
    for src, s_sites in src_filter(sources):
        t0 = time.time()
        if s_sites is None:
            continue
        max_dist = src_filter.integration_distance[trt]
        rupture_filter = functools.partial(
            filter_sites_by_distance_to_rupture,
            integration_distance=max_dist, sites=s_sites)
        num_occ_by_rup = sample_ruptures(
            src, monitor.ses_per_logic_tree_path, num_samples,
            monitor.seed)
        # NB: the number of occurrences is very low, << 1, so it is
        # more efficient to filter only the ruptures that occur, i.e.
        # to call sample_ruptures *before* the filtering
        for ebr in build_eb_ruptures(
                src, num_occ_by_rup, rupture_filter, monitor.seed, rup_mon):
            eb_ruptures.append(ebr)
            num_events += ebr.multiplicity
        dt = time.time() - t0
        calc_times.append((src.id, dt))
    res = AccumDict({grp_id: eb_ruptures})
    res.num_events = num_events
    res.calc_times = calc_times
    res.rup_data = {grp_id: calc.RuptureData(trt, gsims).to_array(eb_ruptures)}
    return res
Beispiel #28
0
def compute_ruptures(sources, sitecol, gsims, monitor):
    """
    :param sources: a sequence of UCERF sources
    :param sitecol: a SiteCollection instance
    :param gsims: a list of GSIMs
    :param monitor: a Monitor instance
    :returns: an AccumDict grp_id -> EBRuptures
    """
    [src] = sources  # there is a single source per UCERF branch
    integration_distance = monitor.maximum_distance[DEFAULT_TRT]
    res = AccumDict()
    res.calc_times = AccumDict()
    serial = 1
    event_mon = monitor('sampling ruptures', measuremem=False)
    res.num_events = 0
    res.trt = DEFAULT_TRT
    t0 = time.time()
    # set the seed before calling generate_event_set
    numpy.random.seed(monitor.seed + src.src_group_id)
    ebruptures = []
    eid = 0
    src.build_idx_set()
    background_sids = src.get_background_sids(sitecol, integration_distance)
    for ses_idx in range(1, monitor.ses_per_logic_tree_path + 1):
        with event_mon:
            rups, n_occs = src.generate_event_set(background_sids)
        for rup, n_occ in zip(rups, n_occs):
            rup.seed = monitor.seed  # to think
            rrup = rup.surface.get_min_distance(sitecol.mesh)
            r_sites = sitecol.filter(rrup <= integration_distance)
            if r_sites is None:
                continue
            indices = r_sites.indices
            events = []
            for occ in range(n_occ):
                events.append((eid, ses_idx, occ, 0))  # 0 is the sampling
                eid += 1
            if events:
                ebruptures.append(
                    event_based.EBRupture(
                        rup, indices,
                        numpy.array(events, event_based.event_dt),
                        src.source_id, src.src_group_id, serial))
                serial += 1
                res.num_events += len(events)
        res[src.src_group_id] = ebruptures
        res.calc_times[src.src_group_id] = (
            src.source_id, len(sitecol), time.time() - t0)
    return res
Beispiel #29
0
def ucerf_classical_hazard_by_rupture_set(
        rupset_idx, branchname, ucerf_source, src_group_id, sitecol,
        gsims, monitor):
    """
    :param rupset_idx:
        indices of the rupture sets
    :param branchname:
        name of the branch
    :param ucerf_source:
        an object taking the place of a source for UCERF
    :param src_group_id:
        source group index
    :param sitecol:
        a SiteCollection instance
    :param gsims:
        a list of GSIMs
    :param monitor:
        a monitor instance
    :returns:
        an AccumDict rlz -> curves
    """
    truncation_level = monitor.oqparam.truncation_level
    imtls = monitor.oqparam.imtls
    max_dist = monitor.oqparam.maximum_distance[DEFAULT_TRT]

    dic = AccumDict()
    dic.bbs = []
    dic.calc_times = []
    monitor.eff_ruptures = 0
    monitor.calc_times = []

    # Apply the initial rupture to site filtering
    rupset_idx, s_sites = \
        ucerf_source.filter_sites_by_distance_from_rupture_set(
            rupset_idx, sitecol,
            monitor.oqparam.maximum_distance[DEFAULT_TRT])

    if len(s_sites):
        dic[src_group_id] = hazard_curves_per_rupture_subset(
            rupset_idx, ucerf_source, s_sites, imtls, gsims,
            truncation_level, maximum_distance=max_dist, bbs=dic.bbs,
            monitor=monitor)

    else:
        dic[src_group_id] = ProbabilityMap(len(imtls.array), len(gsims))
    dic.calc_times += monitor.calc_times  # added by pmap_from_grp
    dic.eff_ruptures = {src_group_id: monitor.eff_ruptures}  # idem
    return dic
Beispiel #30
0
def pmap_from_trt(sources, src_filter, gsims, param, monitor=Monitor()):
    """
    Compute the hazard curves for a set of sources belonging to the same
    tectonic region type for all the GSIMs associated to that TRT.

    :returns:
        a dictionary {grp_id: pmap} with attributes .grp_ids, .calc_times,
        .eff_ruptures
    """
    maxdist = src_filter.integration_distance
    srcs = []
    grp_ids = set()
    for src in sources:
        if hasattr(src, '__iter__'):  # MultiPointSource
            srcs.extend(src)
        else:
            srcs.append(src)
        grp_ids.update(src.src_group_ids)
    del sources
    with GroundShakingIntensityModel.forbid_instantiation():
        imtls = param['imtls']
        trunclevel = param.get('truncation_level')
        cmaker = ContextMaker(gsims, maxdist)
        ctx_mon = monitor('making contexts', measuremem=False)
        pne_mons = [
            monitor('%s.get_poes' % gsim, measuremem=False) for gsim in gsims
        ]
        pmap = AccumDict({
            grp_id: ProbabilityMap(len(imtls.array), len(gsims))
            for grp_id in grp_ids
        })
        pmap.calc_times = []  # pairs (src_id, delta_t)
        pmap.eff_ruptures = AccumDict()  # grp_id -> num_ruptures
        for src, s_sites in src_filter(srcs):
            t0 = time.time()
            poe = poe_map(src, s_sites, imtls, cmaker, trunclevel, ctx_mon,
                          pne_mons)
            for grp_id in src.src_group_ids:
                pmap[grp_id] |= poe
            pmap.calc_times.append(
                (src.source_id, src.weight, len(s_sites), time.time() - t0))
            # storing the number of contributing ruptures too
            pmap.eff_ruptures += {
                grp_id: poe.eff_ruptures
                for grp_id in src.src_group_ids
            }
        return pmap
Beispiel #31
0
def classical(sources, sitecol, siteidx, rlzs_assoc, monitor):
    """
    :param sources:
        a non-empty sequence of sources of homogeneous tectonic region type
    :param sitecol:
        a SiteCollection instance
    :param siteidx:
        index of the first site (0 if there is a single tile)
    :param rlzs_assoc:
        a RlzsAssoc instance
    :param monitor:
        a monitor instance
    :returns:
        an AccumDict rlz -> curves
    """
    truncation_level = monitor.oqparam.truncation_level
    imtls = monitor.oqparam.imtls
    trt_model_id = sources[0].trt_model_id
    # sanity check: the trt_model must be the same for all sources
    for src in sources[1:]:
        assert src.trt_model_id == trt_model_id
    gsims = rlzs_assoc.gsims_by_trt_id[trt_model_id]
    trt = sources[0].tectonic_region_type
    try:
        max_dist = monitor.oqparam.maximum_distance[trt]
    except KeyError:
        max_dist = monitor.oqparam.maximum_distance['default']

    dic = AccumDict()
    dic.siteslice = slice(siteidx, siteidx + len(sitecol))
    if monitor.oqparam.poes_disagg:
        sm_id = rlzs_assoc.get_sm_id(trt_model_id)
        dic.bbs = [BoundingBox(sm_id, sid) for sid in sitecol.sids]
    else:
        dic.bbs = []
    # NB: the source_site_filter below is ESSENTIAL for performance inside
    # hazard_curves_per_trt, since it reduces the full site collection
    # to a filtered one *before* doing the rupture filtering
    curves_by_gsim = hazard_curves_per_trt(
        sources, sitecol, imtls, gsims, truncation_level,
        source_site_filter=source_site_distance_filter(max_dist),
        maximum_distance=max_dist, bbs=dic.bbs, monitor=monitor)
    dic.calc_times = monitor.calc_times  # added by hazard_curves_per_trt
    dic.eff_ruptures = {trt_model_id: monitor.eff_ruptures}  # idem
    for gsim, curves in zip(gsims, curves_by_gsim):
        dic[trt_model_id, str(gsim)] = curves
    return dic
Beispiel #32
0
def compute_ruptures(sources, src_filter, gsims, param, monitor):
    """
    :param sources:
        List of commonlib.source.Source tuples
    :param src_filter:
        a source site filter
    :param gsims:
        a list of GSIMs for the current tectonic region model
    :param param:
        a dictionary of additional parameters
    :param monitor:
        monitor instance
    :returns:
        a dictionary src_group_id -> [Rupture instances]
    """
    # NB: by construction each block is a non-empty list with
    # sources of the same src_group_id
    grp_id = sources[0].src_group_id
    eb_ruptures = []
    calc_times = []
    rup_mon = monitor('making contexts', measuremem=False)
    # Compute and save stochastic event sets
    num_ruptures = 0
    cmaker = ContextMaker(gsims, src_filter.integration_distance)
    for src, s_sites in src_filter(sources):
        t0 = time.time()
        if s_sites is None:
            continue
        num_ruptures += src.num_ruptures
        num_occ_by_rup = sample_ruptures(
            src, param['ses_per_logic_tree_path'], sources.samples,
            param['seed'])
        # NB: the number of occurrences is very low, << 1, so it is
        # more efficient to filter only the ruptures that occur, i.e.
        # to call sample_ruptures *before* the filtering
        for ebr in _build_eb_ruptures(
                src, num_occ_by_rup, cmaker, s_sites, param['seed'], rup_mon):
            eb_ruptures.append(ebr)
        dt = time.time() - t0
        calc_times.append((src.id, dt))
    res = AccumDict({grp_id: eb_ruptures})
    res.num_events = set_eids(eb_ruptures)
    res.calc_times = calc_times
    res.eff_ruptures = {grp_id: num_ruptures}
    return res
Beispiel #33
0
 def zerodict(self):
     """
     Initial accumulator, a dict grp_id -> ProbabilityMap(L, G)
     """
     zd = AccumDict()
     num_levels = len(self.oqparam.imtls.array)
     for grp in self.csm.src_groups:
         num_gsims = len(self.rlzs_assoc.gsims_by_grp_id[grp.id])
         zd[grp.id] = ProbabilityMap(num_levels, num_gsims)
     zd.calc_times = []
     zd.eff_ruptures = AccumDict()  # grp_id -> eff_ruptures
     zd.bb_dict = BBdict()
     if self.oqparam.poes_disagg or self.oqparam.iml_disagg:
         for sid in self.sitecol.sids:
             for smodel in self.csm.source_models:
                 zd.bb_dict[smodel.ordinal,
                            sid] = BoundingBox(smodel.ordinal, sid)
     return zd
Beispiel #34
0
 def zerodict(self):
     """
     Initial accumulator, a dict grp_id -> ProbabilityMap(L, G)
     """
     zd = AccumDict()
     num_levels = len(self.oqparam.imtls.array)
     for grp in self.csm.src_groups:
         num_gsims = len(self.rlzs_assoc.gsims_by_grp_id[grp.id])
         zd[grp.id] = ProbabilityMap(num_levels, num_gsims)
     zd.calc_times = []
     zd.eff_ruptures = AccumDict()  # grp_id -> eff_ruptures
     zd.bb_dict = BBdict()
     if self.oqparam.poes_disagg:
         for sid in self.sitecol.sids:
             for smodel in self.csm.source_models:
                 zd.bb_dict[smodel.ordinal, sid] = BoundingBox(
                     smodel.ordinal, sid)
     return zd
Beispiel #35
0
def count_eff_ruptures(sources, srcfilter, gsims, param, monitor):
    """
    Count the effective number of ruptures contained in the given sources
    within the integration distance and return a dictionary src_group_id ->
    num_ruptures. All sources must belong to the same tectonic region type.
    """
    acc = AccumDict()
    acc.grp_id = sources[0].src_group_id
    acc.calc_times = []
    count = 0
    for src in sources:
        t0 = time.time()
        sites = srcfilter.get_close_sites(src)
        if sites is not None:
            count += src.num_ruptures
            dt = time.time() - t0
            acc.calc_times.append((src.source_id, len(sites), dt))
    acc.eff_ruptures = {acc.grp_id: count}
    return acc
Beispiel #36
0
def pmap_from_trt(sources, src_filter, gsims, param, monitor=Monitor()):
    """
    Compute the hazard curves for a set of sources belonging to the same
    tectonic region type for all the GSIMs associated to that TRT.

    :returns:
        a dictionary {grp_id: pmap} with attributes .grp_ids, .calc_times,
        .eff_ruptures
    """
    grp_ids = set()
    for src in sources:
        grp_ids.update(src.src_group_ids)
    maxdist = src_filter.integration_distance
    srcs = sum([split_source(src) for src in sources], [])  # split first
    with GroundShakingIntensityModel.forbid_instantiation():
        imtls = param['imtls']
        trunclevel = param.get('truncation_level')
        cmaker = ContextMaker(gsims, maxdist)
        ctx_mon = monitor('make_contexts', measuremem=False)
        poe_mon = monitor('get_poes', measuremem=False)
        pmap = AccumDict({
            grp_id: ProbabilityMap(len(imtls.array), len(gsims))
            for grp_id in grp_ids
        })
        pmap.calc_times = []  # pairs (src_id, delta_t)
        pmap.eff_ruptures = AccumDict()  # grp_id -> num_ruptures
        for src, s_sites in src_filter(srcs):  # filter now
            t0 = time.time()
            poemap = cmaker.poe_map(src, s_sites, imtls, trunclevel, ctx_mon,
                                    poe_mon)
            if poemap:
                for grp_id in src.src_group_ids:
                    pmap[grp_id] |= poemap
            pmap.calc_times.append(
                (src.source_id, src.weight, len(s_sites), time.time() - t0))
            # storing the number of contributing ruptures too
            pmap.eff_ruptures += {
                grp_id: getattr(poemap, 'eff_ruptures', 0)
                for grp_id in src.src_group_ids
            }
        return pmap
Beispiel #37
0
def count_ruptures(sources, srcfilter, gsims, param, monitor):
    """
    Count the number of ruptures contained in the given sources by applying a
    raw source filtering on the integration distance. Return a dictionary
    src_group_id -> {}.
    All sources must belong to the same tectonic region type.
    """
    dic = groupby(sources, operator.attrgetter('src_group_id'))
    acc = AccumDict({grp_id: {} for grp_id in dic})
    acc.eff_ruptures = {grp_id: 0 for grp_id in dic}
    acc.calc_times = []
    for grp_id in dic:
        for src in sources:
            t0 = time.time()
            sites = srcfilter.get_close_sites(src)
            if sites is not None:
                acc.eff_ruptures[grp_id] += src.num_ruptures
                dt = time.time() - t0
                acc.calc_times.append(
                    (src.source_id, len(sites), src.weight, dt))
    return acc
Beispiel #38
0
def pmap_from_grp(group, src_filter, gsims, param, monitor=Monitor()):
    """
    Compute the hazard curves for a set of sources belonging to the same
    tectonic region type for all the GSIMs associated to that TRT.
    The arguments are the same as in :func:`calc_hazard_curves`, except
    for ``gsims``, which is a list of GSIM instances.

    :returns: a dictionary {grp_id: ProbabilityMap instance}
    """
    mutex_weight = {
        src.source_id: weight
        for src, weight in zip(group.sources, group.srcs_weights)
    }
    maxdist = src_filter.integration_distance
    srcs = sum([split_source(src) for src in group.sources], [])
    with GroundShakingIntensityModel.forbid_instantiation():
        imtls = param['imtls']
        trunclevel = param.get('truncation_level')
        cmaker = ContextMaker(gsims, maxdist)
        ctx_mon = monitor('make_contexts', measuremem=False)
        poe_mon = monitor('get_poes', measuremem=False)
        pmap = ProbabilityMap(len(imtls.array), len(gsims))
        calc_times = []  # pairs (src_id, delta_t)
        for src, s_sites in src_filter(srcs):
            t0 = time.time()
            poemap = cmaker.poe_map(src, s_sites, imtls, trunclevel, ctx_mon,
                                    poe_mon, group.rup_interdep == 'indep')
            weight = mutex_weight[src.source_id]
            for sid in poemap:
                pcurve = pmap.setdefault(sid, 0)
                pcurve += poemap[sid] * weight
            calc_times.append(
                (src.source_id, src.weight, len(s_sites), time.time() - t0))
        if group.grp_probability is not None:
            pmap *= group.grp_probability
        acc = AccumDict({group.id: pmap})
        # adding the number of contributing ruptures too
        acc.eff_ruptures = {group.id: ctx_mon.counts}
        acc.calc_times = calc_times
        return acc
Beispiel #39
0
def build_ruptures(sources, src_filter, param, monitor):
    """
    :param sources: a list with a single UCERF source
    :param src_filter: a SourceFilter instance
    :param param: extra parameters
    :param monitor: a Monitor instance
    :returns: an AccumDict grp_id -> EBRuptures
    """
    [src] = sources
    res = AccumDict()
    res.calc_times = []
    sampl_mon = monitor('sampling ruptures', measuremem=True)
    filt_mon = monitor('filtering ruptures', measuremem=False)
    res.trt = DEFAULT_TRT
    background_sids = src.get_background_sids(src_filter)
    sitecol = src_filter.sitecol
    cmaker = ContextMaker(param['gsims'], src_filter.integration_distance)
    num_ses = param['ses_per_logic_tree_path']
    samples = getattr(src, 'samples', 1)
    n_occ = AccumDict(accum=0)
    t0 = time.time()
    with sampl_mon:
        for sam_idx in range(samples):
            for ses_idx, ses_seed in param['ses_seeds']:
                seed = sam_idx * TWO16 + ses_seed
                rups, occs = generate_event_set(src, background_sids,
                                                src_filter, ses_idx, seed)
                for rup, occ in zip(rups, occs):
                    n_occ[rup] += occ
    tot_occ = sum(n_occ.values())
    dic = {'eff_ruptures': {src.src_group_id: src.num_ruptures}}
    with filt_mon:
        eb_ruptures = stochastic.build_eb_ruptures(src, num_ses, cmaker,
                                                   sitecol, n_occ.items())
        dic['rup_array'] = (stochastic.get_rup_array(eb_ruptures)
                            if eb_ruptures else ())
    dt = time.time() - t0
    dic['calc_times'] = {src.id: numpy.array([tot_occ, len(sitecol), dt], F32)}
    return dic
Beispiel #40
0
def count_ruptures(sources, srcfilter, gsims, param, monitor):
    """
    Count the number of ruptures contained in the given sources by applying a
    raw source filtering on the integration distance. Return a dictionary
    src_group_id -> {}.
    All sources must belong to the same tectonic region type.
    """
    dic = groupby(sources, lambda src: src.src_group_ids[0])
    acc = AccumDict({grp_id: {} for grp_id in dic})
    acc.eff_ruptures = {grp_id: 0 for grp_id in dic}
    acc.calc_times = AccumDict(accum=numpy.zeros(4))
    for grp_id in dic:
        for src in sources:
            t0 = time.time()
            src_id = src.source_id.split(':')[0]
            sites = srcfilter.get_close_sites(src)
            if sites is not None:
                acc.eff_ruptures[grp_id] += src.num_ruptures
                dt = time.time() - t0
                acc.calc_times[src_id] += numpy.array(
                    [src.weight, len(sites), dt, 1])
    return acc
Beispiel #41
0
def classical(sources, sitecol, gsims, monitor):
    """
    :param sources:
        a non-empty sequence of sources of homogeneous tectonic region type
    :param sitecol:
        a SiteCollection instance
    :param gsims:
        a list of GSIMs for the current tectonic region type
    :param monitor:
        a monitor instance
    :returns:
        an AccumDict rlz -> curves
    """
    truncation_level = monitor.truncation_level
    imtls = monitor.imtls
    src_group_id = sources[0].src_group_id
    # sanity check: the src_group must be the same for all sources
    for src in sources[1:]:
        assert src.src_group_id == src_group_id
    trt = sources[0].tectonic_region_type
    max_dist = monitor.maximum_distance[trt]

    dic = AccumDict()
    if monitor.poes_disagg:
        sm_id = monitor.sm_id
        dic.bbs = [BoundingBox(sm_id, sid) for sid in sitecol.sids]
    else:
        dic.bbs = []
    # NB: the source_site_filter below is ESSENTIAL for performance inside
    # pmap_from_grp, since it reduces the full site collection
    # to a filtered one *before* doing the rupture filtering
    dic[src_group_id] = pmap_from_grp(
        sources, sitecol, imtls, gsims, truncation_level,
        maximum_distance=max_dist, bbs=dic.bbs, monitor=monitor)
    dic.calc_times = monitor.calc_times  # added by pmap_from_grp
    dic.eff_ruptures = {src_group_id: monitor.eff_ruptures}  # idem
    return dic
Beispiel #42
0
def compute_ruptures(sources, src_filter, gsims, param, monitor):
    """
    :param sources:
        a sequence of sources of the same group
    :param src_filter:
        a source site filter
    :param gsims:
        a list of GSIMs for the current tectonic region model
    :param param:
        a dictionary of additional parameters
    :param monitor:
        monitor instance
    :returns:
        a dictionary src_group_id -> [Rupture instances]
    """
    # NB: by construction each block is a non-empty list with
    # sources of the same src_group_id
    grp_id = sources[0].src_group_id
    dic = sample_ruptures(sources, src_filter, gsims, param, monitor)
    res = AccumDict({grp_id: dic['eb_ruptures']})
    res.num_events = dic['num_events']
    res.calc_times = dic['calc_times']
    res.eff_ruptures = {grp_id: dic['num_ruptures']}
    return res
Beispiel #43
0
def compute_ruptures(sources, sitecol, gsims, monitor):
    """
    :param sources:
        List of commonlib.source.Source tuples
    :param sitecol:
        a :class:`openquake.hazardlib.site.SiteCollection` instance
    :param gsims:
        a list of GSIMs for the current tectonic region model
    :param monitor:
        monitor instance
    :returns:
        a dictionary src_group_id -> [Rupture instances]
    """
    # NB: by construction each block is a non-empty list with
    # sources of the same src_group_id
    src_group_id = sources[0].src_group_id
    trt = sources[0].tectonic_region_type
    max_dist = monitor.maximum_distance[trt]
    cmaker = ContextMaker(gsims)
    params = sorted(cmaker.REQUIRES_RUPTURE_PARAMETERS)
    rup_data_dt = numpy.dtype(
        [('rupserial', U32), ('multiplicity', U16),
         ('numsites', U32), ('occurrence_rate', F64)] + [
            (param, F64) for param in params])
    eb_ruptures = []
    rup_data = []
    calc_times = []
    rup_mon = monitor('filtering ruptures', measuremem=False)
    num_samples = monitor.samples
    num_events = 0

    # Compute and save stochastic event sets
    for src in sources:
        t0 = time.time()
        s_sites = src.filter_sites_by_distance_to_source(max_dist, sitecol)
        if s_sites is None:
            continue
        rupture_filter = functools.partial(
            filter_sites_by_distance_to_rupture,
            integration_distance=max_dist, sites=s_sites)
        num_occ_by_rup = sample_ruptures(
            src, monitor.ses_per_logic_tree_path, num_samples,
            monitor.seed)
        # NB: the number of occurrences is very low, << 1, so it is
        # more efficient to filter only the ruptures that occur, i.e.
        # to call sample_ruptures *before* the filtering
        for ebr in build_eb_ruptures(
                src, num_occ_by_rup, rupture_filter, monitor.seed, rup_mon):
            nsites = len(ebr.indices)
            try:
                rate = ebr.rupture.occurrence_rate
            except AttributeError:  # for nonparametric sources
                rate = numpy.nan
            rc = cmaker.make_rupture_context(ebr.rupture)
            ruptparams = tuple(getattr(rc, param) for param in params)
            rup_data.append((ebr.serial, ebr.multiplicity, nsites, rate) +
                            ruptparams)
            eb_ruptures.append(ebr)
            num_events += ebr.multiplicity
        dt = time.time() - t0
        calc_times.append((src.id, dt))
    res = AccumDict({src_group_id: eb_ruptures})
    res.num_events = num_events
    res.calc_times = calc_times
    res.rup_data = numpy.array(rup_data, rup_data_dt)
    res.trt = trt
    return res
Beispiel #44
0
def compute_ruptures_gmfs_curves(
        source_models, sitecol, rlzs_assoc, monitor):
    """
    Returns the ruptures as a TRT set
    :param source_models:
        A list of UCERF source models, one per branch
    :param sitecol:
        Site collection :class:`openquake.hazardlib.site.SiteCollection`
    :param rlzs_assoc:
        Instance of :class:`openquake.commonlib.source.RlzsAssoc`
    :param monitor:
        Instance of :class:`openquake.baselib.performance.Monitor`
    :returns:
        Dictionary of rupture instances associated to a TRT ID
    """
    oq = monitor.oqparam
    correl_model = oq.get_correl_model()
    imts = list(oq.imtls)
    min_iml = calc.fix_minimum_intensity(oq.minimum_intensity, imts)
    integration_distance = oq.maximum_distance[DEFAULT_TRT]
    res = AccumDict()
    res.calc_times = AccumDict()
    serial = 1
    event_mon = monitor('sampling ruptures', measuremem=False)
    res['ruptures'] = rupdic = AccumDict()
    rupdic.num_events = 0
    rupdic.trt = DEFAULT_TRT
    rlzs_by_grp = rlzs_assoc.get_rlzs_by_grp_id()
    for grp_id, source_model in enumerate(source_models):
        [grp] = source_model.src_groups  # one source group per source model
        [ucerf] = grp  # one source per source group
        t0 = time.time()
        # set the seed before calling generate_event_set
        numpy.random.seed(oq.random_seed + grp_id)
        ses_ruptures = []
        eid = 0
        ucerf.idx_set = ucerf.build_idx_set()
        background_sids = ucerf.get_background_sids(
            sitecol, integration_distance)
        for ses_idx in range(1, oq.ses_per_logic_tree_path + 1):
            with event_mon:
                rups, n_occs = ucerf.generate_event_set(background_sids)
            for i, rup in enumerate(rups):
                rup.seed = oq.random_seed  # to think
                rrup = rup.surface.get_min_distance(sitecol.mesh)
                r_sites = sitecol.filter(rrup <= integration_distance)
                if r_sites is None:
                    continue
                indices = r_sites.indices
                events = []
                for j in range(n_occs[i]):
                    events.append((eid, ses_idx, j, 0))  # 0 is the sampling ID
                    eid += 1
                if events:
                    ses_ruptures.append(
                        event_based.EBRupture(
                            rup, indices,
                            numpy.array(events, event_based.event_dt),
                            ucerf.source_id, grp_id, serial))
                    serial += 1
                    rupdic.num_events += len(events)
        res['ruptures'][grp_id] = ses_ruptures
        gsims = [dic[DEFAULT_TRT] for dic in rlzs_assoc.gsim_by_trt]
        gg = riskinput.GmfGetter(gsims, ses_ruptures, sitecol,
                                 imts, min_iml, oq.truncation_level,
                                 correl_model, rlzs_assoc.samples[grp_id])
        rlzs = rlzs_by_grp[grp_id]
        res.update(event_based.compute_gmfs_and_curves(gg, rlzs, monitor))
        res.calc_times[grp_id] = (ucerf.source_id, len(sitecol),
                                  time.time() - t0)
    return res
Beispiel #45
0
def compute_ruptures(sources, sitecol, siteidx, rlzs_assoc, monitor):
    """
    :param sources:
        List of commonlib.source.Source tuples
    :param sitecol:
        a :class:`openquake.hazardlib.site.SiteCollection` instance
    :param siteidx:
        always equal to 0
    :param rlzs_assoc:
        a :class:`openquake.commonlib.source.RlzsAssoc` instance
    :param monitor:
        monitor instance
    :returns:
        a dictionary trt_model_id -> [Rupture instances]
    """
    assert siteidx == 0, (
        'siteidx can be nonzero only for the classical_tiling calculations: '
        'tiling with the EventBasedRuptureCalculator is an error')
    # NB: by construction each block is a non-empty list with
    # sources of the same trt_model_id
    trt_model_id = sources[0].trt_model_id
    oq = monitor.oqparam
    trt = sources[0].tectonic_region_type
    max_dist = oq.maximum_distance[trt]
    cmaker = ContextMaker(rlzs_assoc.gsims_by_trt_id[trt_model_id])
    params = cmaker.REQUIRES_RUPTURE_PARAMETERS
    rup_data_dt = numpy.dtype([('rupserial', U32), ('multiplicity',
                                                    U16), ('numsites', U32)] +
                              [(param, F32) for param in params])
    eb_ruptures = []
    rup_data = []
    calc_times = []
    rup_mon = monitor('filtering ruptures', measuremem=False)
    num_samples = rlzs_assoc.samples[trt_model_id]

    # Compute and save stochastic event sets
    for src in sources:
        t0 = time.time()
        s_sites = src.filter_sites_by_distance_to_source(max_dist, sitecol)
        if s_sites is None:
            continue
        rupture_filter = functools.partial(filter_sites_by_distance_to_rupture,
                                           integration_distance=max_dist,
                                           sites=s_sites)
        num_occ_by_rup = sample_ruptures(src, oq.ses_per_logic_tree_path,
                                         num_samples, rlzs_assoc.seed)
        # NB: the number of occurrences is very low, << 1, so it is
        # more efficient to filter only the ruptures that occur, i.e.
        # to call sample_ruptures *before* the filtering
        for ebr in build_eb_ruptures(src, num_occ_by_rup, rupture_filter,
                                     oq.random_seed, rup_mon):
            nsites = len(ebr.indices)
            rc = cmaker.make_rupture_context(ebr.rupture)
            ruptparams = tuple(getattr(rc, param) for param in params)
            rup_data.append((ebr.serial, len(ebr.etags), nsites) + ruptparams)
            eb_ruptures.append(ebr)
        dt = time.time() - t0
        calc_times.append((src.id, dt))
    res = AccumDict({trt_model_id: eb_ruptures})
    res.calc_times = calc_times
    res.rup_data = numpy.array(rup_data, rup_data_dt)
    res.trt = trt
    return res
Beispiel #46
0
    def execute(self):
        """
        Run in parallel `core_task(sources, sitecol, monitor)`, by
        parallelizing on the sources according to their weight and
        tectonic region type.
        """
        monitor = self.monitor.new(self.core_task.__name__)
        monitor.oqparam = oq = self.oqparam
        ucerf_source = self.src_group.sources[0]
        max_dist = oq.maximum_distance[DEFAULT_TRT]
        acc = AccumDict({
            grp_id: ProbabilityMap(len(oq.imtls.array), len(gsims))
            for grp_id, gsims in self.rlzs_assoc.gsims_by_grp_id.items()})
        acc.calc_times = []
        acc.eff_ruptures = AccumDict()  # grp_id -> eff_ruptures
        acc.bb_dict = {}

        if len(self.csm) > 1:
            # when multiple branches, parallelise by branch
            branches = [br.value for br in self.smlt.branches.values()]
            rup_res = parallel.starmap(
                ucerf_classical_hazard_by_branch,
                self.gen_args(branches, ucerf_source, monitor)).submit_all()
        else:
            # single branch
            gsims = self.rlzs_assoc.gsims_by_grp_id[0]
            [(branch_id, branch)] = self.smlt.branches.items()
            branchname = branch.value
            ucerf_source.src_group_id = 0
            ucerf_source.weight = 1
            ucerf_source.nsites = len(self.sitecol)
            self.infos[0, ucerf_source.source_id] = source.SourceInfo(
                ucerf_source)
            logging.info('Getting the background point sources')
            with self.monitor('getting background sources', autoflush=True):
                ucerf_source.build_idx_set()
                background_sids = ucerf_source.get_background_sids(
                    self.sitecol, max_dist)
                bckgnd_sources = ucerf_source.get_background_sources(
                    background_sids)

            # parallelize on the background sources, small tasks
            args = (bckgnd_sources, self.sitecol, oq.imtls,
                    gsims, self.oqparam.truncation_level,
                    'SourceSitesFilter', max_dist, (), monitor)
            bg_res = parallel.apply(
                pmap_from_grp, args,
                concurrent_tasks=self.oqparam.concurrent_tasks).submit_all()

            # parallelize by rupture subsets
            tasks = self.oqparam.concurrent_tasks * 2  # they are big tasks
            rup_sets = ucerf_source.get_rupture_indices(branchname)
            rup_res = parallel.apply(
                ucerf_classical_hazard_by_rupture_set,
                (rup_sets, branchname, ucerf_source, self.src_group.id,
                 self.sitecol, gsims, monitor),
                concurrent_tasks=tasks).submit_all()

            # compose probabilities from background sources
            for pmap in bg_res:
                acc[0] |= pmap
            self.save_data_transfer(bg_res)

        pmap_by_grp_id = functools.reduce(self.agg_dicts, rup_res, acc)
        with self.monitor('store source_info', autoflush=True):
            self.store_source_info(self.infos)
            self.save_data_transfer(rup_res)
        self.datastore['csm_info'] = self.csm.info
        self.rlzs_assoc = self.csm.info.get_rlzs_assoc(
            functools.partial(self.count_eff_ruptures, pmap_by_grp_id))
        self.datastore['csm_info'] = self.csm.info
        return pmap_by_grp_id
Beispiel #47
0
def compute_ruptures(sources, sitecol, siteidx, rlzs_assoc, monitor):
    """
    :param sources:
        List of commonlib.source.Source tuples
    :param sitecol:
        a :class:`openquake.hazardlib.site.SiteCollection` instance
    :param siteidx:
        always equal to 0
    :param rlzs_assoc:
        a :class:`openquake.commonlib.source.RlzsAssoc` instance
    :param monitor:
        monitor instance
    :returns:
        a dictionary src_group_id -> [Rupture instances]
    """
    assert siteidx == 0, (
        'siteidx can be nonzero only for the classical_tiling calculations: '
        'tiling with the EventBasedRuptureCalculator is an error')
    # NB: by construction each block is a non-empty list with
    # sources of the same src_group_id
    src_group_id = sources[0].src_group_id
    oq = monitor.oqparam
    trt = sources[0].tectonic_region_type
    max_dist = oq.maximum_distance[trt]
    cmaker = ContextMaker(rlzs_assoc.gsims_by_grp_id[src_group_id])
    params = sorted(cmaker.REQUIRES_RUPTURE_PARAMETERS)
    rup_data_dt = numpy.dtype(
        [('rupserial', U32), ('multiplicity', U16),
         ('numsites', U32), ('occurrence_rate', F32)] + [
            (param, F32) for param in params])
    eb_ruptures = []
    rup_data = []
    calc_times = []
    rup_mon = monitor('filtering ruptures', measuremem=False)
    num_samples = rlzs_assoc.samples[src_group_id]

    # Compute and save stochastic event sets
    for src in sources:
        t0 = time.time()
        s_sites = src.filter_sites_by_distance_to_source(max_dist, sitecol)
        if s_sites is None:
            continue
        rupture_filter = functools.partial(
            filter_sites_by_distance_to_rupture,
            integration_distance=max_dist, sites=s_sites)
        num_occ_by_rup = sample_ruptures(
            src, oq.ses_per_logic_tree_path, num_samples,
            rlzs_assoc.seed)
        # NB: the number of occurrences is very low, << 1, so it is
        # more efficient to filter only the ruptures that occur, i.e.
        # to call sample_ruptures *before* the filtering
        for ebr in build_eb_ruptures(
                src, num_occ_by_rup, rupture_filter, oq.random_seed, rup_mon):
            nsites = len(ebr.indices)
            try:
                rate = ebr.rupture.occurrence_rate
            except AttributeError:  # for nonparametric sources
                rate = numpy.nan
            rc = cmaker.make_rupture_context(ebr.rupture)
            ruptparams = tuple(getattr(rc, param) for param in params)
            rup_data.append((ebr.serial, len(ebr.etags), nsites, rate) +
                            ruptparams)
            eb_ruptures.append(ebr)
        dt = time.time() - t0
        calc_times.append((src.id, dt))
    res = AccumDict({src_group_id: eb_ruptures})
    res.calc_times = calc_times
    res.rup_data = numpy.array(rup_data, rup_data_dt)
    res.trt = trt
    return res