def test_select_within_fault_distance(self): # Tests the selection of events within a distance from the fault # Set up catalouge self.catalogue = Catalogue() self.catalogue.data['longitude'] = np.arange(0., 5.5, 0.5) self.catalogue.data['latitude'] = np.arange(0., 5.5, 0.5) self.catalogue.data['depth'] = np.zeros(11, dtype=float) self.catalogue.data['eventID'] = np.arange(0, 11, 1) self.fault_source = mtkSimpleFaultSource('101', 'A simple fault') trace_as_line = line.Line([point.Point(2.0, 3.0), point.Point(3.0, 2.0)]) self.fault_source.create_geometry(trace_as_line, 30., 0., 30.) selector0 = CatalogueSelector(self.catalogue) # Test 1 - simple case Joyner-Boore distance self.fault_source.select_catalogue(selector0, 40.) np.testing.assert_array_almost_equal( np.array([2., 2.5]), self.fault_source.catalogue.data['longitude']) np.testing.assert_array_almost_equal( np.array([2., 2.5]), self.fault_source.catalogue.data['latitude']) # Test 2 - simple case Rupture distance self.fault_source.catalogue = None self.fault_source.select_catalogue(selector0, 40., 'rupture') np.testing.assert_array_almost_equal( np.array([2.5]), self.fault_source.catalogue.data['longitude']) np.testing.assert_array_almost_equal( np.array([2.5]), self.fault_source.catalogue.data['latitude']) # Test 3 - for vertical fault ensure that Joyner-Boore distance # behaviour is the same as for rupture distance fault1 = mtkSimpleFaultSource('102', 'A vertical fault') fault1.create_geometry(trace_as_line, 90., 0., 30.) self.fault_source.create_geometry(trace_as_line, 90., 0., 30.) # Joyner-Boore self.fault_source.select_catalogue(selector0, 40.) # Rupture fault1.select_catalogue(selector0, 40., 'rupture') np.testing.assert_array_almost_equal( self.fault_source.catalogue.data['longitude'], fault1.catalogue.data['longitude']) np.testing.assert_array_almost_equal( self.fault_source.catalogue.data['latitude'], fault1.catalogue.data['latitude']) # The usual test to ensure error is raised when no events in catalogue self.catalogue = Catalogue() selector0 = CatalogueSelector(self.catalogue) with self.assertRaises(ValueError) as ver: self.fault_source.select_catalogue(selector0, 40.0) self.assertEqual(str(ver.exception), 'No events found in catalogue!')
def parse_simple_fault_node(node, mfd_spacing=0.1, mesh_spacing=1.0): """ Parses a "simpleFaultSource" node and returns an instance of the :class: openquake.hmtk.sources.simple_fault.mtkSimpleFaultSource """ assert "simpleFaultSource" in node.tag sf_taglist = get_taglist(node) # Get metadata sf_id, name, trt = (node.attrib["id"], node.attrib["name"], node.attrib["tectonicRegion"]) # Process geometry trace, dip, upper_depth, lower_depth = node_to_simple_fault_geometry( node.nodes[sf_taglist.index("simpleFaultGeometry")]) # Process scaling relation msr = node_to_scalerel(node.nodes[sf_taglist.index("magScaleRel")]) # Process aspect ratio aspect = float_(node.nodes[sf_taglist.index("ruptAspectRatio")].text) # Process MFD mfd = node_to_mfd(node, sf_taglist) # Process rake rake = float_(node.nodes[sf_taglist.index("rake")].text) simple_fault = mtkSimpleFaultSource(sf_id, name, trt, geometry=None, dip=dip, upper_depth=upper_depth, lower_depth=lower_depth, mag_scale_rel=msr, rupt_aspect_ratio=aspect, mfd=mfd, rake=rake) simple_fault.create_geometry(trace, dip, upper_depth, lower_depth, mesh_spacing) return simple_fault
def test_create_oqhazardlib_source(self): # Tests to ensure the hazardlib source is created trace = line.Line([point.Point(10., 10.), point.Point(11., 10.)]) mfd1 = TruncatedGRMFD(5.0, 8.0, 0.1, 3.0, 1.0) self.fault_source = mtkSimpleFaultSource( '001', 'A Fault Source', trt='Active Shallow Crust', geometry=None, dip=90., upper_depth=0., lower_depth=20., mag_scale_rel=None, rupt_aspect_ratio=1.0, mfd=mfd1, rake=0.) self.fault_source.create_geometry(trace, 90., 0., 20., 1.0) test_source = self.fault_source.create_oqhazardlib_source(TOM, 2.0, True) self.assertIsInstance(test_source, SimpleFaultSource) self.assertIsInstance(test_source.mfd, TruncatedGRMFD) self.assertAlmostEqual(test_source.mfd.b_val, 1.0) self.assertIsInstance(test_source.magnitude_scaling_relationship, WC1994)
def test_simple_fault_instantiation(self): # Tests the core instantiation of the module # Simple instantiation - minimual data self.fault_source = mtkSimpleFaultSource('101', 'A simple fault') self.assertListEqual(sorted(self.fault_source.__dict__), sorted(SOURCE_ATTRIBUTES)) self.assertEqual(self.fault_source.id, '101') self.assertEqual(self.fault_source.name, 'A simple fault') self.assertEqual(self.fault_source.typology, 'SimpleFault') # Simple instantiation with dip self.fault_source = mtkSimpleFaultSource('101', 'A simple fault', dip=60.) self.assertAlmostEqual(self.fault_source.dip, 60.) # Instantiation with an invalid dip range - raises AssertionError self.assertRaises(AssertionError, mtkSimpleFaultSource, identifier='101', name='A simple fault', dip=95.)
def test_create_fault_geometry(self): # Tests the creation of the fault geometry. Testing only behaviour # for creating SimpleFaultSurface classes - not the values in the # class (assumes nhlib implementation is correct) # Case 1 - trace input as instance of nhlib.geo.line.Line class self.fault_source = mtkSimpleFaultSource('101', 'A simple fault') trace_as_line = line.Line( [point.Point(2.0, 3.0), point.Point(3.0, 2.0)]) self.fault_source.create_geometry(trace_as_line, 60., 0., 30.) self.assertIsInstance(self.fault_source.geometry, SimpleFaultSurface) # Case 2 - trace input as numpy array trace_as_array = np.array([[2.0, 3.0], [3.0, 2.0]]) self.fault_source = mtkSimpleFaultSource('101', 'A simple fault') self.fault_source.create_geometry(trace_as_array, 60., 0., 30.) self.assertIsInstance(self.fault_source.geometry, SimpleFaultSurface) # Case 3 - raises error when something else is input with self.assertRaises(ValueError) as ver: self.fault_source.create_geometry('a bad input!', 60., 0., 30.) self.assertEqual(str(ver.exception), 'Unrecognised or unsupported geometry definition')
def test_create_fault_geometry(self): # Tests the creation of the fault geometry. Testing only behaviour # for creating SimpleFaultSurface classes - not the values in the # class (assumes nhlib implementation is correct) # Case 1 - trace input as instance of nhlib.geo.line.Line class self.fault_source = mtkSimpleFaultSource('101', 'A simple fault') trace_as_line = line.Line([point.Point(2.0, 3.0), point.Point(3.0, 2.0)]) self.fault_source.create_geometry(trace_as_line, 60., 0., 30.) self.assertIsInstance(self.fault_source.geometry, SimpleFaultSurface) # Case 2 - trace input as numpy array trace_as_array = np.array([[2.0, 3.0], [3.0, 2.0]]) self.fault_source = mtkSimpleFaultSource('101', 'A simple fault') self.fault_source.create_geometry(trace_as_array, 60., 0., 30.) self.assertIsInstance(self.fault_source.geometry, SimpleFaultSurface) # Case 3 - raises error when something else is input with self.assertRaises(ValueError) as ver: self.fault_source.create_geometry('a bad input!', 60., 0., 30.) self.assertEqual(str(ver.exception), 'Unrecognised or unsupported geometry definition')
def generate_fault_source_model(self): ''' Creates a resulting `openquake.hmtk` fault source set. :returns: source_model - list of instances of either the :class: `openquake.hmtk.sources.simple_fault_source.mtkSimpleFaultSource` or :class: `openquake.hmtk.sources.complex_fault_source.mtkComplexFaultSource` model_weight - Corresponding weights for each source model ''' source_model = [] model_weight = [] for iloc in range(0, self.get_number_mfd_models()): model_mfd = EvenlyDiscretizedMFD( self.mfd[0][iloc].min_mag, self.mfd[0][iloc].bin_width, self.mfd[0][iloc].occur_rates.tolist()) if isinstance(self.geometry, ComplexFaultGeometry): # Complex fault class source = mtkComplexFaultSource( self.id, self.name, self.trt, self.geometry.surface, self.mfd[2][iloc], self.rupt_aspect_ratio, model_mfd, self.rake) source.fault_edges = self.geometry.trace else: # Simple Fault source source = mtkSimpleFaultSource( self.id, self.name, self.trt, self.geometry.surface, self.geometry.dip, self.geometry.upper_depth, self.geometry.lower_depth, self.mfd[2][iloc], self.rupt_aspect_ratio, model_mfd, self.rake) source.fault_trace = self.geometry.trace source_model.append(source) model_weight.append(self.mfd[1][iloc]) return source_model, model_weight
def test_check_seismogenic_depths(self): # Tests the check on seismogenic depths - behaviour different from # equivalent function in area and point sources as simple faults cannot # have an undefined lower seismogenic depth, and upper seismogenic # depth with default to 0 if undefined self.fault_source = mtkSimpleFaultSource('101', 'A simple fault') # Test 1 - Good case - upper and lower seismogenic depths defined self.fault_source._check_seismogenic_depths(2.0, 30.0) self.assertAlmostEqual(self.fault_source.upper_depth, 2.) self.assertAlmostEqual(self.fault_source.lower_depth, 30.) # Test 2 - Acceptable case - upper depth not defined, lower depth given self.fault_source._check_seismogenic_depths(None, 30.0) self.assertAlmostEqual(self.fault_source.upper_depth, 0.) self.assertAlmostEqual(self.fault_source.lower_depth, 30.) # Test 3 - Raises error when no lower depth is defined with self.assertRaises(ValueError) as ver: self.fault_source._check_seismogenic_depths(2., None) self.assertEqual( str(ver.exception), 'Lower seismogenic depth must be defined for ' 'simple fault source!') # Test 4 - Raises error when lower depth is less than upper depth with self.assertRaises(ValueError) as ver: self.fault_source._check_seismogenic_depths(upper_depth=20., lower_depth=15.) self.assertEqual( str(ver.exception), 'Lower seismogenic depth must take a greater value' ' than upper seismogenic depth') # Test 4 - Raises value error when upper depth is less than 0. with self.assertRaises(ValueError) as ver: self.fault_source._check_seismogenic_depths(upper_depth=-0.5, lower_depth=15.) self.assertEqual( str(ver.exception), 'Upper seismogenic depth must be greater than or ' 'equal to 0.0!')
def test_check_seismogenic_depths(self): # Tests the check on seismogenic depths - behaviour different from # equivalent function in area and point sources as simple faults cannot # have an undefined lower seismogenic depth, and upper seismogenic # depth with default to 0 if undefined self.fault_source = mtkSimpleFaultSource('101', 'A simple fault') # Test 1 - Good case - upper and lower seismogenic depths defined self.fault_source._check_seismogenic_depths(2.0, 30.0) self.assertAlmostEqual(self.fault_source.upper_depth, 2.) self.assertAlmostEqual(self.fault_source.lower_depth, 30.) # Test 2 - Acceptable case - upper depth not defined, lower depth given self.fault_source._check_seismogenic_depths(None, 30.0) self.assertAlmostEqual(self.fault_source.upper_depth, 0.) self.assertAlmostEqual(self.fault_source.lower_depth, 30.) # Test 3 - Raises error when no lower depth is defined with self.assertRaises(ValueError) as ver: self.fault_source._check_seismogenic_depths(2., None) self.assertEqual(str(ver.exception), 'Lower seismogenic depth must be defined for ' 'simple fault source!') # Test 4 - Raises error when lower depth is less than upper depth with self.assertRaises(ValueError) as ver: self.fault_source._check_seismogenic_depths(upper_depth=20., lower_depth=15.) self.assertEqual(str(ver.exception), 'Lower seismogenic depth must take a greater value' ' than upper seismogenic depth') # Test 4 - Raises value error when upper depth is less than 0. with self.assertRaises(ValueError) as ver: self.fault_source._check_seismogenic_depths(upper_depth=-0.5, lower_depth=15.) self.assertEqual(str(ver.exception), 'Upper seismogenic depth must be greater than or ' 'equal to 0.0!')