def test_set_ab(self): mfd = TruncatedGRMFD(min_mag=2.5, max_mag=3.5, bin_width=0.25, a_val=1, b_val=1.3) mfd.modify('set_ab', {'a_val': -4.2, 'b_val': 1.45}) self.assertEqual(mfd.max_mag, 3.5) self.assertEqual(mfd.a_val, -4.2) self.assertEqual(mfd.b_val, 1.45) self.assertEqual(mfd.min_mag, 2.5)
def test_set_max_mag(self): mfd = TruncatedGRMFD(min_mag=3.5, max_mag=5.5, bin_width=0.5, a_val=1, b_val=1.3) mfd.modify('set_max_mag', {'value': 4.2}) self.assertEqual(mfd.max_mag, 4.2) self.assertEqual(mfd.a_val, 1) self.assertEqual(mfd.b_val, 1.3) self.assertEqual(mfd.min_mag, 3.5)
def test(self): mfd = TruncatedGRMFD(min_mag=0.61, max_mag=0.94, bin_width=0.1, a_val=1, b_val=0.2) # mag values should be rounded to 0.6 and 0.9 and there # should be three bins with the first having center at 0.65 min_mag, num_bins = mfd._get_min_mag_and_num_bins() self.assertAlmostEqual(min_mag, 0.65) self.assertEqual(mfd.get_min_max_mag(), (min_mag, min_mag + 0.2)) self.assertEqual(num_bins, 3)
def _test(self, expected_rates, rate_tolerance, **kwargs): mfd = TruncatedGRMFD(**kwargs) actual_rates = mfd.get_annual_occurrence_rates() self.assertEqual(len(actual_rates), len(expected_rates)) for i, (mag, rate) in enumerate(actual_rates): expected_mag, expected_rate = expected_rates[i] self.assertAlmostEqual(mag, expected_mag, delta=1e-14) self.assertAlmostEqual(rate, expected_rate, delta=rate_tolerance) if i == 0: self.assertEqual((mag, mag + 2), mfd.get_min_max_mag())
def test_3(self): # rupture length greater than fault length, number of nodes along # length is odd and along width is even mfd = TruncatedGRMFD(a_val=0.5, b_val=1.0, min_mag=5.0, max_mag=6.0, bin_width=1.0) self._test_ruptures(test_data.TEST3_RUPTURES, self._make_source(mfd=mfd, aspect_ratio=4.0))
def _get_mfds(srcs): """ Return sources' magnitude frequency distributions. """ mfds = {} tot_occur_rate = 0 for src in srcs: mfd = {} if isinstance(src.mfd, IncrementalMFD): mfd['min_mag'] = float(src.mfd.min_mag) mfd['bin_width'] = float(src.mfd.bin_width) mfd['occur_rates'] = map(float, src.mfd.occur_rates) elif isinstance(src.mfd, TGRMFD): bin_width = 0.1 mfd = TruncatedGRMFD( src.mfd.min_mag, src.mfd.max_mag, bin_width, src.mfd.a_val, src.mfd.b_val ) mags_rates = mfd.get_annual_occurrence_rates() mags = [m for m, _ in mags_rates] occur_rates = [r for _, r in mags_rates] mfd['min_mag'] = mags[0] mfd['bin_width'] = bin_width mfd['occur_rates'] = occur_rates else: raise ValueError( 'MFD %s not recognized' % src.mfd.__class__.__name__ ) tot_occur_rate += sum(mfd['occur_rates']) assert src.id not in mfds mfds[src.id] = mfd return mfds, tot_occur_rate
def test_5(self): # rupture length and width greater than fault length and width # respectively mfd = TruncatedGRMFD(a_val=0.5, b_val=1.0, min_mag=6.0, max_mag=7.0, bin_width=1.0) self._test_ruptures(test_data.TEST5_RUPTURES, self._make_source(mfd=mfd, aspect_ratio=1.0))
def test_4(self): # rupture width greater than fault width, number of nodes along # length is even, along width is odd mfd = TruncatedGRMFD(a_val=0.5, b_val=1.0, min_mag=5.4, max_mag=5.5, bin_width=0.1) self._test_ruptures(test_data.TEST4_RUPTURES, self._make_source(mfd=mfd, aspect_ratio=0.5))
def sliprate2GR_incremental(sliprate, fault_area, b_value, max_mag, min_mag=0.0, bin_width=0.1): """Converts a sliprate and b-value into a Gutenberg- Richter distribution, then converts this to an OpenQuake incremental MFD (to facilitate collapsing of rates with other MFDs) """ a_value, moment_rate = fault_slip_rate_GR_conversion.slip2GR( sliprate, fault_area, float(b_value), float(max_mag), M_min=min_mag) mfd = TruncatedGRMFD(min_mag, max_mag, bin_width, a_value, b_value) mags, rates = zip(*mfd.get_annual_occurrence_rates()) mags = np.array(mags) rates = np.array(rates) return mags, rates, moment_rate
def test_2(self): # rupture dimensions are larger then mesh_spacing, number of nodes # along strike and dip is even mfd = TruncatedGRMFD(a_val=0.5, b_val=1.0, min_mag=3.0, max_mag=4.0, bin_width=1.0) self._test_ruptures(test_data.TEST2_RUPTURES, self._make_source(mfd=mfd, aspect_ratio=1.0))
def test_increment_b(self): mfd = TruncatedGRMFD(min_mag=4.2, max_mag=6.6, bin_width=0.2, a_val=-20.5, b_val=0.51) old_tmr = mfd._get_total_moment_rate() mfd.modify('increment_b', {'value': 1.46}) self.assertEqual(mfd.max_mag, 6.6) self.assertEqual(mfd.b_val, 0.51 + 1.46) self.assertEqual(mfd.min_mag, 4.2) self.assertAlmostEqual(mfd._get_total_moment_rate(), old_tmr) mfd.modify('increment_b', {'value': -1.46}) self.assertAlmostEqual(mfd._get_total_moment_rate(), old_tmr) self.assertEqual(mfd.b_val, 0.51) self.assertAlmostEqual(mfd.a_val, -20.5)
def test_increment_max_mag(self): mfd = TruncatedGRMFD(min_mag=6.0, max_mag=7.0, bin_width=0.1, a_val=-18.2, b_val=0.41) old_tmr = mfd._get_total_moment_rate() mfd.modify('increment_max_mag', {'value': 1}) self.assertEqual(mfd.max_mag, 8.0) self.assertEqual(mfd.b_val, 0.41) self.assertEqual(mfd.min_mag, 6.0) self.assertAlmostEqual(mfd._get_total_moment_rate(), old_tmr) mfd.modify('increment_max_mag', {'value': -1}) self.assertAlmostEqual(mfd._get_total_moment_rate(), old_tmr) self.assertEqual(mfd.max_mag, 7.0) self.assertAlmostEqual(mfd.a_val, -18.2)
def test_mesh_spacing_too_small(self): mfd = TruncatedGRMFD(a_val=0.5, b_val=1.0, min_mag=0.5, max_mag=1.5, bin_width=1.0) with self.assertRaises(ValueError) as ar: self._make_source(mfd=mfd, aspect_ratio=1.0) self.assertEqual( str(ar.exception), 'mesh spacing 1 is too high to represent ' 'ruptures of magnitude 1.5')
def test_fault_trace_intersects_itself(self): mfd = TruncatedGRMFD(a_val=0.5, b_val=1.0, min_mag=10, max_mag=20, bin_width=1.0) fault_trace = Line( [Point(0, 0), Point(0, 1), Point(1, 1), Point(0, 0.5)]) with self.assertRaises(ValueError) as ar: self._make_source(mfd=mfd, aspect_ratio=1, fault_trace=fault_trace) self.assertEqual(str(ar.exception), 'fault trace intersects itself')
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)
def test_instantiation(self): min_mag = 0.0 max_mag = 7.0 bin_width = 0.01 b_val = 1.0 moment_rate = 4.5e16 mfd = TruncatedGRMFD.from_moment(min_mag, max_mag, bin_width, b_val, moment_rate) rates = np.array(mfd.get_annual_occurrence_rates()) computed = np.sum(10**(1.5 * rates[:, 0] + 9.1) * rates[:, 1]) msg = "Scalar Mo rate from MFD does not match the original one" self.assertAlmostEqual(moment_rate, computed, msg=msg, delta=1e14)
def test_set_a_and_get_total_moment_rate(self): mfd = TruncatedGRMFD(min_mag=3.0, max_mag=4.0, bin_width=0.1, a_val=4.4, b_val=0.5) tmr = mfd._get_total_moment_rate() mfd._set_a(tmr) self.assertAlmostEqual(mfd.a_val, 4.4) self.assertEqual(mfd._get_total_moment_rate(), tmr)
def test_set_a_and_get_total_moment_rate_when_b_equal_to_1_5(self): mfd = TruncatedGRMFD(min_mag=2.4, max_mag=5.6, bin_width=0.4, a_val=-0.44, b_val=1.5) tmr = mfd._get_total_moment_rate() mfd._set_a(tmr) self.assertAlmostEqual(mfd.a_val, -0.44) self.assertEqual(mfd._get_total_moment_rate(), tmr)
def test(self): mfd = TruncatedGRMFD(a_val=1, b_val=2, min_mag=3, max_mag=5, bin_width=1) np_dist = PMF([(0.5, NodalPlane(1, 20, 3)), (0.5, NodalPlane(2, 2, 4))]) source = make_point_source(nodal_plane_distribution=np_dist, mfd=mfd) radius = source._get_max_rupture_projection_radius() self.assertAlmostEqual(radius, 1.2830362) mfd = TruncatedGRMFD(a_val=1, b_val=2, min_mag=5, max_mag=6, bin_width=1) np_dist = PMF([(0.5, NodalPlane(1, 40, 3)), (0.5, NodalPlane(2, 30, 4))]) source = make_point_source(nodal_plane_distribution=np_dist, mfd=mfd) radius = source._get_max_rupture_projection_radius() self.assertAlmostEqual(radius, 3.8712214)
def test01(self): """ Simplest test """ # Create the magnitude-frequency distribution mfd = TruncatedGRMFD(a_val=0.5, b_val=1.0, min_mag=6.2, max_mag=6.4, bin_width=0.1) source = self._make_source(mfd=mfd, aspect_ratio=1.5) # The fault surface created should contain 13 quadrilaterals along # the strike and 9 quadrilaterals along the dip. The distance between # the two profiles is 33 km. Given that we use a grid spacing of # 2.5 km, 2.5 * 13 gives 32.5 km. The grid spacing along dip is scaled # by the aspect ratio so that the sampling is proportional along # strike and dip. In this case the sampling along strike is 1.66km msg = 'Wrong surface mesh' self.assertEqual(source.surface.mesh.lons.shape[1], 14, msg) self.assertEqual(source.surface.mesh.lons.shape[0], 10, msg) # Regarding ruptures, the lowest magnitude admitted by the MFD is 6.25 # hence - given that the corresponding area of the rupture is 178 km # and the aspect ratio is 1.5 the mesh covered by this rupture must # have the following dimensions: # - width = 10.68 km i.e. 6 quadrilaterals and 7 vertexes # - lenght = 16.02 km i.e. 7 quadrilaterals and 8 vertexes for idx, tmp in enumerate(source.iter_ruptures()): rup = tmp if idx == 0: break msg = 'Wrong dimension of the rupture' self.assertEqual(rup.surface.mesh.lons.shape[0], 7, msg) self.assertEqual(rup.surface.mesh.lons.shape[1], 8, msg) msg = 'Wrong number of ruptures' self.assertEqual(source.count_ruptures(), 42, msg) if MAKE_PICTURES: ppp(source.profiles, source.surface) if MAKE_MOVIES: ruptures = [r for r in source.iter_ruptures()] self._ruptures_animation('test01', source.surface, ruptures, source.profiles)
def setUp(self): # time span of 10 million years self.time_span = 10e6 nodalplane = NodalPlane(strike=0.0, dip=90.0, rake=0.0) self.mfd = TruncatedGRMFD(a_val=3.5, b_val=1.0, min_mag=5.0, max_mag=6.5, bin_width=0.1) # area source of circular shape with radius of 100 km # centered at 0., 0. self.area1 = AreaSource( source_id='src_1', name='area source', tectonic_region_type='Active Shallow Crust', mfd=self.mfd, nodal_plane_distribution=PMF([(1.0, nodalplane)]), hypocenter_distribution=PMF([(1.0, 5.0)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship=WC1994(), rupture_aspect_ratio=1.0, polygon=Point(0., 0.).to_polygon(100.), area_discretization=9.0, rupture_mesh_spacing=1.0, temporal_occurrence_model=PoissonTOM(self.time_span) ) # area source of circular shape with radius of 100 km # centered at 1., 1. self.area2 = AreaSource( source_id='src_1', name='area source', tectonic_region_type='Active Shallow Crust', mfd=self.mfd, nodal_plane_distribution=PMF([(1.0, nodalplane)]), hypocenter_distribution=PMF([(1.0, 5.0)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship=WC1994(), rupture_aspect_ratio=1.0, polygon=Point(5., 5.).to_polygon(100.), area_discretization=9.0, rupture_mesh_spacing=1.0, temporal_occurrence_model=PoissonTOM(self.time_span) ) # non-parametric source self.np_src, _ = make_non_parametric_source()
def test_calculate_fault_surface_area(self): mfd = TruncatedGRMFD(a_val=0.5, b_val=1.0, min_mag=6.0, max_mag=7.0, bin_width=1.0) # The upper and lower seismogenic depths are 0 and 4.24 respectively fault_trace = Line([Point(0.123, 0.456), Point(1.123, 0.456)]) source = self._make_source(mfd=mfd, aspect_ratio=1.0, fault_trace=fault_trace, dip=45) computed = source.get_fault_surface_area() # Checked with an approx calculaton by hand expected = 665.66913 self.assertAlmostEqual(computed, expected, places=2)
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) loc = Point(longitude=0.0, latitude=0.0) npd = PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]) hpd = PMF([(0.7, 10.), (0.3, 20.0)]) self.src1 = PointSource(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., location=loc, nodal_plane_distribution=npd, hypocenter_distribution=hpd) mfd = EvenlyDiscretizedMFD(min_mag=4.0, bin_width=0.1, occurrence_rates=[3., 2., 1.]) self.src2 = PointSource(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., location=loc, nodal_plane_distribution=npd, hypocenter_distribution=hpd)
def test01(self): source_id = name = 'test-source' trt = self.TRT rake = self.RAKE rupture_mesh_spacing = 2.5 upper_seismogenic_depth = 0 lower_seismogenic_depth = 4.2426406871192848 magnitude_scaling_relationship = PeerMSR() rupture_aspect_ratio = 2.0 tom = self.TOM fault_trace = Line([ Point(0.0, 0.0), Point(0.0, 0.0359728811758), Point(0.0190775080917, 0.0550503815181), Point(0.03974514139, 0.0723925718855) ]) mfd = TruncatedGRMFD(a_val=0.5, b_val=1.0, min_mag=5.8, max_mag=6.2, bin_width=0.1) floating_x_step = 10.0 floating_y_step = 5.0 dip = 90.0 src = KiteFaultSource.as_simple_fault( source_id, name, trt, mfd, rupture_mesh_spacing, magnitude_scaling_relationship, rupture_aspect_ratio, tom, upper_seismogenic_depth, lower_seismogenic_depth, fault_trace, dip, rake, floating_x_step, floating_y_step) sfs = SimpleFaultSurface.from_fault_data(fault_trace, upper_seismogenic_depth, lower_seismogenic_depth, dip, rupture_mesh_spacing) msh = Mesh(lons=numpy.array([0.02]), lats=numpy.array([0.03]), depths=numpy.array([0.0])) rrup_sf = sfs.get_min_distance(msh) rrup_kf = src.surface.get_min_distance(msh) numpy.testing.assert_almost_equal(rrup_sf, rrup_kf, decimal=1) if MAKE_PICTURES: ppp(src.profiles, src.surface)
def make_area_source(polygon, discretization, **kwargs): default_arguments = { 'source_id': 'source_id', 'name': 'area source name', 'tectonic_region_type': TRT.VOLCANIC, 'mfd': TruncatedGRMFD(a_val=3, b_val=1, min_mag=5, max_mag=7, bin_width=1), 'nodal_plane_distribution': PMF([(1, NodalPlane(1, 2, 3))]), 'hypocenter_distribution': PMF([(1, 4)]), 'upper_seismogenic_depth': 1.3, 'lower_seismogenic_depth': 4.9, 'magnitude_scaling_relationship': PeerMSR(), 'rupture_aspect_ratio': 1.333, 'polygon': polygon, 'area_discretization': discretization, 'rupture_mesh_spacing': 12.33 } default_arguments.update(kwargs) kwargs = default_arguments source = AreaSource(**kwargs) return source
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 make_point_source(lon=1.2, lat=3.4, **kwargs): default_arguments = { 'source_id': 'source_id', 'name': 'source name', 'tectonic_region_type': TRT.SUBDUCTION_INTRASLAB, 'mfd': TruncatedGRMFD(a_val=1, b_val=2, min_mag=3, max_mag=5, bin_width=1), 'location': Point(lon, lat, 5.6), 'nodal_plane_distribution': PMF([(1, NodalPlane(1, 2, 3))]), 'hypocenter_distribution': PMF([(1, 4)]), 'upper_seismogenic_depth': 1.3, 'lower_seismogenic_depth': 4.9, 'magnitude_scaling_relationship': PeerMSR(), 'rupture_aspect_ratio': 1.333, 'rupture_mesh_spacing': 1.234, 'temporal_occurrence_model': PoissonTOM(50.) } default_arguments.update(kwargs) kwargs = default_arguments ps = PointSource(**kwargs) assert_pickleable(ps) return ps
def test02(self): """ Simplest test """ profiles = [Line([Point(0.0, 0.0, 0.0), Point(0.0, 0.001, 15.0)]), Line([Point(0.1, 0.0, 0.0), Point(0.1, 0.010, 12.0)]), Line([Point(0.2, 0.0, 0.0), Point(0.2, 0.020, 9.0)]), Line([Point(0.3, 0.0, 0.0), Point(0.3, 0.030, 6.0)])] mfd = TruncatedGRMFD(a_val=0.5, b_val=1.0, min_mag=5.8, max_mag=6.2, bin_width=0.1) source = self._make_source(mfd=mfd, aspect_ratio=1.5, profiles=profiles) msg = 'Wrong number of ruptures' self.assertEqual(source.count_ruptures(), 28, msg) if MAKE_MOVIES: ruptures = [r for r in source.iter_ruptures()] self._ruptures_animation('test02', source.surface, ruptures, source.profiles)
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
class TestCCumulativeInterpolation(unittest.TestCase): def setUp(self): min_mag = 6.5 max_mag = 7.0 bin_width = 0.1 a_val = 3.0 b_val = 1.0 self.mfd = TruncatedGRMFD(min_mag, max_mag, bin_width, a_val, b_val) self.ms = [] self.os = [] # # loading information for the original MFD for mag, occ in self.mfd.get_annual_occurrence_rates(): self.ms.append(mag) self.os.append(occ) self.os = np.array(self.os) def test_interpolate_01(self): """ Test calculation of exceedance rate for magnitude equal to bin limit """ exrate = interpolate_ccumul(self.mfd, 6.8) self.assertAlmostEqual(exrate, sum(self.os[-2:])) def test_interpolate_02(self): """ Test calculation of exceedance rate for a given magnitude """ exrate = interpolate_ccumul(self.mfd, 6.84) # rate computed by hand self.assertAlmostEqual(exrate, 4.5450608e-05) def test_interpolate_03(self): """ Test calculation of exceedance rate within the last bin """ exrate = interpolate_ccumul(self.mfd, 6.94) # rate computed by hand self.assertAlmostEqual(exrate, 1.285383e-05)
def test_dilated(self): mfd = TruncatedGRMFD(a_val=1, b_val=2, min_mag=3, max_mag=5, bin_width=1) np_dist = PMF([(1, NodalPlane(0, 2, 4))]) source = make_point_source(nodal_plane_distribution=np_dist, mfd=mfd) polygon = source.get_rupture_enclosing_polygon(dilation=20) self.assertIsInstance(polygon, Polygon) elons = [ 1.3917408, 1.3908138, 1.3880493, 1.3834740, 1.3771320, 1.3690846, 1.3594093, 1.3481992, 1.3355624, 1.3216207, 1.3065082, 1.2903704, 1.2733628, 1.2556490, 1.2373996, 1.2187902, 1.2000000, 1.1812098, 1.1626004, 1.1443510, 1.1266372, 1.1096296, 1.0934918, 1.0783793, 1.0644376, 1.0518008, 1.0405907, 1.0309154, 1.0228680, 1.0165260, 1.0119507, 1.0091862, 1.0082592, 1.0091788, 1.0119361, 1.0165049, 1.0228411, 1.0308838, 1.0405556, 1.0517635, 1.0643995, 1.0783420, 1.0934567, 1.1095979, 1.1266103, 1.1443298, 1.1625858, 1.1812023, 1.2000000, 1.2187977, 1.2374142, 1.2556702, 1.2733897, 1.2904021, 1.3065433, 1.3216580, 1.3356005, 1.3482365, 1.3594444, 1.3691162, 1.3771589, 1.3834951, 1.3880639, 1.3908212, 1.3917408 ] elats = [ 3.3999810, 3.3812204, 3.3626409, 3.3444213, 3.3267370, 3.3097585, 3.2936490, 3.2785638, 3.2646481, 3.2520357, 3.2408482, 3.2311932, 3.2231637, 3.2168369, 3.2122738, 3.2095182, 3.2085967, 3.2095182, 3.2122738, 3.2168369, 3.2231637, 3.2311932, 3.2408482, 3.2520357, 3.2646481, 3.2785638, 3.2936490, 3.3097585, 3.3267370, 3.3444213, 3.3626409, 3.3812204, 3.3999810, 3.4187420, 3.4373226, 3.4555440, 3.4732305, 3.4902120, 3.5063247, 3.5214135, 3.5353329, 3.5479490, 3.5591401, 3.5687983, 3.5768308, 3.5831599, 3.5877248, 3.5904815, 3.5914033, 3.5904815, 3.5877248, 3.5831599, 3.5768308, 3.5687983, 3.5591401, 3.5479490, 3.5353329, 3.5214135, 3.5063247, 3.4902120, 3.4732305, 3.4555440, 3.4373226, 3.4187420, 3.3999810 ] numpy.testing.assert_allclose(polygon.lons, elons) numpy.testing.assert_allclose(polygon.lats, elats)
def test_no_dilation(self): mfd = TruncatedGRMFD(a_val=1, b_val=2, min_mag=3, max_mag=5, bin_width=1) np_dist = PMF([(1, NodalPlane(0, 2, 4))]) source = make_point_source(nodal_plane_distribution=np_dist, mfd=mfd) polygon = source.get_rupture_enclosing_polygon() self.assertIsInstance(polygon, Polygon) elons = [ 1.2115590, 1.2115033, 1.2113368, 1.2110612, 1.2106790, 1.2101940, 1.2096109, 1.2089351, 1.2081734, 1.2073329, 1.2064218, 1.2054488, 1.2044234, 1.2033554, 1.2022550, 1.2011330, 1.2000000, 1.1988670, 1.1977450, 1.1966446, 1.1955766, 1.1945512, 1.1935782, 1.1926671, 1.1918266, 1.1910649, 1.1903891, 1.1898060, 1.1893210, 1.1889388, 1.1886632, 1.1884967, 1.1884410, 1.1884967, 1.1886631, 1.1889387, 1.1893209, 1.1898058, 1.1903890, 1.1910647, 1.1918265, 1.1926670, 1.1935781, 1.1945511, 1.1955765, 1.1966446, 1.1977449, 1.1988670, 1.2000000, 1.2011330, 1.2022551, 1.2033554, 1.2044235, 1.2054489, 1.2064219, 1.2073330, 1.2081735, 1.2089353, 1.2096110, 1.2101942, 1.2106791, 1.2110613, 1.2113369, 1.2115033, 1.2115590 ] elats = [ 3.3999999, 3.3988689, 3.3977489, 3.3966505, 3.3955843, 3.3945607, 3.3935894, 3.3926799, 3.3918409, 3.3910805, 3.3904060, 3.3898238, 3.3893397, 3.3889582, 3.3886831, 3.3885169, 3.3884614, 3.3885169, 3.3886831, 3.3889582, 3.3893397, 3.3898238, 3.3904060, 3.3910805, 3.3918409, 3.3926799, 3.3935894, 3.3945607, 3.3955843, 3.3966505, 3.3977489, 3.3988689, 3.3999999, 3.4011309, 3.4022510, 3.4033494, 3.4044156, 3.4054392, 3.4064105, 3.4073200, 3.4081590, 3.4089194, 3.4095940, 3.4101761, 3.4106603, 3.4110418, 3.4113169, 3.4114831, 3.4115386, 3.4114831, 3.4113169, 3.4110418, 3.4106603, 3.4101761, 3.4095940, 3.4089194, 3.4081590, 3.4073200, 3.4064105, 3.4054392, 3.4044156, 3.4033494, 3.4022510, 3.4011309, 3.3999999 ] numpy.testing.assert_allclose(polygon.lons, elons) numpy.testing.assert_allclose(polygon.lats, elats)
def test02(self): """ Increases the complexity of the surface; because of the surface geometry, the floating factor only impacts the along-strike sampling and only for some magnitudes """ profiles = [Line([Point(0.0, 0.0, 0.0), Point(0.0, 0.001, 15.0)]), Line([Point(0.1, 0.0, 0.0), Point(0.1, 0.010, 12.0)]), Line([Point(0.2, 0.0, 0.0), Point(0.2, 0.020, 9.0)]), Line([Point(0.3, 0.0, 0.0), Point(0.3, 0.030, 6.0)])] mfd = TruncatedGRMFD(a_val=0.5, b_val=1.0, min_mag=5.8, max_mag=6.2, bin_width=0.1) source = self._make_source(mfd=mfd, aspect_ratio=1.5, profiles=profiles) msg = 'Wrong number of ruptures' self.assertEqual(source.count_ruptures(), 25, msg) if MAKE_MOVIES: ruptures = [r for r in source.iter_ruptures()] self._ruptures_animation('test02', source.surface, ruptures, source.profiles)
def _get_rupture(self, min_mag, max_mag, hypocenter_depth, aspect_ratio, dip, rupture_mesh_spacing, upper_seismogenic_depth=2, lower_seismogenic_depth=16): source_id = name = 'test-source' trt = TRT.ACTIVE_SHALLOW_CRUST mfd = TruncatedGRMFD(a_val=2, b_val=1, min_mag=min_mag, max_mag=max_mag, bin_width=1) location = Point(0, 0) nodal_plane = NodalPlane(strike=45, dip=dip, rake=-123.23) nodal_plane_distribution = PMF([(1, nodal_plane)]) hypocenter_distribution = PMF([(1, hypocenter_depth)]) magnitude_scaling_relationship = PeerMSR() rupture_aspect_ratio = aspect_ratio tom = PoissonTOM(time_span=50) point_source = PointSource( source_id, name, trt, mfd, rupture_mesh_spacing, magnitude_scaling_relationship, rupture_aspect_ratio, tom, upper_seismogenic_depth, lower_seismogenic_depth, location, nodal_plane_distribution, hypocenter_distribution) ruptures = list(point_source.iter_ruptures()) self.assertEqual(len(ruptures), 1) [rupture] = ruptures self.assertIs(rupture.temporal_occurrence_model, tom) self.assertIs(rupture.tectonic_region_type, trt) self.assertEqual(rupture.rake, nodal_plane.rake) self.assertIsInstance(rupture.surface, PlanarSurface) self.assertEqual(rupture.surface.mesh_spacing, rupture_mesh_spacing) return rupture
def test_get_total_moment_rate(self): mfd = TruncatedGRMFD(min_mag=6.0, max_mag=8.0, bin_width=0.1, a_val=-17.2, b_val=0.4) self.assertAlmostEqual(mfd._get_total_moment_rate(), 1.6140553)
def test_get_total_moment_rate_when_b_equal_to_1_5(self): # pylint: disable=invalid-name mfd = TruncatedGRMFD(min_mag=6.0, max_mag=8.0, bin_width=0.1, a_val=-9.4, b_val=1.5) self.assertAlmostEqual(mfd._get_total_moment_rate(), 1.3400508)
def test_areasource(self): nodalplane = NodalPlane(strike=0.0, dip=90.0, rake=0.0) src = AreaSource(source_id='src_1', name='area source', tectonic_region_type='Active Shallow Crust', mfd=TruncatedGRMFD(a_val=3.5, b_val=1.0, min_mag=5.0, max_mag=6.5, bin_width=0.1), nodal_plane_distribution=PMF([(1.0, nodalplane)]), hypocenter_distribution=PMF([(1.0, 5.0)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship=WC1994(), rupture_aspect_ratio=1.0, polygon=Polygon([ Point(-0.5, -0.5), Point(-0.5, 0.5), Point(0.5, 0.5), Point(0.5, -0.5) ]), area_discretization=9.0, rupture_mesh_spacing=1.0, temporal_occurrence_model=PoissonTOM(50.)) site = Site(location=Point(0.0, 0.0), vs30=800.0, vs30measured=True, z1pt0=500.0, z2pt5=2.0) gsims = {'Active Shallow Crust': BooreAtkinson2008()} imt = SA(period=0.1, damping=5.0) iml = 0.2 truncation_level = 3.0 n_epsilons = 3 mag_bin_width = 0.2 # in km dist_bin_width = 10.0 # in decimal degree coord_bin_width = 0.2 # compute disaggregation bin_edges, diss_matrix = disagg.disaggregation( [src], site, imt, iml, gsims, truncation_level, n_epsilons, mag_bin_width, dist_bin_width, coord_bin_width) mag_bins, dist_bins, lon_bins, lat_bins, eps_bins, trt_bins = bin_edges numpy.testing.assert_almost_equal( mag_bins, [5., 5.2, 5.4, 5.6, 5.8, 6., 6.2, 6.4, 6.6]) numpy.testing.assert_almost_equal( dist_bins, [0., 10., 20., 30., 40., 50., 60., 70., 80.]) numpy.testing.assert_almost_equal( lat_bins, [-0.6, -0.4, -0.2, 0., 0.2, 0.4, 0.6]) numpy.testing.assert_almost_equal( lon_bins, [-0.6, -0.4, -0.2, 0., 0.2, 0.4, 0.6]) numpy.testing.assert_almost_equal(eps_bins, [-3., -1., 1., 3.]) self.assertEqual(trt_bins, ['Active Shallow Crust']) expected_matrix = numpy.fromstring( codecs.decode( codecs.decode( b"""\ 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\ """, 'base64'), 'zip')).reshape((8, 8, 6, 6, 3, 1)) numpy.testing.assert_almost_equal(diss_matrix, expected_matrix)
class StochasticEventSetTestCase(unittest.TestCase): def setUp(self): # time span of 10 million years self.time_span = 10e6 nodalplane = NodalPlane(strike=0.0, dip=90.0, rake=0.0) self.mfd = TruncatedGRMFD(a_val=3.5, b_val=1.0, min_mag=5.0, max_mag=6.5, bin_width=0.1) # area source of circular shape with radius of 100 km # centered at 0., 0. self.area1 = AreaSource( source_id='src_1', name='area source', tectonic_region_type='Active Shallow Crust', mfd=self.mfd, nodal_plane_distribution=PMF([(1.0, nodalplane)]), hypocenter_distribution=PMF([(1.0, 5.0)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship=WC1994(), rupture_aspect_ratio=1.0, polygon=Point(0., 0.).to_polygon(100.), area_discretization=9.0, rupture_mesh_spacing=1.0, temporal_occurrence_model=PoissonTOM(self.time_span)) # area source of circular shape with radius of 100 km # centered at 1., 1. self.area2 = AreaSource( source_id='src_1', name='area source', tectonic_region_type='Active Shallow Crust', mfd=self.mfd, nodal_plane_distribution=PMF([(1.0, nodalplane)]), hypocenter_distribution=PMF([(1.0, 5.0)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship=WC1994(), rupture_aspect_ratio=1.0, polygon=Point(5., 5.).to_polygon(100.), area_discretization=9.0, rupture_mesh_spacing=1.0, temporal_occurrence_model=PoissonTOM(self.time_span)) # non-parametric source self.np_src, _ = make_non_parametric_source() def _extract_rates(self, ses, time_span, bins): """ Extract annual rates of occurence from stochastic event set """ rates, _ = numpy.histogram([r.mag for r in ses], bins=bins) return rates / time_span def test_ses_generation_from_parametric_source(self): # generate stochastic event set (SES) from area source with given # magnitude frequency distribution (MFD). Check that the MFD as # obtained from the SES (by making an histogram of the magnitude values # and normalizing by the total duration of the event set) is # approximately equal to the original MFD. numpy.random.seed(123) ses = stochastic_event_set([self.area1]) rates = self._extract_rates(ses, time_span=self.time_span, bins=numpy.arange(5., 6.6, 0.1)) expect_rates = numpy.array( [r for m, r in self.mfd.get_annual_occurrence_rates()]) numpy.testing.assert_allclose(rates, expect_rates, rtol=0, atol=1e-4) def test_ses_generation_from_parametric_source_with_filtering(self): # generate stochastic event set (SES) from 2 area sources (area1, # area2). However, by including a single site co-located with the # area1 center, and with source site filtering of 100 km (exactly # the radius of area1), the second source (area2), which is centered # at 5., 5. (that is about 500 km from center of area1), will be # excluded. the MFD from the SES will be therefore approximately equal # to the one of area1 only. numpy.random.seed(123) sites = SiteCollection([ Site(location=Point(0., 0.), vs30=760, vs30measured=True, z1pt0=40., z2pt5=2.) ]) ses = stochastic_event_set([self.area1, self.area2], filters.SourceFilter( sites, filters.MagDepDistance.new('100'))) rates = self._extract_rates(ses, time_span=self.time_span, bins=numpy.arange(5., 6.6, 0.1)) expect_rates = numpy.array( [r for m, r in self.mfd.get_annual_occurrence_rates()]) numpy.testing.assert_allclose(rates, expect_rates, rtol=0, atol=1e-4) def test_ses_generation_from_non_parametric_source(self): # np_src contains two ruptures: rup1 (of magnitude 5) and rup2 (of # magnitude 6) # rup1 has probability of zero occurences of 0.7 and of one # occurrence of 0.3 # rup2 has probability of zero occurrence of 0.7, of one occurrence of # 0.2 and of two occurrences of 0.1 # the test generate multiple SESs. From the ensamble of SES the # probability of 0, 1, and 2, rupture occurrences is computed and # compared with the expected value numpy.random.seed(123) num_sess = 10000 sess = [stochastic_event_set([self.np_src]) for i in range(num_sess)] # loop over ses. For each ses count number of rupture # occurrences (for each magnitude) n_rups1 = {} n_rups2 = {} for i, ses in enumerate(sess): n_rups1[i] = 0 n_rups2[i] = 0 for rup in ses: if rup.mag == 5.: n_rups1[i] += 1 elif rup.mag == 6.: n_rups2[i] += 1 # count how many SESs have 0,1 or 2 occurrences, and then normalize # by the total number of SESs generated. This gives the probability # of having 0, 1 or 2 occurrences n_occs1 = numpy.fromiter(n_rups1.values(), int) n_occs2 = numpy.fromiter(n_rups2.values(), int) p_occs1_0 = (n_occs1 == 0).sum() / num_sess p_occs1_1 = (n_occs1 == 1).sum() / num_sess p_occs2_0 = (n_occs2 == 0).sum() / num_sess p_occs2_1 = (n_occs2 == 1).sum() / num_sess p_occs2_2 = (n_occs2 == 2).sum() / num_sess self.assertAlmostEqual(p_occs1_0, 0.70, places=2) self.assertAlmostEqual(p_occs1_1, 0.30, places=2) self.assertAlmostEqual(p_occs2_0, 0.70, places=2) self.assertAlmostEqual(p_occs2_1, 0.20, places=2) self.assertAlmostEqual(p_occs2_2, 0.10, places=2)
def test_set_a(self): mfd = TruncatedGRMFD(min_mag=6.0, max_mag=8.0, bin_width=0.1, a_val=1.5, b_val=0.5) mfd._set_a(123.45) self.assertAlmostEqual(mfd.a_val, -14.6531141)
def test_set_a_when_b_equal_to_1_5(self): mfd = TruncatedGRMFD(min_mag=6.0, max_mag=8.0, bin_width=0.1, a_val=1.5, b_val=1.5) mfd._set_a(12.45) self.assertAlmostEqual(mfd.a_val, -8.4319519)
class StochasticEventSetTestCase(unittest.TestCase): def setUp(self): # time span of 10 million years self.time_span = 10e6 nodalplane = NodalPlane(strike=0.0, dip=90.0, rake=0.0) self.mfd = TruncatedGRMFD(a_val=3.5, b_val=1.0, min_mag=5.0, max_mag=6.5, bin_width=0.1) # area source of circular shape with radius of 100 km # centered at 0., 0. self.area1 = AreaSource( source_id='src_1', name='area source', tectonic_region_type='Active Shallow Crust', mfd=self.mfd, nodal_plane_distribution=PMF([(1.0, nodalplane)]), hypocenter_distribution=PMF([(1.0, 5.0)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship=WC1994(), rupture_aspect_ratio=1.0, polygon=Point(0., 0.).to_polygon(100.), area_discretization=9.0, rupture_mesh_spacing=1.0, temporal_occurrence_model=PoissonTOM(self.time_span) ) # area source of circular shape with radius of 100 km # centered at 1., 1. self.area2 = AreaSource( source_id='src_1', name='area source', tectonic_region_type='Active Shallow Crust', mfd=self.mfd, nodal_plane_distribution=PMF([(1.0, nodalplane)]), hypocenter_distribution=PMF([(1.0, 5.0)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship=WC1994(), rupture_aspect_ratio=1.0, polygon=Point(5., 5.).to_polygon(100.), area_discretization=9.0, rupture_mesh_spacing=1.0, temporal_occurrence_model=PoissonTOM(self.time_span) ) # non-parametric source self.np_src, _ = make_non_parametric_source() def _extract_rates(self, ses, time_span, bins): """ Extract annual rates of occurence from stochastic event set """ mags = [] for r in ses: mags.append(r.mag) rates, _ = numpy.histogram(mags, bins=bins) rates = rates / time_span return rates def test_ses_generation_from_parametric_source(self): # generate stochastic event set (SES) from area source with given # magnitude frequency distribution (MFD). Check that the MFD as # obtained from the SES (by making an histogram of the magnitude values # and normalizing by the total duration of the event set) is # approximately equal to the original MFD. numpy.random.seed(123) ses = stochastic_event_set([self.area1]) rates = self._extract_rates(ses, time_span=self.time_span, bins=numpy.arange(5., 6.6, 0.1)) expect_rates = numpy.array( [r for m, r in self.mfd.get_annual_occurrence_rates()] ) numpy.testing.assert_allclose(rates, expect_rates, rtol=0, atol=1e-4) def test_ses_generation_from_parametric_source_with_filtering(self): # generate stochastic event set (SES) from 2 area sources (area1, # area2). However, by including a single site co-located with the # area1 center, and with source site filtering of 100 km (exactly # the radius of area1), the second source (area2), which is centered # at 5., 5. (that is about 500 km from center of area1), will be # excluded. the MFD from the SES will be therefore approximately equal # to the one of area1 only. numpy.random.seed(123) sites = SiteCollection([ Site( location=Point(0., 0.), vs30=760, vs30measured=True, z1pt0=40., z2pt5=2. ) ]) ses = stochastic_event_set( [self.area1, self.area2], sites=sites, source_site_filter=filters.SourceFilter(sites, 100.) ) rates = self._extract_rates(ses, time_span=self.time_span, bins=numpy.arange(5., 6.6, 0.1)) expect_rates = numpy.array( [r for m, r in self.mfd.get_annual_occurrence_rates()] ) numpy.testing.assert_allclose(rates, expect_rates, rtol=0, atol=1e-4) def test_ses_generation_from_non_parametric_source(self): # np_src contains two ruptures: rup1 (of magnitude 5) and rup2 (of # magnitude 6) # rup1 has probability of zero occurences of 0.7 and of one # occurrence of 0.3 # rup2 has probability of zero occurrence of 0.7, of one occurrence of # 0.2 and of two occurrences of 0.1 # the test generate multiple SESs. From the ensamble of SES the # probability of 0, 1, and 2, rupture occurrences is computed and # compared with the expected value numpy.random.seed(123) num_sess = 10000 sess = [stochastic_event_set([self.np_src]) for i in range(num_sess)] # loop over ses. For each ses count number of rupture # occurrences (for each magnitude) n_rups1 = {} n_rups2 = {} for i, ses in enumerate(sess): n_rups1[i] = 0 n_rups2[i] = 0 for rup in ses: if rup.mag == 5.: n_rups1[i] += 1 if rup.mag == 6.: n_rups2[i] += 1 # count how many SESs have 0,1 or 2 occurrences, and then normalize # by the total number of SESs generated. This gives the probability # of having 0, 1 or 2 occurrences n_occs1 = numpy.array(list(n_rups1.values())) n_occs2 = numpy.array(list(n_rups2.values())) p_occs1_0 = float(len(n_occs1[n_occs1 == 0])) / num_sess p_occs1_1 = float(len(n_occs1[n_occs1 == 1])) / num_sess p_occs2_0 = float(len(n_occs2[n_occs2 == 0])) / num_sess p_occs2_1 = float(len(n_occs2[n_occs2 == 1])) / num_sess p_occs2_2 = float(len(n_occs2[n_occs2 == 2])) / num_sess self.assertAlmostEqual(p_occs1_0, 0.7, places=2) self.assertAlmostEqual(p_occs1_1, 0.3, places=2) self.assertAlmostEqual(p_occs2_0, 0.7, places=2) self.assertAlmostEqual(p_occs2_1, 0.2, places=2) self.assertAlmostEqual(p_occs2_2, 0.1, places=2)