def fromdict(self, dic, weights=None): """ Populate a GriddedSource with ruptures """ assert not self.data, '%s is not empty' % self i = 0 for mag, rake, hp, probs, (start, stop) in zip(dic['magnitude'], dic['rake'], dic['hypocenter'], dic['probs_occur'], dic['slice']): mesh = Mesh(dic['mesh3d'][start:stop, 0], dic['mesh3d'][start:stop, 1], dic['mesh3d'][start:stop, 2]) surface = GriddedSurface(mesh) pmf = PMF([(prob, i) for i, prob in enumerate(probs)]) hypocenter = Point(hp[0], hp[1], hp[2]) rup = NonParametricProbabilisticRupture( mag, rake, self.tectonic_region_type, hypocenter, surface, pmf, weight=None if weights is None else weights[i]) self.data.append((rup, pmf)) i += 1
def __fromh5__(self, dic, attrs): vars(self).update(attrs) self.data = [] for mag, rake, hp, probs, points in zip( dic['magnitude'], dic['rake'], dic['hypocenter'], dic['probs_occur'], dic['points']): mesh = Mesh(points[0], points[1], points[2]) surface = GriddedSurface(mesh) pmf = PMF([(prob, i) for i, prob in enumerate(probs)]) hypocenter = Point(hp['lon'], hp['lat'], hp['depth']) rup = NonParametricProbabilisticRupture( mag, rake, self.tectonic_region_type, hypocenter, surface, pmf) self.data.append((rup, pmf))
def create_nrml_source(rup, mag, sid, name, tectonic_region_type): """ :param rup: :param mag: :param sid: :param name: :param tectonic_region_type: """ data = [] for key in rup.keys(): d = rup[key][:] # # creating the surface llo = np.squeeze(d['lons']) lla = np.squeeze(d['lats']) lde = np.squeeze(d['deps']) # # find a node in the middle of the rupture if len(llo.shape): ihyp = (int(np.round(llo.shape[0] / 2))) if len(llo.shape) > 1: ihyp = (ihyp, int(np.round(llo.shape[1] / 2))) hlo = llo[ihyp] hla = lla[ihyp] hde = lde[ihyp] # # ppp = np.squeeze(d['prbs']) i = np.isfinite(llo) points = [ Point(x, y, z) for x, y, z in zip(llo[i], lla[i], lde[i]) ] srf = GriddedSurface.from_points_list(points) """ br = BaseRupture(mag=mag, rake=-90., tectonic_region_type=tectonic_region_type, hypocenter=Point(hlo, hla, hde), surface=srf, source_typology=NonParametricSeismicSource) """ br = BaseRupture(mag=mag, rake=-90., tectonic_region_type=tectonic_region_type, hypocenter=Point(hlo, hla, hde), surface=srf) xxx = Decimal('{:.8f}'.format(ppp[1])) pmf = PMF(data=[((Decimal('1') - xxx), 0), (xxx, 1)]) data.append((br, pmf)) src = NonParametricSeismicSource(sid, name, tectonic_region_type, data) return src
def create_source(rup, mag, sid, name, tectonic_region_type): """ :param rup: A h5py dataset with the rupture information :param mag: The magnitude of the ruptures :param sid: Source ID :param name: Name of the source :param tectonic_region_type: Tectonic region type """ data = [] for key in rup.keys(): d = rup[key][:] # Creating the surface llo = np.squeeze(d['lons']) lla = np.squeeze(d['lats']) lde = np.squeeze(d['deps']) # Create the gridded surface if len(llo.shape) > 0: # Hypocenter computed in the 'rupture.py' module hypo = np.squeeze(d['hypo'][:]) hlo = hypo[0] hla = hypo[1] hde = hypo[2] # Probabilities of occurrence ppp = np.squeeze(d['prbs']) i = np.isfinite(llo) points = [Point(x, y, z) for x, y, z in zip(llo[i], lla[i], lde[i])] # Create the surface and the rupture srf = GriddedSurface.from_points_list(points) brup = BaseRupture(mag=mag, rake=-90., tectonic_region_type=tectonic_region_type, hypocenter=Point(hlo, hla, hde), surface=srf) xxx = Decimal('{:.8f}'.format(ppp[1])) pmf = PMF(data=[((Decimal('1')-xxx), 0), (xxx, 1)]) data.append((brup, pmf)) src = NonParametricSeismicSource(sid, name, tectonic_region_type, data) return src
def setUp(self): self.surf = GriddedSurface.from_points_list(POINTSIDL) self.mesh = Mesh(np.array([-179.5]), np.array([2.]), np.array([3.]))
def setUp(self): self.surf = GriddedSurface.from_points_list(POINTS) self.mesh = Mesh(np.array([1.]), np.array([2.]), np.array([3.])) self.surf2 = GriddedSurface.from_points_list(POINTS2)
def setUp(self): self.surf = GriddedSurface.from_points_list(POINTS) self.mesh = Mesh(np.array([1.0]), np.array([2.0]), np.array([3.0]))
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