def test_create_oqhazardlib_complex_fault_source(self): """ Tests the conversion of a point source to an instance of the :class: openquake.hazardlib.source.complex_fault.ComplexFaultSource """ complex_edges = [ line.Line([point.Point(11., 10., 0.), point.Point(10., 10., 0.)]), line.Line([point.Point(11.5, 10., 21.), point.Point(10.0, 10., 21.)]) ] self.fault_source = mtkComplexFaultSource('001', 'A Fault Source', trt='Active Shallow Crust', geometry = None, mag_scale_rel=None, rupt_aspect_ratio=1.0, mfd=models.TGRMFD(a_val=3., b_val=1.0, min_mag=5.0, max_mag=8.0), rake=0.) self.fault_source.create_geometry(complex_edges, 2.0) test_source = self.fault_source.create_oqhazardlib_source(TOM, 5.0, True) self.assertIsInstance(test_source, ComplexFaultSource) self.assertIsInstance(test_source.mfd, TruncatedGRMFD) self.assertAlmostEqual(test_source.mfd.b_val, 1.0) self.assertIsInstance(test_source.magnitude_scaling_relationship, WC1994)
def _parse_complex(cls, src_elem, mesh_spacing): """ :param src_elem: :class:`lxml.etree._Element` instance representing a source. :returns: Fully populated :class:`openquake.nrmllib.models.ComplexFaultSource` object. """ # Instantiate with identifier and name complx = mtkComplexFaultSource( src_elem.get('id'), src_elem.get('name')) print 'Complex Fault Source - ID: %s, name: %s' % (complx.id, complx.name) # Set common attributes cls._set_common_attrs(complx, src_elem) # Create the complex geometry complex_edges = cls._parse_complex_geometry(src_elem) complx.create_geometry(complex_edges, mesh_spacing) # Get mfd complx.mfd = cls._parse_mfd(src_elem) if _xpath(src_elem, './/nrml:rake')[0].text: complx.rake = float( _xpath(src_elem, './/nrml:rake')[0].text) return complx
def test_select_within_distance(self): ''' Tests the selection of earthquakes within distance of fault ''' # Create fault self.fault_source = mtkComplexFaultSource('101', 'A complex fault') # Test case when input as list of nhlib.geo.line.Line self.fault_source.create_geometry(self.trace_line, mesh_spacing=2.0) self.assertIsInstance(self.fault_source.geometry, ComplexFaultSurface) # Create simple catalogue self.catalogue.data['longitude'] = np.arange(0., 4.1, 0.1) self.catalogue.data['latitude'] = np.arange(0., 4.1, 0.1) self.catalogue.data['depth'] = np.ones(41, dtype=float) self.catalogue.data['eventID'] = np.arange(0, 41, 1) selector0 = CatalogueSelector(self.catalogue) # Test when considering Joyner-Boore distance self.fault_source.select_catalogue(selector0, 50.) np.testing.assert_array_equal( self.fault_source.catalogue.data['eventID'], np.arange(2, 14, 1)) # Test when considering rupture distance self.fault_source.select_catalogue(selector0, 50., 'rupture') np.testing.assert_array_equal( self.fault_source.catalogue.data['eventID'], np.arange(2, 12, 1)) # 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(ver.exception.message, 'No events found in catalogue!')
def parse_complex_fault_node(node, mfd_spacing=0.1, mesh_spacing=4.0): """ Parses a "complexFaultSource" node and returns an instance of the :class: hmtk.sources.complex_fault.mtkComplexFaultSource """ assert "complexFaultSource" 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 edges = node_to_complex_fault_geometry( node.nodes[sf_taglist.index("complexFaultGeometry")]) # 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) complex_fault = mtkComplexFaultSource(sf_id, name, trt, geometry=None, mag_scale_rel=msr, rupt_aspect_ratio=aspect, mfd=mfd, rake=rake) complex_fault.create_geometry(edges, mesh_spacing) return complex_fault
def test_select_within_distance(self): """ Tests the selection of earthquakes within distance of fault """ # Create fault self.fault_source = mtkComplexFaultSource("101", "A complex fault") # Test case when input as list of nhlib.geo.line.Line self.fault_source.create_geometry(self.trace_line, mesh_spacing=2.0) self.assertIsInstance(self.fault_source.geometry, ComplexFaultSurface) # Create simple catalogue self.catalogue.data["longitude"] = np.arange(0.0, 4.1, 0.1) self.catalogue.data["latitude"] = np.arange(0.0, 4.1, 0.1) self.catalogue.data["depth"] = np.ones(41, dtype=float) self.catalogue.data["eventID"] = np.arange(0, 41, 1) selector0 = CatalogueSelector(self.catalogue) # Test when considering Joyner-Boore distance self.fault_source.select_catalogue(selector0, 50.0) np.testing.assert_array_equal(self.fault_source.catalogue.data["eventID"], np.arange(2, 14, 1)) # Test when considering rupture distance self.fault_source.select_catalogue(selector0, 50.0, "rupture") np.testing.assert_array_equal(self.fault_source.catalogue.data["eventID"], np.arange(2, 12, 1)) # 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(ver.exception.message, "No events found in catalogue!")
def test_create_oqhazardlib_complex_fault_source(self): """ Tests the conversion of a point source to an instance of the :class: openquake.hazardlib.source.complex_fault.ComplexFaultSource """ complex_edges = [ line.Line([point.Point(11., 10., 0.), point.Point(10., 10., 0.)]), line.Line( [point.Point(11.5, 10., 21.), point.Point(10.0, 10., 21.)]) ] self.fault_source = mtkComplexFaultSource('001', 'A Fault Source', trt='Active Shallow Crust', geometry=None, mag_scale_rel=None, rupt_aspect_ratio=1.0, mfd=models.TGRMFD( a_val=3., b_val=1.0, min_mag=5.0, max_mag=8.0), rake=0.) self.fault_source.create_geometry(complex_edges, 2.0) test_source = self.fault_source.create_oqhazardlib_source( TOM, 5.0, True) self.assertIsInstance(test_source, ComplexFaultSource) 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_create_complex_geometry(self): ''' Tests the complex geometry creation ''' self.fault_source = mtkComplexFaultSource('101', 'A complex fault') # Test case when input as list of nhlib.geo.line.Line self.fault_source.create_geometry(self.trace_line, mesh_spacing=2.0) self.assertIsInstance(self.fault_source.geometry, ComplexFaultSurface) # Use the dip as a simple indicator of geometrical success! self.assertAlmostEqual(self.fault_source.dip, 40.5398531, 2) # Create a second instance fault2 = mtkComplexFaultSource('101', 'A complex fault') fault2.create_geometry(self.trace_array, mesh_spacing=2.0) self.assertIsInstance(fault2.geometry, ComplexFaultSurface) # Compare it to the first self.assertAlmostEqual(self.fault_source.dip, fault2.dip) # If less than two edges are input ensure error is raised bad_traces = [ line.Line([point.Point(1.0, 0.0, 3.0), point.Point(1.0, 0.0, 3.0)]) ] self.fault_source = mtkComplexFaultSource('101', 'A complex fault') with self.assertRaises(ValueError) as ver: self.fault_source.create_geometry(bad_traces) self.assertEqual(ver.exception.message, 'Complex fault geometry ' 'incorrectly defined') # If an edge is not defined from either a nhlib.geo.line.Line instance # or numpy.ndarray then ensure error is raised bad_traces = [ line.Line([point.Point(1.0, 0.0, 3.0), point.Point(1.0, 0.0, 3.0)]) ] bad_traces.append('a bad input') self.fault_source = mtkComplexFaultSource('101', 'A complex fault') with self.assertRaises(ValueError) as ver: self.fault_source.create_geometry(bad_traces) self.assertEqual(ver.exception.message, 'Unrecognised or unsupported ' 'geometry definition')
def test_simple_fault_instantiation(self): """ Tests the core instantiation of the module """ # Simple instantiation - minimual data self.fault_source = mtkComplexFaultSource("101", "A complex fault") self.assertEqual(self.fault_source.id, "101") self.assertEqual(self.fault_source.name, "A complex fault") self.assertEqual(self.fault_source.typology, "ComplexFault") self.assertListEqual(self.fault_source.__dict__.keys(), SOURCE_ATTRIBUTES)
def test_simple_fault_instantiation(self): ''' Tests the core instantiation of the module ''' # Simple instantiation - minimual data self.fault_source = mtkComplexFaultSource('101', 'A complex fault') self.assertEqual(self.fault_source.id, '101') self.assertEqual(self.fault_source.name, 'A complex fault') self.assertEqual(self.fault_source.typology, 'ComplexFault') self.assertListEqual(self.fault_source.__dict__.keys(), SOURCE_ATTRIBUTES)
def test_create_complex_geometry(self): ''' Tests the complex geometry creation ''' self.fault_source = mtkComplexFaultSource('101', 'A complex fault') # Test case when input as list of nhlib.geo.line.Line self.fault_source.create_geometry(self.trace_line, mesh_spacing = 2.0) self.assertIsInstance(self.fault_source.geometry, ComplexFaultSurface) # Use the dip as a simple indicator of geometrical success! self.assertAlmostEqual(self.fault_source.dip, 40.5398531, 2) # Create a second instance fault2 = mtkComplexFaultSource('101', 'A complex fault') fault2.create_geometry(self.trace_array, mesh_spacing = 2.0) self.assertIsInstance(fault2.geometry, ComplexFaultSurface) # Compare it to the first self.assertAlmostEqual(self.fault_source.dip, fault2.dip) # If less than two edges are input ensure error is raised bad_traces = [line.Line([point.Point(1.0, 0.0, 3.0), point.Point(1.0, 0.0, 3.0)])] self.fault_source = mtkComplexFaultSource('101', 'A complex fault') with self.assertRaises(ValueError) as ver: self.fault_source.create_geometry(bad_traces) self.assertEqual(ver.exception.message, 'Complex fault geometry ' 'incorrectly defined') # If an edge is not defined from either a nhlib.geo.line.Line instance # or numpy.ndarray then ensure error is raised bad_traces = [line.Line([point.Point(1.0, 0.0, 3.0), point.Point(1.0, 0.0, 3.0)])] bad_traces.append('a bad input') self.fault_source = mtkComplexFaultSource('101', 'A complex fault') with self.assertRaises(ValueError) as ver: self.fault_source.create_geometry(bad_traces) self.assertEqual(ver.exception.message, 'Unrecognised or unsupported ' 'geometry definition')
def test_get_minmax_edges(self): ''' Tests the private method to extract the minimum and maximum depth from a set of edges ''' self.fault_source = mtkComplexFaultSource('101', 'A complex fault') # Test case simple edge self.fault_source._get_minmax_edges(self.trace_line[0]) self.assertAlmostEqual(self.fault_source.upper_depth, 0.9) self.assertAlmostEqual(self.fault_source.lower_depth, 1.0) self.fault_source._get_minmax_edges(self.trace_line[1]) self.assertAlmostEqual(self.fault_source.upper_depth, 0.9) self.assertAlmostEqual(self.fault_source.lower_depth, 45.0) # Check the same behaviour when input as array self.fault_source = mtkComplexFaultSource('101', 'A complex fault') # Test case simple edge self.fault_source._get_minmax_edges(self.trace_array[0]) self.assertAlmostEqual(self.fault_source.upper_depth, 0.9) self.assertAlmostEqual(self.fault_source.lower_depth, 1.0) self.fault_source._get_minmax_edges(self.trace_array[1]) self.assertAlmostEqual(self.fault_source.upper_depth, 0.9) self.assertAlmostEqual(self.fault_source.lower_depth, 45.0)
def test_create_oqnmrl_complex_fault_source(self): ''' Tests the conversion of a point source to an instance of the :class: oqnrmllib.models.AreaSource ''' # Define a complete source complex_edges = [ line.Line([point.Point(10., 10., 0.), point.Point(11., 10., 0.)]), line.Line( [point.Point(10., 10., 20.), point.Point(11.5, 10., 21.)]) ] self.fault_source = mtkComplexFaultSource('001', 'A Fault Source', trt='Active Shallow Crust', geometry=None, mag_scale_rel=None, rupt_aspect_ratio=1.0, mfd=models.TGRMFD( a_val=3., b_val=1.0, min_mag=5.0, max_mag=8.0), rake=0.) self.fault_source.create_geometry(complex_edges, 2.0) expected_geometry = models.ComplexFaultGeometry( top_edge_wkt='LINESTRING (10.0 10.0 0.0, 11.0 10.0 0.0)', bottom_edge_wkt='LINESTRING (10.0 10.0 20.0, 11.5 10.0 21.0)') expected_source = models.ComplexFaultSource('001', 'A Fault Source', trt='Active Shallow Crust', geometry=expected_geometry, mag_scale_rel='WC1994', rupt_aspect_ratio=1.0, mfd=models.TGRMFD( a_val=3., b_val=1.0, min_mag=5.0, max_mag=8.0), rake=90.) test_source = self.fault_source.create_oqnrml_source(use_defaults=True) self.assertTrue(isinstance(test_source, models.ComplexFaultSource)) self.assertEqual(test_source.id, expected_source.id) self.assertEqual(test_source.name, expected_source.name) self.assertAlmostEqual(test_source.mfd.b_val, expected_source.mfd.b_val)
def generate_fault_source_model(self): ''' Creates a resulting hmtk fault source set. :returns: source_model - list of instances of either the :class:`hmtk.sources.simple_fault_source.mtkSimpleFaultSource` or :class:`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_create_oqnmrl_complex_fault_source(self): """ Tests the conversion of a point source to an instance of the :class: oqnrmllib.models.AreaSource """ # Define a complete source complex_edges = [ line.Line([point.Point(10.0, 10.0, 0.0), point.Point(11.0, 10.0, 0.0)]), line.Line([point.Point(10.0, 10.0, 20.0), point.Point(11.5, 10.0, 21.0)]), ] self.fault_source = mtkComplexFaultSource( "001", "A Fault Source", trt="Active Shallow Crust", geometry=None, mag_scale_rel=None, rupt_aspect_ratio=1.0, mfd=models.TGRMFD(a_val=3.0, b_val=1.0, min_mag=5.0, max_mag=8.0), rake=0.0, ) self.fault_source.create_geometry(complex_edges, 2.0) expected_geometry = models.ComplexFaultGeometry( top_edge_wkt="LINESTRING (10.0 10.0 0.0, 11.0 10.0 0.0)", bottom_edge_wkt="LINESTRING (10.0 10.0 20.0, 11.5 10.0 21.0)", ) expected_source = models.ComplexFaultSource( "001", "A Fault Source", trt="Active Shallow Crust", geometry=expected_geometry, mag_scale_rel="WC1994", rupt_aspect_ratio=1.0, mfd=models.TGRMFD(a_val=3.0, b_val=1.0, min_mag=5.0, max_mag=8.0), rake=90.0, ) test_source = self.fault_source.create_oqnrml_source(use_defaults=True) self.assertTrue(isinstance(test_source, models.ComplexFaultSource)) self.assertEqual(test_source.id, expected_source.id) self.assertEqual(test_source.name, expected_source.name) self.assertAlmostEqual(test_source.mfd.b_val, expected_source.mfd.b_val)
def test_create_oqnmrl_complex_fault_source(self): ''' Tests the conversion of a point source to an instance of the :class: oqnrmllib.models.AreaSource ''' complex_edges = [ line.Line([point.Point(11., 10., 0.), point.Point(10., 10., 0.)]), line.Line([point.Point(11.5, 10., 21.), point.Point(10.0, 10., 21.)]) ] self.fault_source = mtkComplexFaultSource('001', 'A Fault Source', trt='Active Shallow Crust', geometry = None, mag_scale_rel=None, rupt_aspect_ratio=1.0, mfd=models.TGRMFD(a_val=3., b_val=1.0, min_mag=5.0, max_mag=8.0), rake=0.) self.fault_source.create_geometry(complex_edges, 2.0) expected_geometry=models.ComplexFaultGeometry( top_edge_wkt='LINESTRING (10.0 10.0 0.0, 11.0 10.0 0.0)', bottom_edge_wkt='LINESTRING (10.0 10.0 20.0, 11.5 10.0 21.0)') expected_source = models.ComplexFaultSource( '001', 'A Fault Source', trt='Active Shallow Crust', geometry=expected_geometry, mag_scale_rel='WC1994', rupt_aspect_ratio=1.0, mfd=models.TGRMFD(a_val=3., b_val=1.0, min_mag=5.0, max_mag=8.0), rake=90.) test_source = self.fault_source.create_oqnrml_source(use_defaults=True) self.assertTrue(isinstance(test_source, models.ComplexFaultSource)) self.assertEqual(test_source.id, expected_source.id) self.assertEqual(test_source.name, expected_source.name) self.assertAlmostEqual(test_source.mfd.b_val, expected_source.mfd.b_val)
def _parse_complex(cls, src_elem, mesh_spacing): """ :param src_elem: :class:`lxml.etree._Element` instance representing a source. :returns: Fully populated :class:`openquake.nrmllib.models.ComplexFaultSource` object. """ # Instantiate with identifier and name complx = mtkComplexFaultSource(src_elem.get('id'), src_elem.get('name')) print 'Complex Fault Source - ID: %s, name: %s' % (complx.id, complx.name) # Set common attributes cls._set_common_attrs(complx, src_elem) # Create the complex geometry complex_edges = cls._parse_complex_geometry(src_elem) complx.create_geometry(complex_edges, mesh_spacing) # Get mfd complx.mfd = cls._parse_mfd(src_elem) if _xpath(src_elem, './/nrml:rake')[0].text: complx.rake = float(_xpath(src_elem, './/nrml:rake')[0].text) return complx