def test_create3(self): """ Create edges from profiles 3 """ # sampling: profile, edge # MN: 'msh' assigned but never used msh = create_from_profiles(self.profiles2, 50, 50, False)
def setUp(self): path = os.path.join(BASE_DATA_PATH, '../data/slab/cs04/*.csv') profiles2 = [] for filename in sorted(glob.glob(path)): profiles2.append(_read_profile(filename)) # # building the mesh self.msh = create_from_profiles(profiles2, 50, 50, False)
def setUp(self): path = os.path.join(BASE_DATA_PATH, 'profiles06') self.profiles, _ = _read_profiles(path) self.h_sampl = 4 self.v_sampl = 4 idl = False alg = False self.smsh = create_from_profiles(self.profiles, self.h_sampl, self.v_sampl, idl, alg)
def test_mesh_creation_with_alignment(self): """ Test construction of the mesh """ h_sampl = 4 v_sampl = 4 idl = False alg = True smsh = create_from_profiles(self.profiles, h_sampl, v_sampl, idl, alg) # ppp(self.profiles, smsh) idx = numpy.isfinite(smsh[:, :, 0])
def test_mesh_creation(self): """ Test construction of the mesh """ h_sampl = 5 v_sampl = 5 idl = False alg = False smsh = create_from_profiles(self.profiles, h_sampl, v_sampl, idl, alg) # ppp(self.profiles, smsh) # plotter(self.profiles, smsh) idx = numpy.isfinite(smsh[:, :, 0])
def test_mesh_creation(self): """ Create mesh from profiles for SA """ sampling = 40 idl = False alg = False smsh = create_from_profiles(self.profiles, sampling, sampling, idl, alg) # ppp(self.profiles, smsh) # plotter(self.profiles, smsh) idx = numpy.isfinite(smsh[:, :, 0]) self.assertEqual(numpy.sum(numpy.sum(idx)), 202)
def test_mesh_creation(self): """ Create the mesh: two parallel profiles - no top alignment """ h_sampl = 4 v_sampl = 4 idl = False alg = False smsh = create_from_profiles(self.profiles, h_sampl, v_sampl, idl, alg) # plotter(self.profiles, smsh) # # Check the horizontal mesh spacing computed = [] for i in range(0, smsh.shape[0]): tmp = [] for j in range(0, smsh.shape[1] - 1): k = j + 1 dst = distance(smsh[i, j, 0], smsh[i, j, 1], smsh[i, j, 2], smsh[i, k, 0], smsh[i, k, 1], smsh[i, k, 2]) tmp.append(dst) computed.append(dst) computed = numpy.array(computed) self.assertTrue(numpy.all(abs(computed - h_sampl) / h_sampl < 0.05)) # # Check the vertical mesh spacing computed = [] for i in range(0, smsh.shape[0] - 1): tmp = [] k = i + 1 for j in range(0, smsh.shape[1]): dst = distance(smsh[i, j, 0], smsh[i, j, 1], smsh[i, j, 2], smsh[k, j, 0], smsh[k, j, 1], smsh[k, j, 2]) tmp.append(dst) computed.append(dst) computed = numpy.array(computed) print(numpy.amax(abs(computed - v_sampl) / v_sampl)) self.assertTrue(numpy.all(abs(computed - v_sampl) / v_sampl < 0.05))
def _test_create4(self): """ Create edges from profiles 3 """ msh = create_from_profiles(self.profiles3, 5, 5, False) assert not np.any(np.isnan(msh))
def calculate_ruptures(ini_fname, only_plt=False, ref_fdr=None): """ :param str ini_fname: The name of a .ini file :param ref_fdr: The path to the reference folder used to set the paths in the .ini file. If not provided directly, we use the one set in the .ini file. """ # # read config file config = configparser.ConfigParser() config.readfp(open(ini_fname)) # # logging settings logging.basicConfig(format='rupture:%(levelname)s:%(message)s') # # reference folder if ref_fdr is None: ref_fdr = config.get('main', 'reference_folder') # # set parameters profile_sd_topsl = config.getfloat('main', 'profile_sd_topsl') edge_sd_topsl = config.getfloat('main', 'edge_sd_topsl') # this sampling distance is used to sampling = config.getfloat('main', 'sampling') float_strike = config.getfloat('main', 'float_strike') float_dip = config.getfloat('main', 'float_dip') slab_thickness = config.getfloat('main', 'slab_thickness') label = config.get('main', 'label') hspa = config.getfloat('main', 'hspa') vspa = config.getfloat('main', 'vspa') uniform_fraction = config.getfloat('main', 'uniform_fraction') # # MFD params agr = config.getfloat('main', 'agr') bgr = config.getfloat('main', 'bgr') mmax = config.getfloat('main', 'mmax') mmin = config.getfloat('main', 'mmin') # # IDL if config.has_option('main', 'idl'): idl = config.get('main', 'idl') else: idl = False # # IDL align = False if config.has_option('main', 'profile_alignment'): tmps = config.get('main', 'profile_alignment') if re.search('true', tmps.lower()): align = True # # set profile folder path = config.get('main', 'profile_folder') path = os.path.abspath(os.path.join(ref_fdr, path)) # # catalogue cat_pickle_fname = config.get('main', 'catalogue_pickle_fname') cat_pickle_fname = os.path.abspath(os.path.join(ref_fdr, cat_pickle_fname)) # # output hdf5_filename = config.get('main', 'out_hdf5_fname') hdf5_filename = os.path.abspath(os.path.join(ref_fdr, hdf5_filename)) # # smoothing output out_hdf5_smoothing_fname = config.get('main', 'out_hdf5_smoothing_fname') tmps = os.path.join(ref_fdr, out_hdf5_smoothing_fname) out_hdf5_smoothing_fname = os.path.abspath(tmps) # # tectonic regionalisation treg_filename = config.get('main', 'treg_fname') if not re.search('[a-z]', treg_filename): treg_filename = None else: treg_filename = os.path.abspath(os.path.join(ref_fdr, treg_filename)) # # dips = list_of_floats_from_string(config.get('main', 'dips')) asprsstr = config.get('main', 'aspect_ratios') asprs = dict_of_floats_from_string(asprsstr) # # magnitude-scaling relationship msrstr = config.get('main', 'mag_scaling_relation') msrd = get_available_scalerel() if msrstr not in msrd.keys(): raise ValueError('') msr = msrd[msrstr]() # # ------------------------------------------------------------------------ logging.info('Reading profiles from: {:s}'.format(path)) profiles, pro_fnames = _read_profiles(path) assert len(profiles) > 0 # """ if logging.getLogger().isEnabledFor(logging.DEBUG): import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D fig = plt.figure(figsize=(10, 8)) ax = fig.add_subplot(111, projection='3d') for ipro, (pro, fnme) in enumerate(zip(profiles, pro_fnames)): tmp = [[p.longitude, p.latitude, p.depth] for p in pro.points] tmp = np.array(tmp) ax.plot(tmp[:, 0], tmp[:, 1], tmp[:, 2], 'x--b', markersize=2) tmps = '{:d}-{:s}'.format(ipro, os.path.basename(fnme)) ax.text(tmp[0, 0], tmp[0, 1], tmp[0, 2], tmps) ax.invert_zaxis() ax.view_init(50, 55) plt.show() """ # # create mesh from profiles msh = create_from_profiles(profiles, profile_sd_topsl, edge_sd_topsl, idl) # # Create inslab mesh. The one created here describes the top of the slab. # The output (i.e ohs) is a dictionary with the values of dip as keys. The # values in the dictionary are :class:`openquake.hazardlib.geo.line.Line` # instances ohs = create_inslab_meshes(msh, dips, slab_thickness, sampling) if only_plt: pass """ azim = 10. elev = 20. dist = 20. f = mlab.figure(bgcolor=(1, 1, 1), size=(900, 600)) vsc = -0.01 # # profiles for ipro, (pro, fnme) in enumerate(zip(profiles, pro_fnames)): tmp = [[p.longitude, p.latitude, p.depth] for p in pro.points] tmp = np.array(tmp) tmp[tmp[:, 0] < 0, 0] = tmp[tmp[:, 0] < 0, 0] + 360 mlab.plot3d(tmp[:, 0], tmp[:, 1], tmp[:, 2]*vsc, color=(1, 0, 0)) # # top of the slab mesh plot_mesh_mayavi(msh, vsc, color=(0, 1, 0)) # for key in ohs: for iii in range(len(ohs[key])): for line in ohs[key][iii]: pnt = np.array([[p.longitude, p.latitude, p.depth] for p in line.points]) pnt[pnt[:, 0] < 0, 0] = pnt[pnt[:, 0] < 0, 0] + 360 mlab.plot3d(pnt[:, 0], pnt[:, 1], pnt[:, 2]*vsc, color=(0, 0, 1)) f.scene.camera.azimuth(azim) f.scene.camera.elevation(elev) mlab.view(distance=dist) mlab.show() mlab.show() exit(0) """ if 1: vsc = 0.01 import matplotlib.pyplot as plt # MN: 'Axes3D' imported but never used from mpl_toolkits.mplot3d import Axes3D fig = plt.figure(figsize=(10, 8)) ax = fig.add_subplot(111, projection='3d') # # profiles for ipro, (pro, fnme) in enumerate(zip(profiles, pro_fnames)): tmp = [[p.longitude, p.latitude, p.depth] for p in pro.points] tmp = np.array(tmp) tmp[tmp[:, 0] < 0, 0] = tmp[tmp[:, 0] < 0, 0] + 360 ax.plot(tmp[:, 0], tmp[:, 1], tmp[:, 2] * vsc, 'x--b', markersize=2) tmps = '{:d}-{:s}'.format(ipro, os.path.basename(fnme)) ax.text(tmp[0, 0], tmp[0, 1], tmp[0, 2] * vsc, tmps) # # top of the slab mesh # plot_mesh(ax, msh, vsc) # for key in ohs: for iii in range(len(ohs[key])): for line in ohs[key][iii]: pnt = np.array([[p.longitude, p.latitude, p.depth] for p in line.points]) pnt[pnt[:, 0] < 0, 0] = pnt[pnt[:, 0] < 0, 0] + 360 ax.plot(pnt[:, 0], pnt[:, 1], pnt[:, 2] * vsc, '-r') ax.invert_zaxis() ax.view_init(50, 55) plt.show() # # The one created here describes the bottom of the slab lmsh = create_lower_surface_mesh(msh, slab_thickness) # # get min and max values milo, mila, mide, malo, mala, made = get_min_max(msh, lmsh) # # discretizing the slab # omsh = Mesh(msh[:, :, 0], msh[:, :, 1], msh[:, :, 2]) # olmsh = Mesh(lmsh[:, :, 0], lmsh[:, :, 1], lmsh[:, :, 2]) # # this `dlt` value [in degrees] is used to create a buffer around the mesh dlt = 5.0 msh3d = Grid3d(milo - dlt, mila - dlt, mide, malo + dlt, mala + dlt, made, hspa, vspa) # mlo, mla, mde = msh3d.select_nodes_within_two_meshesa(omsh, olmsh) mlo, mla, mde = msh3d.get_coordinates_vectors() # # save data on hdf5 file if os.path.exists(hdf5_filename): os.remove(hdf5_filename) logging.info('Creating {:s}'.format(hdf5_filename)) fh5 = h5py.File(hdf5_filename, 'w') grp_slab = fh5.create_group('slab') dset = grp_slab.create_dataset('top', data=msh) dset.attrs['spacing'] = sampling grp_slab.create_dataset('bot', data=lmsh) fh5.close() # # get catalogue catalogue = get_catalogue(cat_pickle_fname, treg_filename, label) # # smoothing values, smooth = smoothing(mlo, mla, mde, catalogue, hspa, vspa, out_hdf5_smoothing_fname) # # spatial index # r = spatial_index(mlo, mla, mde, catalogue, hspa, vspa) r, proj = spatial_index(smooth) # # magnitude-frequency distribution mfd = TruncatedGRMFD(min_mag=mmin, max_mag=mmax, bin_width=0.1, a_val=agr, b_val=bgr) # # create all the ruptures - the probability of occurrence is for one year # in this case # MN: 'Axes3D' assigned but never used allrup = create_ruptures(mfd, dips, sampling, msr, asprs, float_strike, float_dip, r, values, ohs, 1., hdf5_filename, uniform_fraction, proj, idl, align, True)
def create_ruptures(mfd, dips, sampling, msr, asprs, float_strike, float_dip, r, values, oms, tspan, hdf5_filename, uniform_fraction, proj, idl, align=False, inslab=False): """ Create inslab ruptures using an MFD, a time span. The dictionary 'oms' contains lists of profiles for various values of dip. The ruptures are floated on each virtual fault created from a set of profiles. :param mfd: A magnitude frequency distribution :param dips: A set of dip values :param sampling: The distance in km used to :param msr: A magnitude scaling relationship instance :param asprs: A set of aspect ratios :param float_strike: Along strike floating parameter :param float_dip: Along dip floating parameter :param r: Spatial index :param values: Smothing results :param oms: A dictionary. Values of dip are used as keys while values of the dictionary are list of lists. Every list contains one or several :class:`openquake.hazardlib.geo.line.Line` instances each one corresponding to a 3D profile. :param tspan: Time span [in yr] :param hdf5_filename: Name of the hdf5 file where to store the ruptures :param uniform_fraction: Fraction of the overall rate for a given magnitude bin to be distributed uniformly to all the ruptures for the same mag bin. :param align: Profile alignment flag """ # # hdf5 file fh5 = h5py.File(hdf5_filename, 'a') grp_inslab = fh5.create_group('inslab') # allrup = {} iscnt = 0 for dip in dips: for mi, lines in enumerate(oms[dip]): # # filter out small surfaces i.e. surfaces defined by less than # three profiles if len(lines) < 3: continue # # checking initial profiles for l in lines: ps = np.array([[p.longitude, p.latitude, p.depth] for p in l.points]) assert not np.any(np.isnan(ps)) # # create in-slab virtual fault - `lines` is the list of profiles # to be used for the construction of the virtual fault surface smsh = create_from_profiles(lines, sampling, sampling, idl, align) # # Create mesh omsh = Mesh(smsh[:, :, 0], smsh[:, :, 1], smsh[:, :, 2]) # # Store data in the hdf5 file grp_inslab.create_dataset('{:09d}'.format(iscnt), data=smsh) # # get centroids for a given virtual fault surface ccc = get_centroids(smsh[:, :, 0], smsh[:, :, 1], smsh[:, :, 2]) # # Get weights - this assigns to each cell centroid the weight of # the closest node in the values array weights = get_weights(ccc, r, values, proj) # # loop over magnitudes for mag, _ in mfd.get_annual_occurrence_rates(): # # TODO this is assigns arbitrarly a rake of 90 degrees. It # should be a configuration parameter area = msr.get_median_area(mag=mag, rake=90) rups = [] for aspr in asprs: # # IMPORTANT: the sampling here must be consistent with # what we use for the construction of the mesh lng, wdt = get_discrete_dimensions(area, sampling, aspr) # # If one of the dimensions is equal to 0 it means that # this aspect ratio cannot be represented with the value of # sampling if (lng is None or wdt is None or lng < 1e-10 or wdt < 1e-10): msg = 'Ruptures for magnitude {:.2f} and ar {:.2f}' msg = msg.format(mag, aspr) msg = '{:s} will not be defined'.format(msg) logging.warning(msg) continue # # rupture lenght and rupture width as multiples of the # mesh sampling distance rup_len = int(lng / sampling) + 1 rup_wid = int(wdt / sampling) + 1 # # skipping small ruptures if rup_len < 2 or rup_wid < 2: msg = 'Found an incompatible discrete rupture size' logging.warning(msg) continue # # get_ruptures counter = 0 for rup, rl, cl in get_ruptures(omsh, rup_len, rup_wid, f_strike=float_strike, f_dip=float_dip): # # getting weights from the smoothing w = weights[cl:rup_len - 1, rl:rup_wid - 1] i = np.isfinite(w) # # fix the longitudes outside the standard [-180, 180] # range ij = np.isfinite(rup[0]) iw = rup[0] > 180. ik = np.logical_and(ij, iw) rup[0][ik] -= 360 """ iw = np.nonzero(rup[0][ij] > 180.) if len(iw): print(type(rup), rup[0]) print(ij[iw]) rup[0][ij[iw]] -= 360. """ #if np.any(rup[0][j] > 180): # rup[0][rup[0] > 180.] = rup[0][rup[0] > 180.] - 360. assert np.all(rup[0][ij] <= 180) assert np.all(rup[0][ij] >= -180) rx = rup[0][ij].flatten() ry = rup[1][ij].flatten() rz = rup[2][ij].flatten() # # normalize the weight using the aspect ratio weight wsum = sum(w[i]) / asprs[aspr] # # create the gridded surface. We need at least four # vertexes if len(rx) > 3: #if rup[0].size > 3: srfc = GriddedSurface( Mesh.from_coords(zip(rx, ry, rz), sort=False)) #srfc = GriddedSurface(Mesh.from_coords(zip(rup[0], # rup[1], # rup[2]), # sort=False)) # # update the list with the ruptures - the last # element in the list is the container for the # probability of occurrence. For the time being # this is not defined rups.append([srfc, wsum, dip, aspr, []]) counter += 1 # # update the list of ruptures lab = '{:.2f}'.format(mag) if lab in allrup: allrup[lab] += rups else: allrup[lab] = rups # # update counter iscnt += 1 # # closing the hdf5 file fh5.close() # # logging info for lab in sorted(allrup.keys()): tmps = 'Number of ruptures for m={:s}: {:d}' logging.info(tmps.format(lab, len(allrup[lab]))) # # Compute the normalizing factor for every rupture. This is used only in # the case when smoothing is used a reference for distributing occurrence twei = {} for mag, occr in mfd.get_annual_occurrence_rates(): smm = 0. lab = '{:.2f}'.format(mag) for _, wei, _, _, _ in allrup[lab]: if np.isfinite(wei): smm += wei twei[lab] = smm tmps = 'Total weight {:s}: {:f}' logging.info(tmps.format(lab, twei[lab])) # # generate and store the final set of ruptures fh5 = h5py.File(hdf5_filename, 'a') grp_rup = fh5.create_group('ruptures') # for mag, occr in mfd.get_annual_occurrence_rates(): # # set label lab = '{:.2f}'.format(mag) # # warning if twei[lab] < 1e-50 and uniform_fraction < 0.99: tmps = 'Weight for magnitude {:s} equal to 0' tmps = tmps.format(lab) logging.warning(tmps) # # rups = [] grp = grp_rup.create_group(lab) cnt = 0 numrup = len(allrup[lab]) for srfc, wei, _, _, _ in allrup[lab]: # # Adjust the weight. Every rupture will have a weight that is # a combination between a flat rate and a variable rate if twei[lab] > 1e-10: wei = wei / twei[lab] ocr = (wei * occr * (1. - uniform_fraction) + occr / numrup * uniform_fraction) else: ocr = occr / numrup * uniform_fraction # # compute the probabilities p0 = np.exp(-ocr * tspan) p1 = 1. - p0 # # rups.append([srfc, wei, dip, aspr, [p0, p1]]) # # a = np.zeros(1, dtype=[ ('lons', 'f4', srfc.mesh.lons.shape), ('lats', 'f4', srfc.mesh.lons.shape), ('deps', 'f4', srfc.mesh.lons.shape), ('w', 'float32'), ('dip', 'f4'), ('aspr', 'f4'), ('prbs', 'float32', (2)), ]) a['lons'] = srfc.mesh.lons a['lats'] = srfc.mesh.lats a['deps'] = srfc.mesh.depths a['w'] = wei a['dip'] = dip a['aspr'] = aspr a['prbs'] = np.array([p0, p1], dtype='float32') grp.create_dataset('{:08d}'.format(cnt), data=a) cnt += 1 allrup[lab] = rups fh5.close() return allrup
def create_ruptures(mfd, dips, sampling, msr, asprs, float_strike, float_dip, r, values, oms, tspan, hdf5_filename, uniform_fraction, proj, idl, align=False, inslab=False): """ Create inslab ruptures using an MFD, a time span. The dictionary 'oms' contains lists of profiles for various values of dip. The ruptures are floated on each virtual fault created from a set of profiles. :param mfd: A magnitude frequency distribution :param dips: A set of dip values used to create the virtual faults withni the slab. :param sampling: The distance in km used to sample the profiles :param msr: A magnitude scaling relationship instance :param asprs: A dictionary of aspect ratios (key: aspect ratio, value: weight) :param float_strike: Along strike rupture floating parameter :param float_dip: Along dip rupture floating parameter :param r: Spatial index for the nodes of the grid over which we smoothed seismicity :param values: Smothing results :param oms: A dictionary. Values of dip are used as keys while values of the dictionary are list of lists. Every list contains one or several :class:`openquake.hazardlib.geo.line.Line` instances each one corresponding to a 3D profile. :param tspan: Time span [in yr] :param hdf5_filename: Name of the hdf5 file where to store the ruptures :param uniform_fraction: Fraction of the overall rate for a given magnitude bin to be distributed uniformly to all the ruptures for the same mag bin. :param align: Profile alignment flag """ # Create the output hdf5 file fh5 = h5py.File(hdf5_filename, 'a') grp_inslab = fh5.create_group('inslab') # Loop over dip angles, top traces on the top the slab surface and # magnitudes. The traces are used to create the virtual faults and # float the ruptures. allrup = {} iscnt = 0 trup = 0 for dip in dips: for mi, lines in enumerate(oms[dip]): print('\nVirtual fault {:d} dip {:.2f}\n'.format(mi, dip)) # Filter out small surfaces i.e. surfaces defined by less than # three profiles if len(lines) < 3: continue # Checking initial profiles for lne in lines: ps = np.array([[p.longitude, p.latitude, p.depth] for p in lne.points]) assert not np.any(np.isnan(ps)) # Create in-slab virtual fault - `lines` is the list of profiles # to be used for the construction of the virtual fault surface smsh = create_from_profiles(lines, sampling, sampling, idl, align) # Create mesh omsh = Mesh(smsh[:, :, 0], smsh[:, :, 1], smsh[:, :, 2]) # Store data in the hdf5 file grp_inslab.create_dataset('{:09d}'.format(iscnt), data=smsh) # Get centroids for a given virtual fault surface ccc = get_centroids(smsh[:, :, 0], smsh[:, :, 1], smsh[:, :, 2]) # Get weights - this assigns to each centroid the weight of # the closest node in the values array weights = get_weights(ccc, r, values, proj) # Loop over magnitudes for mag, _ in mfd.get_annual_occurrence_rates(): # TODO this is assigns arbitrarly a rake of 90 degrees. It # should be a configuration parameter area = msr.get_median_area(mag=mag, rake=90) rups = [] for aspr in asprs: # IMPORTANT: the sampling here must be consistent with # what we use for the construction of the mesh lng, wdt = get_discrete_dimensions(area, sampling, aspr) # If one of the dimensions is equal to 0 it means that # this aspect ratio cannot be represented with the value of # sampling if (lng is None or wdt is None or lng < 1e-10 or wdt < 1e-10): msg = 'Ruptures for magnitude {:.2f} and ar {:.2f}' msg = msg.format(mag, aspr) msg = ' {:s} will not be defined'.format(msg) logging.warning(msg) continue # Rupture lenght and rupture width as multiples of the # mesh sampling distance rup_len = int(lng / sampling) + 1 rup_wid = int(wdt / sampling) + 1 # Skip small ruptures if rup_len < 2 or rup_wid < 2: msg = 'Found a small rupture size' logging.warning(msg) continue # Get Ruptures counter = 0 for rup, rl, cl in get_ruptures(omsh, rup_len, rup_wid, f_strike=float_strike, f_dip=float_dip): # Get weights wsum = asprs[aspr] wsum_smoo = np.nan if uniform_fraction < 0.99: w = weights[rl:rl + rup_wid - 1, cl:cl + rup_len - 1] i = np.isfinite(w) tmpw = sum(w[i]) wsum_smoo = tmpw * asprs[aspr] # Fix the longitudes outside the standard [-180, 180] # range ij = np.isfinite(rup[0]) iw = rup[0] > 180. ik = np.logical_and(ij, iw) rup[0][ik] -= 360 # Get centroid idx_r = np.floor(rup[0].shape[0] / 2).astype('i4') idx_c = np.floor(rup[0].shape[1] / 2).astype('i4') hypo = [ rup[0][idx_r, idx_c], rup[1][idx_r, idx_c], rup[2][idx_r, idx_c] ] # Checking assert np.all(rup[0][ij] <= 180) assert np.all(rup[0][ij] >= -180) # Get coordinates of the rupture surface rx = rup[0][ij].flatten() ry = rup[1][ij].flatten() rz = rup[2][ij].flatten() # Create the gridded surface. We need at least four # vertexes if len(rx) > 3: srfc = GriddedSurface( Mesh.from_coords(zip(rx, ry, rz), sort=False)) # Update the list with the ruptures - the last # element in the list is the container for the # probability of occurrence. For the time being # this is not defined rups.append( [srfc, wsum, wsum_smoo, dip, aspr, [], hypo]) counter += 1 trup += 1 # Update the list of ruptures lab = '{:.2f}'.format(mag) if lab in allrup: allrup[lab] += rups else: allrup[lab] = rups # Update counter iscnt += 1 # Closing the hdf5 file fh5.close() # Logging info for lab in sorted(allrup.keys()): tmps = 'Number of ruptures for m={:s}: {:d}' logging.info(tmps.format(lab, len(allrup[lab]))) # Compute the normalizing factor twei = {} tweis = {} for mag, occr in mfd.get_annual_occurrence_rates(): smm = 0. smms = 0. lab = '{:.2f}'.format(mag) for _, wei, weis, _, _, _, _ in allrup[lab]: if np.isfinite(wei): smm += wei if np.isfinite(weis): smms += weis twei[lab] = smm tweis[lab] = smms tmps = 'Total weight {:s}: {:f}' logging.info(tmps.format(lab, twei[lab])) # Generate and store the final set of ruptures fh5 = h5py.File(hdf5_filename, 'a') grp_rup = fh5.create_group('ruptures') # Assign probability of occurrence for mag, occr in mfd.get_annual_occurrence_rates(): # Create the label lab = '{:.2f}'.format(mag) # Check if weight is larger than 0 if twei[lab] < 1e-50 and uniform_fraction < 0.99: tmps = 'Weight for magnitude {:s} equal to 0' tmps = tmps.format(lab) logging.warning(tmps) rups = [] grp = grp_rup.create_group(lab) # Loop over the ruptures and compute the annual pocc cnt = 0 chk = 0 chks = 0 for srfc, wei, weis, _, _, _, hypo in allrup[lab]: # Adjust the weight. Every rupture will have a weight that is # a combination between a flat rate and a spatially variable rate wei = wei / twei[lab] ocr = (occr * uniform_fraction) * wei chk += wei if uniform_fraction < 0.99: weis = weis / tweis[lab] ocr += (occr * (1. - uniform_fraction)) * weis chks += weis # Compute the probabilities p0 = np.exp(-ocr * tspan) p1 = 1. - p0 # Append ruptures rups.append([srfc, [wei, weis], dip, aspr, [p0, p1]]) # Preparing the data structure for storing information a = np.zeros(1, dtype=[ ('lons', 'f4', srfc.mesh.lons.shape), ('lats', 'f4', srfc.mesh.lons.shape), ('deps', 'f4', srfc.mesh.lons.shape), ('w', 'float32', (2)), ('dip', 'f4'), ('aspr', 'f4'), ('prbs', 'float32', (2)), ('hypo', 'float32', (3)), ]) a['lons'] = srfc.mesh.lons a['lats'] = srfc.mesh.lats a['deps'] = srfc.mesh.depths a['w'] = [wei, weis] a['dip'] = dip a['aspr'] = aspr a['prbs'] = np.array([p0, p1], dtype='float32') a['hypo'] = hypo grp.create_dataset('{:08d}'.format(cnt), data=a) cnt += 1 allrup[lab] = rups if len(rups): if uniform_fraction < 0.99: fmt = 'Sum of weights for smoothing: ' fmt = '{:.5f}. Should be close to 1' msg = fmt.format(chks) assert (1.0 - chks) < 1e-5, msg if uniform_fraction > 0.01: fmt = 'Sum of weights for uniform: ' fmt = '{:.5f}. Should be close to 1' msg = fmt.format(chk) assert (1.0 - chk) < 1e-5, msg fh5.close() return allrup