def compute_disagg(dstore, idxs, cmaker, iml3, trti, bin_edges, oq, monitor): # see https://bugs.launchpad.net/oq-engine/+bug/1279247 for an explanation # of the algorithm used """ :param dstore a DataStore instance :param idxs: an array of indices to ruptures :param cmaker: a :class:`openquake.hazardlib.gsim.base.ContextMaker` instance :param iml3: an ArrayWrapper of shape (N, P, Z) with an attribute imt :param trti: tectonic region type index :param bin_egdes: a quintet (mag_edges, dist_edges, lon_edges, lat_edges, eps_edges) :param monitor: monitor of the currently running job :returns: a dictionary sid -> 8D-array """ with monitor('reading rupdata', measuremem=True): dstore.open('r') sitecol = dstore['sitecol'] rupdata = {k: dstore['rup/' + k][idxs] for k in dstore['rup']} RuptureContext.temporal_occurrence_model = PoissonTOM( oq.investigation_time) pne_mon = monitor('disaggregate_pne', measuremem=False) mat_mon = monitor('build_disagg_matrix', measuremem=True) gmf_mon = monitor('disagg mean_std', measuremem=False) for sid, iml2 in zip(sitecol.sids, iml3): singlesite = sitecol.filtered([sid]) bins = disagg.get_bins(bin_edges, sid) gsim_by_z = {} for z in range(iml3.shape[-1]): try: gsim = cmaker.gsim_by_rlzi[iml3.rlzs[sid, z]] except KeyError: pass else: gsim_by_z[z] = gsim ctxs = [] ok, = numpy.where( rupdata['rrup_'][:, sid] <= cmaker.maximum_distance(cmaker.trt)) for ridx in ok: # consider only the ruptures close to the site ctx = RuptureContext((par, rupdata[par][ridx]) for par in rupdata if not par.endswith('_')) for par in rupdata: if par.endswith('_'): setattr(ctx, par[:-1], rupdata[par][ridx, [sid]]) ctxs.append(ctx) if not ctxs: continue eps3 = disagg._eps3(cmaker.trunclevel, oq.num_epsilon_bins) matrix = numpy.zeros([len(b) - 1 for b in bins] + list(iml2.shape)) for z, gsim in gsim_by_z.items(): with gmf_mon: ms = disagg.get_mean_stdv(singlesite, ctxs, iml3.imt, gsim) bdata = disagg.disaggregate( ms, ctxs, iml3.imt, iml2[:, z], eps3, pne_mon) if bdata.pnes.sum(): with mat_mon: matrix[..., z] = disagg.build_disagg_matrix(bdata, bins) if matrix.any(): yield {'trti': trti, 'imti': iml3.imti, sid: matrix}
def compute_disagg(dstore, slc, cmaker, hmap4, magi, bin_edges, monitor): # see https://bugs.launchpad.net/oq-engine/+bug/1279247 for an explanation # of the algorithm used """ :param dstore: a DataStore instance :param slc: a slice of ruptures :param cmaker: a :class:`openquake.hazardlib.gsim.base.ContextMaker` instance :param hmap4: an ArrayWrapper of shape (N, M, P, Z) :param magi: magnitude bin indices :param bin_egdes: a quartet (dist_edges, lon_edges, lat_edges, eps_edges) :param monitor: monitor of the currently running job :returns: a dictionary sid, imti -> 6D-array """ with monitor('reading contexts', measuremem=True): dstore.open('r') allctxs = cmaker.read_ctxs(dstore, slc) for magidx, ctx in zip(magi, allctxs): ctx.magi = magidx dis_mon = monitor('disaggregate', measuremem=False) ms_mon = monitor('disagg mean_std', measuremem=True) N, M, P, Z = hmap4.shape g_by_z = AccumDict(accum={}) # dict s -> z -> g for g, rlzs in enumerate(cmaker.gsims.values()): for (s, z), r in numpy.ndenumerate(hmap4.rlzs): if r in rlzs: g_by_z[s][z] = g eps3 = disagg._eps3(cmaker.trunclevel, cmaker.num_epsilon_bins) imts = [from_string(im) for im in cmaker.imtls] for magi, ctxs in groupby(allctxs, operator.attrgetter('magi')).items(): res = {'trti': cmaker.trti, 'magi': magi} with ms_mon: # compute mean and std (N * U * M * G * 16 bytes) disagg.set_mean_std(ctxs, imts, cmaker.gsims) # disaggregate by site, IMT for s, iml3 in enumerate(hmap4): close = [ctx for ctx in ctxs if ctx.magi == magi and s in ctx.sids] if not g_by_z[s] or not close: # g_by_z[s] is empty in test case_7 continue # dist_bins, lon_bins, lat_bins, eps_bins bins = (bin_edges[1], bin_edges[2][s], bin_edges[3][s], bin_edges[4]) iml2 = dict(zip(imts, iml3)) with dis_mon: # 7D-matrix #distbins, #lonbins, #latbins, #epsbins, M, P, Z matrix = disagg.disaggregate(close, cmaker.tom, g_by_z[s], iml2, eps3, s, bins) # 7D-matrix for m in range(M): mat6 = matrix[..., m, :, :] if mat6.any(): res[s, m] = output(mat6) yield res
def compute_disagg(dstore, rctx, cmaker, hmap4, trti, bin_edges, oq, monitor): # see https://bugs.launchpad.net/oq-engine/+bug/1279247 for an explanation # of the algorithm used """ :param dstore: a DataStore instance :param rctx: an array of rupture parameters :param cmaker: a :class:`openquake.hazardlib.gsim.base.ContextMaker` instance :param hmap4: an ArrayWrapper of shape (N, M, P, Z) :param trti: tectonic region type index :param magi: magnitude bin index :param bin_egdes: a quartet (dist_edges, lon_edges, lat_edges, eps_edges) :param monitor: monitor of the currently running job :returns: a dictionary sid, imti -> 6D-array """ RuptureContext.temporal_occurrence_model = PoissonTOM( oq.investigation_time) with monitor('reading contexts', measuremem=True): dstore.open('r') ctxs, close_ctxs = read_ctxs( dstore, rctx, req_site_params=cmaker.REQUIRES_SITES_PARAMETERS) magi = numpy.searchsorted(bin_edges[0], rctx[0]['mag']) - 1 if magi == -1: # when the magnitude is on the edge magi = 0 dis_mon = monitor('disaggregate', measuremem=False) ms_mon = monitor('disagg mean_std', measuremem=True) N, M, P, Z = hmap4.shape g_by_z = AccumDict(accum={}) # dict s -> z -> g for g, rlzs in enumerate(cmaker.gsims.values()): for (s, z), r in numpy.ndenumerate(hmap4.rlzs): if r in rlzs: g_by_z[s][z] = g eps3 = disagg._eps3(cmaker.trunclevel, oq.num_epsilon_bins) res = {'trti': trti, 'magi': magi} imts = [from_string(im) for im in oq.imtls] with ms_mon: # compute mean and std for a single IMT to save memory # the size is N * U * G * 16 bytes disagg.set_mean_std(ctxs, imts, cmaker.gsims) # disaggregate by site, IMT for s, iml3 in enumerate(hmap4): if not g_by_z[s] or not close_ctxs[s]: # g_by_z[s] is empty in test case_7 continue # dist_bins, lon_bins, lat_bins, eps_bins bins = (bin_edges[1], bin_edges[2][s], bin_edges[3][s], bin_edges[4]) iml2 = dict(zip(imts, iml3)) with dis_mon: # 7D-matrix #distbins, #lonbins, #latbins, #epsbins, M, P, Z matrix = disagg.disaggregate(close_ctxs[s], g_by_z[s], iml2, eps3, s, bins) # 7D-matrix for m in range(M): mat6 = matrix[..., m, :, :] if mat6.any(): res[s, m] = output(mat6) return res
def compute_disagg(dstore, idxs, cmaker, iml4, trti, magi, bin_edges, oq, monitor): # see https://bugs.launchpad.net/oq-engine/+bug/1279247 for an explanation # of the algorithm used """ :param dstore: a DataStore instance :param idxs: an array of indices to ruptures :param cmaker: a :class:`openquake.hazardlib.gsim.base.ContextMaker` instance :param iml4: an ArrayWrapper of shape (N, M, P, Z) :param trti: tectonic region type index :param magi: magnitude bin index :param bin_egdes: a quartet (dist_edges, lon_edges, lat_edges, eps_edges) :param monitor: monitor of the currently running job :returns: a dictionary sid -> 7D-array """ res = {'trti': trti, 'magi': magi} with monitor('reading rupdata', measuremem=True): dstore.open('r') sitecol = dstore['sitecol'] # NB: using dstore['rup/' + k][idxs] would be ultraslow! a, b = idxs.min(), idxs.max() + 1 rupdata = {k: dstore['rup/' + k][a:b][idxs-a] for k in dstore['rup']} RuptureContext.temporal_occurrence_model = PoissonTOM( oq.investigation_time) pne_mon = monitor('disaggregate_pne', measuremem=False) mat_mon = monitor('build_disagg_matrix', measuremem=False) ms_mon = monitor('disagg mean_std', measuremem=True) eps3 = disagg._eps3(cmaker.trunclevel, oq.num_epsilon_bins) with ms_mon: ctxs = _prepare_ctxs(rupdata, cmaker, sitecol) # ultra-fast mean_std = disagg.get_mean_std(ctxs, oq.imtls, cmaker.gsims) for s, iml3 in enumerate(iml4): iml2dict = {imt: iml3[m] for m, imt in enumerate(oq.imtls)} # z indices by gsim M, P, Z = iml3.shape zs_by_g = AccumDict(accum=[]) for g, rlzs in enumerate(cmaker.gsims.values()): for z in range(Z): if iml4.rlzs[s, z] in rlzs: zs_by_g[g].append(z) # sanity check: the zs are disjoint counts = numpy.zeros(Z, numpy.uint8) for zs in zs_by_g.values(): counts[zs] += 1 assert (counts <= 1).all(), counts # dist_bins, lon_bins, lat_bins, eps_bins bins = bin_edges[0], bin_edges[1][s], bin_edges[2][s], bin_edges[3] # build 7D-matrix #distbins, #lonbins, #latbins, #epsbins, M, P, Z matrix = disagg.disaggregate( ctxs, mean_std, zs_by_g, iml2dict, eps3, s, bins, pne_mon, mat_mon) if matrix.any(): res[s] = matrix return res