def test_parse_region_list_to_tuples(self): ''' Tests the function to parse a region list to a set of tuples ''' self.data = { 'Shear_Modulus': {'Value': [30.], 'Weight': [1.0]}, 'Displacement_Length_Ratio': {'Value': [1.25E-5], 'Weight': [1.0]}, 'Magnitude_Scaling_Relation': {'Value': [WC1994()], 'Weight': [1.0]}} expected_output = {'Shear_Modulus': [(30., 1.0)], 'Displacement_Length_Ratio': [(1.25E-5, 1.0)], 'Magnitude_Scaling_Relation': [(WC1994(), 1.0)]} output = parse_tect_region_dict_to_tuples([self.data]) self.assertAlmostEqual(expected_output['Shear_Modulus'][0][0], output[0]['Shear_Modulus'][0][0]) self.assertAlmostEqual(expected_output['Shear_Modulus'][0][1], output[0]['Shear_Modulus'][0][1]) self.assertAlmostEqual( expected_output['Displacement_Length_Ratio'][0][0], output[0]['Displacement_Length_Ratio'][0][0]) self.assertAlmostEqual( expected_output['Displacement_Length_Ratio'][0][1], output[0]['Displacement_Length_Ratio'][0][1]) self.assertTrue(isinstance( output[0]['Magnitude_Scaling_Relation'][0][0], WC1994)) self.assertAlmostEqual( expected_output['Magnitude_Scaling_Relation'][0][1], output[0]['Shear_Modulus'][0][1])
def test_get_recurrence_simple_characteristic(self): ''' Tests the function to get the recurrence calculation for a simple characteristic earthquake ''' self.mfd_config = {'MFD_spacing': 0.1, 'Model_Name': 'Characteristic', 'Model_Weight': 1.0, 'Maximum_Magnitude': None, 'Maximum_Uncertainty': None, 'Lower_Bound': -2., 'Upper_Bound': 2., 'Sigma': 0.12} self.model = RecurrenceBranch(8500., 5., WC1994(), 0., 30.) self.model.get_recurrence(self.mfd_config) # Test the same process using just the hmtk.faults.mfd.characteristic # Implementation test_model = Characteristic() test_model.setUp(self.mfd_config) test_model.get_mmax(self.mfd_config, WC1994(), 0., 8500.) _ = test_model.get_mfd(5.0, 8500., 30.) self.assertTrue(isinstance(self.model.recurrence, IncrementalMFD)) self.assertAlmostEqual(self.model.recurrence.min_mag, test_model.mmin) self.assertAlmostEqual(self.model.recurrence.bin_width, test_model.bin_width) np.testing.assert_array_almost_equal(self.model.recurrence.occur_rates, test_model.occurrence_rate)
def example_calc(apply): sitecol = SiteCollection([ Site(Point(30.0, 30.0), 760., 1.0, 1.0), Site(Point(30.25, 30.25), 760., 1.0, 1.0), Site(Point(30.4, 30.4), 760., 1.0, 1.0) ]) mfd_1 = TruncatedGRMFD(4.5, 8.0, 0.1, 4.0, 1.0) mfd_2 = TruncatedGRMFD(4.5, 7.5, 0.1, 3.5, 1.1) sources = [ PointSource('001', 'Point1', 'Active Shallow Crust', mfd_1, 1.0, WC1994(), 1.0, PoissonTOM(50.0), 0.0, 30.0, Point(30.0, 30.5), PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]), PMF([(1.0, 10.0)])), PointSource('002', 'Point2', 'Active Shallow Crust', mfd_2, 1.0, WC1994(), 1.0, PoissonTOM(50.0), 0.0, 30.0, Point(30.0, 30.5), PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]), PMF([(1.0, 10.0)])) ] imtls = { 'PGA': [0.01, 0.1, 0.2, 0.5, 0.8], 'SA(0.5)': [0.01, 0.1, 0.2, 0.5, 0.8] } gsims = {'Active Shallow Crust': AkkarBommer2010()} return calc_hazard_curves(sources, sitecol, imtls, gsims, apply=apply, filter_distance='rrup')
def setUp(self): """ """ mfd_1 = TruncatedGRMFD(4.5, 8.0, 0.1, 4.0, 1.0) mfd_2 = TruncatedGRMFD(4.5, 7.5, 0.1, 3.5, 1.1) self.source_model = [ PointSource('001', 'Point1', 'Active Shallow Crust', mfd_1, 1.0, WC1994(), 1.0, PoissonTOM(50.0), 0.0, 30.0, Point(30.0, 30.5), PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]), PMF([(1.0, 10.0)])), PointSource('002', 'Point2', 'Active Shallow Crust', mfd_2, 1.0, WC1994(), 1.0, PoissonTOM(50.0), 0.0, 30.0, Point(30.0, 30.5), PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]), PMF([(1.0, 10.0)])) ] self.sites = SiteCollection([ Site(Point(30.0, 30.0), 760., True, 1.0, 1.0, 1), Site(Point(30.25, 30.25), 760., True, 1.0, 1.0, 2), Site(Point(30.4, 30.4), 760., True, 1.0, 1.0, 2) ]) self.gsims = {'Active Shallow Crust': 'AkkarBommer2010'} self.imts = ['PGA', 'SA(0.5)'] self.imls = [[0.01, 0.1, 0.2, 0.5, 0.8]]
def reference_psha_calculation_openquake(): """ Sets up the reference PSHA calculation calling OpenQuake directly. All subsequent implementations should match this example """ # Site model - 3 Sites site_model = SiteCollection([ Site(Point(30.0, 30.0), 760., True, 1.0, 1.0, 1), Site(Point(30.25, 30.25), 760., True, 1.0, 1.0, 2), Site(Point(30.4, 30.4), 760., True, 1.0, 1.0, 2) ]) # Source Model Two Point Sources mfd_1 = TruncatedGRMFD(4.5, 8.0, 0.1, 4.0, 1.0) mfd_2 = TruncatedGRMFD(4.5, 7.5, 0.1, 3.5, 1.1) source_model = [ PointSource('001', 'Point1', 'Active Shallow Crust', mfd_1, 1.0, WC1994(), 1.0, PoissonTOM(50.0), 0.0, 30.0, Point(30.0, 30.5), PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]), PMF([(1.0, 10.0)])), PointSource('002', 'Point2', 'Active Shallow Crust', mfd_2, 1.0, WC1994(), 1.0, PoissonTOM(50.0), 0.0, 30.0, Point(30.0, 30.5), PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]), PMF([(1.0, 10.0)])) ] imts = { 'PGA': [0.01, 0.1, 0.2, 0.5, 0.8], 'SA(0.5)': [0.01, 0.1, 0.2, 0.5, 0.8] } # Akkar & Bommer (2010) GMPE gsims = {'Active Shallow Crust': gsim.akkar_bommer_2010.AkkarBommer2010()} truncation_level = None return calc_hazard_curves(source_model, site_model, imts, gsims, truncation_level)
def test_generate_fault_source_model_complex(self): ''' Tests the function to turn fault model into mtkSimpleFault or mtkComplexFault ''' self.fault = mtkActiveFault( '001', 'A Fault', self.complex_fault, [(5.0, 1.0)], 0., None, aseismic=0., msr_sigma=[(0.0, 1.0)], neotectonic_fault=None, scale_rel=[(WC1994(), 1.0)], aspect_ratio=1.0, shear_modulus=[(30., 1.0)], disp_length_ratio=[(1.25E-5, 1.0)]) # Define simple placeholder MFD rec_models = [IncrementalMFD(5.0, 0.1, 1.0 * np.ones(10)), IncrementalMFD(5.0, 0.1, 2.0 * np.ones(10))] self.fault.mfd = (rec_models, [0.5, 0.5], [WC1994(), WC1994()]) # Run model source_model, weights = self.fault.generate_fault_source_model() self.assertEqual(len(source_model), 2) self.assertTrue(isinstance(source_model[0], mtkComplexFaultSource)) for iloc, model in enumerate(source_model): self.assertEqual(model.id, '001') self.assertTrue(isinstance(model.mfd, EvenlyDiscretizedMFD)) np.testing.assert_array_almost_equal(model.mfd.occurrence_rates, rec_models[iloc].occur_rates) self.assertAlmostEqual(weights[iloc], 0.5)
def test_recurrence_collapse_branches(self): ''' Tests the recurrence model generated by collapsing branches ''' self.fault = mtkActiveFault('001', 'A Fault', self.simple_fault, [(5., 0.5), (7., 0.5)], 0., None, aseismic=0., msr_sigma=[(0.0, 1.0)], neotectonic_fault=None, scale_rel=[(WC1994(), 1.0)], aspect_ratio=1.0, shear_modulus=[(30., 1.0)], disp_length_ratio=[(1.25E-5, 1.0)]) mfd_config = [{ 'MFD_spacing': 0.1, 'Maximum_Magnitude': None, 'Minimum_Magnitude': 5.0, 'Model_Name': 'AndersonLucoArbitrary', 'Model_Weight': 0.7, 'Model_Type': 'First', 'b_value': [0.8, 0.05] }, { 'MFD_spacing': 0.1, 'Maximum_Magnitude': None, 'Maximum_Magnitude_Uncertainty': None, 'Minimum_Magnitude': 5.0, 'Model_Name': 'YoungsCoppersmithExponential', 'Model_Weight': 0.3, 'b_value': [0.8, 0.05] }] # Enumerated branches should have four models self.fault.generate_recurrence_models(collapse=True, rendered_msr=WC1994(), config=mfd_config) expected_rates = 0. expected_weights = np.array([0.35, 0.15, 0.35, 0.15]) for iloc in range(0, 4): expected_rates = expected_rates + (expected_weights[iloc] * 10.**FAULT_RATE_DATA[iloc, :]) np.testing.assert_array_almost_equal( np.log10(self.fault.mfd[0][0].occur_rates), np.log10(expected_rates))
def __init__(self, source_file, investigation_time, start_date, min_mag, npd, hdd, aspect=1.5, upper_seismogenic_depth=0.0, lower_seismogenic_depth=15.0, msr=WC1994(), mesh_spacing=1.0, trt="Active Shallow Crust", integration_distance=1000): assert os.path.exists(source_file), source_file self.source_file = source_file self.source_id = None # unset until .new is called self.inv_time = investigation_time self.start_date = start_date self.temporal_occurrence_model = PoissonTOM(self.inv_time) self.min_mag = min_mag self.npd = npd self.hdd = hdd self.aspect = aspect self.usd = upper_seismogenic_depth self.lsd = lower_seismogenic_depth self.msr = msr self.mesh_spacing = mesh_spacing self.tectonic_region_type = trt self.stop = None self.start = None
def prefilter_background_model(hdf5, sites, integration_distance, msr=WC1994(), aspect=1.5): """ Identify those points within the integration distance :param sites: Sites for consideration (can be None!) :param float integration_distance: Maximum distance from rupture to site for consideration :param msr: Magnitude scaling relation :param float aspect: Aspect ratio :returns: Boolean vector indicating if sites are within (True) or outside (False) the integration distance """ bg_locations = hdf5["Grid/Locations"][:].astype("float64") n_locations = bg_locations.shape[0] if not sites: # Apply no filtering - all sources valid return numpy.ones(n_locations, dtype=bool) distances = min_distance(sites.lons, sites.lats, numpy.zeros_like(sites.lons), bg_locations[:, 0], bg_locations[:, 1], numpy.zeros(n_locations)) # Add buffer equal to half of length of median area from Mmax mmax_areas = msr.get_median_area(hdf5["Grid/MMax"][:], 0.0) mmax_lengths = numpy.sqrt(mmax_areas / aspect) return distances <= (0.5 * mmax_lengths + integration_distance)
def test_generate_branching_index(self): ''' Simple test to check that a correct branching index is raised Slip - 2 values MSR - 1 value Shear Modulus - 2 value DLR - 1 value MSR_Sigma - 3 Values Config - 1 value ''' self.fault = mtkActiveFault('001', 'A Fault', self.simple_fault, [(5., 0.5), (7., 0.5)], 0., None, msr_sigma=[(-1.5, 0.15), (0., 0.7), (1.5, 0.15)], neotectonic_fault=None, scale_rel=[(WC1994(), 1.0)], aspect_ratio=1.0, shear_modulus=[(28., 0.5), (30., 0.5)], disp_length_ratio=[(1.25E-5, 1.0)]) # Set with only one config - no data input self.fault.generate_config_set({}) expected_result = np.array( [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 2, 0], [0, 0, 1, 0, 0, 0], [0, 0, 1, 0, 1, 0], [0, 0, 1, 0, 2, 0], [1, 0, 0, 0, 0, 0], [1, 0, 0, 0, 1, 0], [1, 0, 0, 0, 2, 0], [1, 0, 1, 0, 0, 0], [1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 2, 0]], dtype=int) branch_index, number_branches = \ self.fault._generate_branching_index() np.testing.assert_array_equal(branch_index, expected_result) self.assertEqual(number_branches, 12)
def __init__(self, magnitude, dip, aspect, tectonic_region='Active Shallow Crust', rake=0., ztor=0., strike=0., msr=WC1994(), initial_point=DEFAULT_POINT, hypocentre_location=None): """ Instantiate the rupture - requires a minimum of a magnitude, dip and aspect ratio """ self.magnitude = magnitude self.dip = dip self.aspect = aspect self.rake = rake self.strike = strike self.location = initial_point self.ztor = ztor self.trt = tectonic_region self.hypo_loc = hypocentre_location # If the top of rupture depth in the initial if fabs(self.location.depth - self.ztor) > 1E-9: self.location.depth = ztor self.msr = msr self.area = self.msr.get_median_area(self.magnitude, self.rake) self.surface = create_planar_surface(self.location, self.strike, self.dip, self.area, self.aspect) self.hypocentre = get_hypocentre_on_planar_surface(self.surface, self.hypo_loc) self.rupture = self.get_rupture() self.target_sites_config = None self.target_sites = None
def setUp(self): ''' ''' self.fault = None self.regionalisation = None self.msr = [(WC1994(), 1.0)] self.msr_sigma = [(-1.5, 0.15), (0.0, 0.7), (1.5, 0.15)] self.shear_mod = [(30.0, 0.8), (35.0, 0.2)] self.dlr = [(1.25E-5, 1.0)] self.config = [{}] self.slip = [(10.0, 1.0)] x0 = Point(30., 30., 0.) x1 = x0.point_at(30., 0., 30.) x2 = x1.point_at(30., 0., 60.) # Total length is 60 km self.trace = Line([x0, x1, x2]) self.dip = 90. self.upper_depth = 0. self.lower_depth = 20. self.simple_fault = SimpleFaultGeometry(self.trace, self.dip, self.upper_depth, self.lower_depth) # Creates a trace ~60 km long made of 3 points upper_edge = Line([x0, x1, x2]) lower_edge = Line([x0.point_at(40., 20., 130.), x1.point_at(42., 25., 130.), x2.point_at(41., 22., 130.)]) self.complex_fault = ComplexFaultGeometry([upper_edge, lower_edge], 2.0)
def build_fault_model(self, collapse=False, rendered_msr=WC1994(), mfd_config=None): ''' Constructs a full fault model with epistemic uncertainty by enumerating all the possible recurrence models of each fault as separate faults, with the recurrence rates multiplied by the corresponding weights. :param bool collapse: Determines whether or not to collapse the branches :param rendered_msr: If the option is taken to collapse the branches then a recurrence model for rendering must be defined :param list/dict mfd_config: Universal list or dictionay of configuration parameters for the magnitude frequency distribution - will overwrite whatever is previously defined for the fault! ''' self.source_model = mtkSourceModel(self.id, self.name) for fault in self.faults: fault.generate_recurrence_models(collapse, config=mfd_config, rendered_msr=rendered_msr) src_model, src_weight = fault.generate_fault_source_model() for iloc, model in enumerate(src_model): new_model = deepcopy(model) new_model.id = str(model.id) + '_%g' % (iloc + 1) new_model.mfd.occurrence_rates = \ (np.array(new_model.mfd.occurrence_rates) * src_weight[iloc]).tolist() self.source_model.sources.append(new_model)
def setUp(self): mfd = TruncatedGRMFD(min_mag=4.0, max_mag=6.0, bin_width=0.1, a_val=2.0, b_val=1.0) msr = WC1994() tom = PoissonTOM(1.0) pol = Polygon([Point(longitude=0.0, latitude=0.0), Point(longitude=1.0, latitude=0.0), Point(longitude=1.0, latitude=1.0), Point(longitude=0.0, latitude=1.0)]) npd = PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]) hpd = PMF([(0.7, 10.), (0.3, 20.0)]) self.src1 = AreaSource(source_id='1', name='1', tectonic_region_type='Test', mfd=mfd, rupture_mesh_spacing=1, magnitude_scaling_relationship=msr, rupture_aspect_ratio=1., temporal_occurrence_model=tom, upper_seismogenic_depth=0, lower_seismogenic_depth=100., nodal_plane_distribution=npd, hypocenter_distribution=hpd, polygon=pol, area_discretization=10.)
def _parse_event_data(self, metadata): """ Read in the distance related metadata and return an instance of the :class: smtk.sm_database.Earthquake """ metadata["MODY"] = metadata["MODY"].zfill(4) metadata["HRMN"] = metadata["HRMN"].zfill(4) # Date and Time year = get_int(metadata["YEAR"]) month = get_int(metadata["MODY"][:2]) day = get_int(metadata["MODY"][2:]) hour = get_int(metadata["HRMN"][:2]) minute = get_int(metadata["HRMN"][2:]) eq_datetime = datetime(year, month, day, hour, minute) # Event ID and Name eq_id = metadata["EQID"] eq_name = metadata["Earthquake Name"] # Focal Mechanism focal_mechanism = self._get_focal_mechanism(eq_id, eq_name, metadata) focal_mechanism.scalar_moment = get_float(metadata["Mo (dyne.cm)"]) *\ 1E-7 # Read magnitude pref_mag = Magnitude(get_float(metadata["Earthquake Magnitude"]), metadata["Magnitude Type"], sigma=get_float(metadata["Uncertainty"])) # Create Earthquake Class eqk = Earthquake(eq_id, eq_name, eq_datetime, get_float(metadata["Hypocenter Longitude (deg)"]), get_float(metadata["Hypocenter Latitude (deg)"]), get_float(metadata["Hypocenter Depth (km)"]), pref_mag, focal_mechanism, metadata["Country"]) hypo_loc = (0.5, 0.7) # Hypocentre Location msr = WC1994() # Warning rake set to 0.0 in scaling relationship area = msr.get_median_area(pref_mag.value, 0.0) aspect_ratio = 1.5 # Assumed Fixed width_model = np.sqrt(area / aspect_ratio) length_model = aspect_ratio * width_model ztor_model = eqk.depth - width_model / 2. if ztor_model < 0: ztor_model = 0.0 length = get_float(metadata["Fault Rupture Length (km)"]) if length is None: length = length_model width = get_float(metadata["Fault Rupture Width (km)"]) if width is None: width = width_model ztor = get_float(metadata["Depth to Top Of Fault Rupture Model"]) if ztor is None: ztor = ztor_model # Rupture eqk.rupture = Rupture(eq_id, eq_name, pref_mag, length, width, ztor) # get_float(metadata["Fault Rupture Length (km)"]), # get_float(metadata["Fault Rupture Width (km)"]), # get_float(metadata["Depth to Top Of Fault Rupture Model"])) eqk.rupture.get_area() return eqk
def plot_planes_at(x, y, strikes, dips, magnitudes, strike_cs, dip_cs, aratio=1.0, msr=None, ax=None, zorder=20, color='None', linewidth=1, axis=None): """ This plots a cross-section and number of rupture planes defined in terms of a strike and a dip. :parameter x: Coordinates x on the cross-section :parameter y: Coordinates y on the cross-section (it corresponds to a depth) :parameter strikes: Strike values of the planes :parameter dips: Dip values of the planes :parameter strike_cs: Strike angle of the cross-section plane [in degrees] :parameter dip_cs: Dip angle of the cross-section plane [in degrees] """ if axis is None: ax = plt.gca() else: plt.sca(axis) if msr is None: msr = WC1994() cols = ['red', 'blue', 'green'] for strike, dip, col, mag in zip(strikes, dips, cols, magnitudes): area = msr.get_median_area(mag, None) width = (area / aratio)**.5 t = np.arange(-width / 2, width / 2, 0.1) inter = get_line_of_intersection(strike, dip, strike_cs, dip_cs) xl = t * inter[0] yl = t * inter[1] zl = t * inter[2] ds = -np.sign(t) * (xl**2 + yl**2)**.5 + x if color is not None: col = color plt.plot(ds, zl + y, zorder=zorder, color=col, linewidth=linewidth)
def sample_background_model( hdf5, branch_key, tom, eff_num_ses, seed, filter_idx, min_mag, npd, hdd, upper_seismogenic_depth, lower_seismogenic_depth, msr=WC1994(), aspect=1.5, trt=DEFAULT_TRT): """ Generates a rupture set from a sample of the background model :param branch_key: Key to indicate the branch for selecting the background model :param tom: Temporal occurrence model as instance of :class: openquake.hazardlib.tom.TOM :param seed: Random seed to use in the call to tom.sample_number_of_occurrences :param filter_idx: Sites for consideration (can be None!) :param float min_mag: Minimim magnitude for consideration of background sources :param npd: Nodal plane distribution as instance of :class: openquake.hazardlib.pmf.PMF :param hdd: Hypocentral depth distribution as instance of :class: openquake.hazardlib.pmf.PMF :param float aspect: Aspect ratio :param float upper_seismogenic_depth: Upper seismogenic depth (km) :param float lower_seismogenic_depth: Lower seismogenic depth (km) :param msr: Magnitude scaling relation :param float integration_distance: Maximum distance from rupture to site for consideration """ bg_magnitudes = hdf5["/".join(["Grid", branch_key, "Magnitude"])][()] # Select magnitudes above the minimum magnitudes mag_idx = bg_magnitudes >= min_mag mags = bg_magnitudes[mag_idx] rates = hdf5["/".join(["Grid", branch_key, "RateArray"])][filter_idx, :] rates = rates[:, mag_idx] valid_locs = hdf5["Grid/Locations"][filter_idx, :] # Sample remaining rates sampler = tom.sample_number_of_occurrences(rates * eff_num_ses, seed) background_ruptures = [] background_n_occ = [] for i, mag in enumerate(mags): rate_idx = numpy.where(sampler[:, i])[0] rate_cnt = sampler[rate_idx, i] occurrence = rates[rate_idx, i] locations = valid_locs[rate_idx, :] ruptures = generate_background_ruptures( tom, locations, occurrence, mag, npd, hdd, upper_seismogenic_depth, lower_seismogenic_depth, msr, aspect, trt) background_ruptures.extend(ruptures) background_n_occ.extend(rate_cnt.tolist()) return background_ruptures, background_n_occ
def generate_background_ruptures(tom, locations, occurrence, mag, npd, hdd, upper_seismogenic_depth, lower_seismogenic_depth, msr=WC1994(), aspect=1.5, trt=DEFAULT_TRT): """ :param tom: Temporal occurrence model as instance of :class: openquake.hazardlib.tom.TOM :param numpy.ndarray locations: Array of locations [Longitude, Latitude] of the point sources :param numpy.ndarray occurrence: Annual rates of occurrence :param float mag: Magnitude :param npd: Nodal plane distribution as instance of :class: openquake.hazardlib.pmf.PMF :param hdd: Hypocentral depth distribution as instance of :class: openquake.hazardlib.pmf.PMF :param float upper_seismogenic_depth: Upper seismogenic depth (km) :param float lower_seismogenic_depth: Lower seismogenic depth (km) :param msr: Magnitude scaling relation :param float aspect: Aspect ratio :param str trt: Tectonic region type :returns: List of ruptures """ ruptures = [] n_vals = len(locations) depths = hdd.sample_pairs(n_vals) nodal_planes = npd.sample_pairs(n_vals) for i, (x, y) in enumerate(locations): hypocentre = Point(x, y, depths[i][1]) surface = get_rupture_surface(mag, nodal_planes[i][1], hypocentre, msr, aspect, upper_seismogenic_depth, lower_seismogenic_depth) rupture_probability = (occurrence[i] * nodal_planes[i][0] * depths[i][0]) ruptures.append( ParametricProbabilisticRupture(mag, nodal_planes[i][1].rake, trt, hypocentre, surface, PointSource, rupture_probability, tom)) return ruptures
def nrml_from_shapefile(shapefile, shapefile_faultname_attribute, shapefile_dip_attribute, shapefile_sliprate_attribute, source_model_name, simple_fault_tectonic_region, magnitude_scaling_relation, rupture_aspect_ratio, upper_depth, lower_depth, a_value, b_value, min_mag, max_mag, rake, output_dir, quiet): """Driver routine to convert nrml to shapefile """ # Get geometry fault_traces, faultnames, dips, \ sliprate, fault_lengths = parse_line_shapefile(shapefile, shapefile_faultname_attribute, shapefile_dip_attribute, shapefile_sliprate_attribute) # Output is written line-by-line to this list output_xml = [] append_xml_header(output_xml, source_model_name) # Loop through each fault and add source specific info for i in range(len(fault_traces)): simple_fault_id = i A = fault_lengths[i] * (float(lower_depth) - float(upper_depth)) # Calculate M_max from scaling relations scalrel = WC1994() max_mag = scalrel.get_median_mag(A, float(rake)) # print A # Calculate GR a values from slip rate if sliprate[i] != '""': print sliprate[i] a_value, moment_rate = fault_slip_rate_GR_conversion.slip2GR( sliprate[i], A, float(b_value), float(max_mag), M_min=0.0) append_rupture_geometry(output_xml, fault_traces[i], dips[i], simple_fault_id, faultnames[i], upper_depth, lower_depth, simple_fault_tectonic_region) append_earthquake_information(output_xml, magnitude_scaling_relation, rupture_aspect_ratio, a_value, b_value, min_mag, max_mag, rake) # Close xml output_xml.append(' </sourceModel>') output_xml.append('</nrml>') # Add newlines output_xml = [oxml + '\n' for oxml in output_xml] return output_xml
def test_collapse_fault_model(self): input_file = os.path.join( BASE_DATA_PATH, "collapse_test_simple_fault_example_4branch.yml") mesh_spacing = 1.0 reader = FaultYmltoSource(input_file) fault_model, tectonic_region = reader.read_file(mesh_spacing) fault_model.build_fault_model(collapse=True, bin_width=0.05, rendered_msr=WC1994()) expected_mfd = self.src.incrementalMFD model_mfd = fault_model.faults[0].mfd[0][0] self.assertAlmostEqual(expected_mfd["binWidth"], model_mfd.bin_width, 7) self.assertAlmostEqual(expected_mfd["minMag"], model_mfd.min_mag, 7) expected_rates = np.array(expected_mfd.occurRates.text) np.testing.assert_array_almost_equal(model_mfd.occur_rates, expected_rates, 7)
def test_generate_recurrence_models_no_collapse(self): ''' Tests the generate recurrence models option without collapsing branches: simple example with two slip rates and two mfd configurations ''' self.fault = mtkActiveFault( '001', 'A Fault', self.simple_fault, [(5., 0.5), (7., 0.5)], 0., None, aseismic=0., msr_sigma=[(0.0, 1.0)], neotectonic_fault=None, scale_rel=[(WC1994(), 1.0)], aspect_ratio=1.0, shear_modulus=[(30., 1.0)], disp_length_ratio=[(1.25E-5, 1.0)]) mfd_config = [{'MFD_spacing': 0.1, 'Maximum_Magnitude': None, 'Minimum_Magnitude': 5.0, 'Model_Name': 'AndersonLucoArbitrary', 'Model_Weight': 0.7, 'Model_Type': 'First', 'b_value': [0.8, 0.05]}, {'MFD_spacing': 0.1, 'Maximum_Magnitude': None, 'Maximum_Magnitude_Uncertainty': None, 'Minimum_Magnitude': 5.0, 'Model_Name': 'YoungsCoppersmithExponential', 'Model_Weight': 0.3, 'b_value': [0.8, 0.05]}] # Enumerates branches should have four models self.fault.generate_recurrence_models(config=mfd_config) mfds = self.fault.mfd[0] weights = self.fault.mfd[1] np.testing.assert_array_almost_equal( weights, np.array([0.35, 0.15, 0.35, 0.15])) for (iloc, occur) in enumerate(mfds): np.testing.assert_array_almost_equal( np.log10(occur.occur_rates), FAULT_RATE_DATA[iloc, :])
def test_rupture_close_to_south_pole(self): # data taken from real example and causing "surface's angles are not # right" error mfd = EvenlyDiscretizedMFD( min_mag=5., bin_width=0.1, occurrence_rates=[2.180e-07] ) nodal_plane_dist = PMF([(1., NodalPlane(135., 20., 90.))]) src = PointSource(source_id='1', name='pnt', tectonic_region_type='asc', mfd=mfd, rupture_mesh_spacing=1, magnitude_scaling_relationship=WC1994(), rupture_aspect_ratio=1., temporal_occurrence_model=PoissonTOM(50.), upper_seismogenic_depth=0, lower_seismogenic_depth=26, location=Point(-165.125, -83.600), nodal_plane_distribution=nodal_plane_dist, hypocenter_distribution=PMF([(1., 9.)])) ruptures = list(src.iter_ruptures()) self.assertEqual(len(ruptures), 1)
def setUp(self): """ """ # # coordinates of point sources lons = [10.00, 10.10, 10.20, 10.00, 10.10, 10.20, 10.00, 10.10, 10.20] lats = [45.10, 45.10, 45.10, 45.05, 45.05, 45.05, 45.00, 45.00, 45.00] deps = [10.00, 10.00, 10.00, 10.00, 10.00, 10.00, 10.00, 10.00, 10.00] self.lons = lons self.lats = lats # # set main parameters mfd = TruncatedGRMFD(min_mag=4.0, max_mag=6.0, bin_width=0.1, a_val=2.0, b_val=1.0) msr = WC1994() tom = PoissonTOM(1.0) npd = PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]) hdd = PMF([(0.7, 4.), (0.3, 8.0)]) # # create the list of sources srcs = [] for idx, (lon, lat, dep) in enumerate(zip(lons, lats, deps)): src = PointSource(source_id='1', name='Test', tectonic_region_type=TRT.ACTIVE_SHALLOW_CRUST, mfd=mfd, rupture_mesh_spacing=5.0, magnitude_scaling_relationship=msr, rupture_aspect_ratio=1.0, temporal_occurrence_model=tom, upper_seismogenic_depth=0, lower_seismogenic_depth=10., location=Point(lon, lat, dep), nodal_plane_distribution=npd, hypocenter_distribution=hdd) srcs.append(src) self.points = srcs
def test(self): sitecol = SiteCollection([Site(Point(30.0, 30.0), 760., 1.0, 1.0)]) mfd = TruncatedGRMFD(4.5, 8.0, 0.1, 4.0, 1.0) sources = [ PointSource('001', 'Point1', 'Active Shallow Crust', mfd, 1.0, WC1994(), 1.0, PoissonTOM(50.0), 0.0, 30.0, Point(30.0, 30.5), PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]), PMF([(1.0, 10.0)])) ] imtls = {'PGA': [0.01, 0.1, 0.2, 0.5, 0.8]} hc1 = calc_hazard_curves( sources, sitecol, imtls, {'Active Shallow Crust': AkkarBommer2010()})['PGA'] hc2 = calc_hazard_curves( sources, sitecol, imtls, {'Active Shallow Crust': SadighEtAl1997()})['PGA'] hc = .6 * hc1 + .4 * hc2 ag = AvgGMPE(b1=dict(AkkarBommer2010={'weight': .6}), b2=dict(SadighEtAl1997={'weight': .4})) hcm = calc_hazard_curves(sources, sitecol, imtls, {'Active Shallow Crust': ag})['PGA'] # the AvgGMPE is not producing real means!! numpy.testing.assert_almost_equal(hc, hcm, decimal=3)
def _parse_distance_data(self, event, site, metadata): """ Read in the distance related metadata and return an instance of the :class: smtk.sm_database.RecordDistance """ # Compute various distance metrics # Add calculation of Repi, Rhypo from event and station localizations # (latitudes, longitudes, depth, elevation)? target_site = Mesh(np.array([site.longitude]), np.array([site.latitude]), np.array([-site.altitude / 1000.0])) # Warning ratio fixed to 1.5 ratio = 1.5 if not event.rupture.area: event.rupture.area = WC1994().get_median_area( event.magnitude.value, None) surface_modeled = rcfg.create_planar_surface( Point(event.longitude, event.latitude, event.depth), event.mechanism.nodal_planes.nodal_plane_1['strike'], event.mechanism.nodal_planes.nodal_plane_1['dip'], event.rupture.area, ratio) hypocenter = rcfg.get_hypocentre_on_planar_surface( surface_modeled, event.rupture.hypo_loc) try: surface_modeled._create_mesh() except: dip = surface_modeled.get_dip() dip_dir = (surface_modeled.get_strike() - 90.) % 360. ztor = surface_modeled.top_left.depth d_x = ztor * np.tan(np.radians(90.0 - dip)) top_left_surface = surface_modeled.top_left.point_at( d_x, -ztor, dip_dir) top_left_surface.depth = 0. top_right_surface = surface_modeled.top_right.point_at( d_x, -ztor, dip_dir) top_right_surface.depth = 0. surface_modeled = SimpleFaultSurface.from_fault_data( Line([top_left_surface, top_right_surface]), surface_modeled.top_left.depth, surface_modeled.bottom_left.depth, surface_modeled.get_dip(), 1.0) # Rhypo Rhypo, Repi, Rrup, Rjb, Ry0 = tuple( map(get_positive_float, [ metadata[key] for key in [ "Hypocentral Distance (km)", "Epicentral Distance (km)", "Rupture Distance (km)", "Joyner-Boore Distance (km)", "Ry0 (km)" ] ])) Rx = get_float(metadata["Rx (km)"]) # Rx can be negative #Rhypo = get_float(metadata["Hypocentral Distance (km)"]) if Rhypo is None or Rhypo < 0.0: Rhypo = hypocenter.distance_to_mesh(target_site) # Repi #Repi = get_float(metadata["Epicentral Distance (km)"]) if Repi is None or Repi < 0.0: Repi = hypocenter.distance_to_mesh(target_site, with_depths=False) # Rrup #Rrup = get_float(metadata["Rupture Distance (km)"]) if Rrup is None or Rrup < 0.0: Rrup = surface_modeled.get_min_distance(target_site)[0] # Rjb #Rjb = get_float(metadata["Joyner-Boore Distance (km)"]) if Rjb is None or Rjb < 0.0: Rjb = surface_modeled.get_joyner_boore_distance(target_site)[0] # Need to check if Rx and Ry0 are consistant with the other metrics # when those are coming from the flatfile? # Rx #Rx = get_float(metadata["Rx (km)"]) if Rx is None or Rx < 0.0: Rx = surface_modeled.get_rx_distance(target_site)[0] # Ry0 Ry0 = get_float(metadata["Ry0 (km)"]) if Ry0 is None or Ry0 < 0.0: Ry0 = surface_modeled.get_ry0_distance(target_site)[0] distance = RecordDistance(repi=Repi, rhypo=Rhypo, rjb=Rjb, rrup=Rrup, r_x=Rx, ry0=Ry0) distance.azimuth = get_float(metadata["Source to Site Azimuth (deg)"]) #distance.hanging_wall = get_float(metadata["FW/HW Indicator"]) if metadata["FW/HW Indicator"] == "HW": distance.hanging_wall = True elif metadata["FW/HW Indicator"] == "FW": distance.hanging_wall = False else: pass return distance return
# The GEM Foundation, and the authors of the software, assume no # liability for use of the software. ''' :mod: hmtk.regionalisation.tectonic_regionalisation implements the hmtk.ancillary.tectonic_regionalisation.TectonicRegion :class:, defining the methods and attributes associated with a region, and the hmtk.ancillary.tectonic_regionalisation.TectonicRegionalisation :class: defining a regionalisation as a set of regions ''' from math import fabs import numpy as np from openquake.hazardlib.scalerel.wc1994 import WC1994 DEFAULT_SHEAR_MODULUS = [(30.0, 1.0)] DEFAULT_DLR = [(1.25E-5, 1.0)] DEFAULT_MSR = [(WC1994(), 1.0)] def _check_list_weights(parameter, name): ''' Checks that the weights in a list of tuples sums to 1.0 ''' if not isinstance(parameter, list): raise ValueError('%s must be formulated with a list of tuples' % name) weight = np.sum([val[1] for val in parameter]) if fabs(weight - 1.) > 1E-8: raise ValueError('%s weights do not sum to 1.0!' % name) return parameter #~ if isinstance(parameter, dict): #~ if isinstance(parameter['Model'], float):
def setUp(self): """ """ self.msr = WC1994()
def _parse_event_data(self, metadata): """ Read in the distance related metadata and return an instance of the :class: smtk.sm_database.Earthquake """ data_fields = ['Month', 'Day', 'Hour', 'Minute', 'Second'] for f in data_fields: metadata[f] = metadata[f].zfill(2) # Date and Time year = get_int(metadata["Year"]) month = get_int(metadata["Month"]) day = get_int(metadata["Day"]) hour = get_int(metadata["Hour"]) minute = get_int(metadata["Minute"]) second = get_int(metadata["Second"]) eq_datetime = datetime(year, month, day, hour, minute, second) # Event ID and Name eq_id = metadata["EQID"] eq_name = metadata["Earthquake Name"] # Focal Mechanism focal_mechanism = self._get_focal_mechanism(eq_id, eq_name, metadata) focal_mechanism.scalar_moment = get_float(metadata["Mo (dyne.cm)"]) *\ 1E-7 # Read magnitude pref_mag = Magnitude(get_float(metadata["Magnitude"]), metadata["Magnitude type"], sigma=get_float(metadata["Magnitude uncertainty"])) # Create Earthquake Class eqk = Earthquake(eq_id, eq_name, eq_datetime, get_float(metadata["Epicenter Longitude (deg; positive E)"]), get_float(metadata["Epicenter Latitude (deg; positive N)"]), get_float(metadata["Hypocenter Depth (km)"]), pref_mag, focal_mechanism, metadata["Country"]) # hypocenter location f1 = get_float(metadata[ "Along-strike Hypocenter location " + "on the fault (fraction between 0 and 1)"]) f2 = get_float(metadata[ "Along-width Hypocenter location " + "on the fault (fraction between 0 and 1)"]) if f1 is None or f2 is None: hypo_loc = (0.5, 0.7) else: hypo_loc = (f1, f2) evt_tectonic_region = metadata["Tectonic environment (Crustal; Inslab; Interface; Stable; Geothermal; Volcanic; Oceanic_crust)"] if evt_tectonic_region == "Stable" or evt_tectonic_region == "Crustal": msr=WC1994() elif evt_tectonic_region == "Inslab": msr=StrasserIntraslab() elif evt_tectonic_region == "Interface": msr=StrasserInterface() # Warning rake set to 0.0 in scaling relationship - applies only # to WC1994 area = msr.get_median_area(pref_mag.value, 0.0) aspect_ratio = 1.5 width_model = np.sqrt(area / aspect_ratio) length_model = aspect_ratio * width_model ztor_model = eqk.depth - width_model / 2. if ztor_model < 0: ztor_model = 0.0 length = get_float(metadata["Fault Rupture Length (km)"]) if length is None: length = length_model width = get_float(metadata["Fault Rupture Width (km)"]) if width is None: width = width_model ztor = get_float(metadata["Depth to Top Of Fault Rupture Model"]) if ztor is None: ztor=ztor_model # Rupture eqk.rupture = Rupture(eq_id, length, width, ztor, hypo_loc=hypo_loc) # get_float(metadata["Fault Rupture Length (km)"]), # get_float(metadata["Fault Rupture Width (km)"]), # get_float(metadata["Depth to Top Of Fault Rupture Model"]), # hypo_loc=hypo_loc) eqk.rupture.get_area() return eqk