def test(self): edges = [ Line([Point(-3.4, 5.5, 0), Point(-3.9, 5.3, 0)]), Line([Point(-2.4, 4.6, 10), Point(-3.6, 4.9, 20)]) ] polygon = ComplexFaultSurface.surface_projection_from_fault_data(edges) elons = [-2.4, -3.6, -3.9, -3.4] elats = [4.6, 4.9, 5.3, 5.5] numpy.testing.assert_allclose(polygon.lons, elons) numpy.testing.assert_allclose(polygon.lats, elats)
def test_invalid_surface_polygon_case3(self): # intermediate edge has opposite strike than top and bottom edges = [ Line([Point(0, 0), Point(0, 2)]), Line([Point(0.1, 2, 10), Point(0.1, 0, 10)]), Line([Point(0.2, 0, 20), Point(0.2, 2, 20)]) ] with self.assertRaises(ValueError) as cm: ComplexFaultSurface.from_fault_data(edges, mesh_spacing=10) self.assertEqual('Edges points are not in the right order', str(cm.exception))
def setUp(self): ''' ''' self.simple_edge = Line( [Point(10.5, 10.5, 1.0), Point(11.35, 11.45, 2.0)]) top_edge = Line([Point(10.5, 10.5, 1.0), Point(11.35, 11.45, 2.0)]) int_edge = Line([Point(10.5, 10.5, 20.0), Point(11.35, 11.45, 21.0)]) low_edge = Line([Point(10.5, 10.5, 40.0), Point(11.35, 11.45, 40.0)]) self.complex_edge = [top_edge, int_edge, low_edge]
def linestring_node_to_line(node, with_depth=False): """ Returns an instance of a Linestring node to :class: openquake.hazardlib.geo.line.Line """ assert "LineString" in node.tag crds = [float(x) for x in node.nodes[0].text.split()] if with_depth: return Line([Point(crds[iloc], crds[iloc + 1], crds[iloc + 2]) for iloc in range(0, len(crds), 3)]) else: return Line([Point(crds[iloc], crds[iloc + 1]) for iloc in range(0, len(crds), 2)])
def test_1(self): edge1 = Line([Point(0, 0), Point(0.03, 0)]) edge2 = Line([Point(0, 0, 2.224), Point(0.03, 0, 2.224)]) surface = ComplexFaultSurface.from_fault_data([edge1, edge2], mesh_spacing=1.112) self.assertIsInstance(surface, ComplexFaultSurface) self.assert_mesh_is(surface=surface, expected_mesh=[ [(0, 0, 0), (0.01, 0, 0), (0.02, 0, 0), (0.03, 0, 0)], [(0, 0, 1.112), (0.01, 0, 1.112), (0.02, 0, 1.112), (0.03, 0, 1.112)], [(0, 0, 2.224), (0.01, 0, 2.224), (0.02, 0, 2.224), (0.03, 0, 2.224)], ])
def setUp(self): ''' Creates a complex fault typology ''' x0 = Point(30., 30., 0.) x1 = x0.point_at(30., 0., 30.) x2 = x1.point_at(30., 0., 60.) 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.edges = [upper_edge, lower_edge] self.fault = None
def test_non_positive_mesh_spacing(self): edges = [ Line([Point(0, 0), Point(0, 1)]), Line([Point(0, 0, 1), Point(0, 1, 1)]) ] self.assertRaises(ValueError, ComplexFaultSurface.from_fault_data, edges, mesh_spacing=0) self.assertRaises(ValueError, ComplexFaultSurface.from_fault_data, edges, mesh_spacing=-1)
def get_target_sites_mesh(self, maximum_distance, spacing, vs30, vs30measured=True, z1pt0=None, z2pt5=None, backarc=False): """ Renders a two dimensional mesh of points over the rupture surface """ # Get bounding box of dilated rupture lowx, highx, lowy, highy = self._get_limits_maximum_rjb( maximum_distance) # Create bounding box lines and then resample at spacing ewline = Line([Point(lowx, highy, 0.), Point(highx, highy, 0.)]) nsline = Line([Point(lowx, highy, 0.), Point(lowx, lowy, 0.)]) ewline = ewline.resample(spacing) nsline = nsline.resample(spacing) xvals = np.array([pnt.longitude for pnt in ewline.points]) yvals = np.array([pnt.latitude for pnt in nsline.points]) gridx, gridy = np.meshgrid(xvals, yvals) numx, numy = np.shape(gridx) npts = numx * numy gridx = (np.reshape(gridx, npts, 1)).flatten() gridy = (np.reshape(gridy, npts, 1)).flatten() site_list = [] if not z1pt0: #z1pt0 = vs30_to_z1pt0_as08(vs30) z1pt0 = vs30_to_z1pt0_cy14(vs30) if not z2pt5: #z2pt5 = z1pt0_to_z2pt5(z1pt0) z2pt5 = vs30_to_z2pt5_cb14(vs30) for iloc in range(0, npts): site_list.append(Site(Point(gridx[iloc], gridy[iloc], 0.), vs30, vs30measured, z1pt0, z2pt5, backarc=backarc)) self.target_sites = SiteCollection(site_list) self.target_sites_config = { "TYPE": "Mesh", "RMAX": maximum_distance, "SPACING": spacing, "VS30": vs30, "VS30MEASURED": vs30measured, "Z1.0": z1pt0, "Z2.5": z2pt5, "BACKARC": backarc} return self.target_sites
def test_dip_90_three_points(self): edges = [ Line([Point(1, -20, 30), Point(1, -20.2, 30), Point(2, -19.7, 30)]), Line([Point(1, -20, 50), Point(1, -20.2, 50), Point(2, -19.7, 50)]) ] polygon = ComplexFaultSurface.surface_projection_from_fault_data(edges) elons = [1, 1, 2] elats = [-20.2, -20., -19.7] numpy.testing.assert_allclose(polygon.lons, elons) numpy.testing.assert_allclose(polygon.lats, elats)
def test_dip_left_of_fault_strike_case1(self): # checks that an error is raised when fault surface dips left of # fault strike (i.e. does not obey to Aki & Richards convention) # simple case of planar surface with strike 0 (pointing towards # north) but with surface dipping to the west edges = [Line([Point(0, 0), Point(0, 1)]), Line([Point(-1, 0, 10), Point(-1, 1, 10)])] with self.assertRaises(ValueError) as cm: ComplexFaultSurface.from_fault_data(edges, mesh_spacing=10) self.assertEqual( 'Surface does not conform with Aki & Richards convention', str(cm.exception) )
def test_dip_90_two_points(self): edges = [ Line([Point(2, 2, 10), Point(1, 1, 10)]), Line([Point(2, 2, 20), Point(1, 1, 20)]) ] polygon = ComplexFaultSurface.surface_projection_from_fault_data(edges) elons = [ 1.00003181, 0.99996821, 0.99996819, 1.99996819, 2.00003182, 2.00003181 ] elats = [ 0.99996822, 0.99996819, 1.00003178, 2.0000318, 2.0000318, 1.9999682 ] numpy.testing.assert_allclose(polygon.lons, elons) numpy.testing.assert_allclose(polygon.lats, elats)
def test_surface_with_variable_width(self): edges = [ Line([ Point(0.1, 0.1, 0), Point(0.459729190252, 0.0999980290582, 0.0), Point(0.819458380482, 0.0999960581553, 0.0) ]), Line([ Point(0.1, 0.1, 20.0), Point(0.459729190252, 0.0999980290582, 20.0), Point(0.819458380482, 0.0999960581553, 43.0940107676) ]) ] surface = ComplexFaultSurface.from_fault_data(edges, mesh_spacing=5.0) self.assertAlmostEqual(surface.get_width(), 26.0, places=0)
def get_grd_nodes_within_buffer(self, x, y, buffer_distance, minlo, maxlo, minla, maxla): """ :parameter x: An iterable containing the longitudes of the points defining the polyline :parameter y: An iterable containing the latitudes of the points defining the polyline :parameter buffer_distance: Horizontal buffer_distance used to select earthquakes included in the catalogue [in km] :parameter minlo: :parameter minla: :parameter maxlo: :parameter maxla: """ line = Line([Point(lo, la) for lo, la in zip(self.plo, self.pla)]) idxs = numpy.nonzero((x > minlo) & (x < maxlo) & (y > minla) & (y < maxla)) xs = x[idxs[0]] ys = y[idxs[0]] coo = [(lo, la) for lo, la in zip(list(xs), list(ys))] if len(coo): dst = get_min_distance(line, numpy.array(coo)) return idxs[0][abs(dst) <= buffer_distance] else: print(' Warning: no nodes found around the cross-section') return None
def _parse_edge_to_line(cls, edge_string, dimension=2): ''' For a string returned from the _xpath function, convert to an instance of a line class :param edge_string: List of nodes in format returned from _xpath :param int dimension: Number of dimenions - 2 (Long, Lat) or 3 (Long, Lat, Depth) ''' coords = edge_string.text.split() if dimension == 3: # Long lat and depth edge = [ Point(float(coords[iloc]), float(coords[iloc + 1]), float(coords[iloc + 2])) for iloc in range(0, len(coords), dimension) ] else: # Only long & lat edge = [ Point(float(coords[iloc]), float(coords[iloc + 1])) for iloc in range(0, len(coords), dimension) ] return Line(edge)
def make_rupture(self): # Create the rupture surface. upper_seismogenic_depth = 3. lower_seismogenic_depth = 15. dip = 90. mesh_spacing = 1. fault_trace_start = Point(28.531397, 40.8790859336) fault_trace_end = Point(28.85, 40.9) fault_trace = Line([fault_trace_start, fault_trace_end]) default_arguments = { 'mag': 6.5, 'rake': 180., 'tectonic_region_type': const.TRT.STABLE_CONTINENTAL, 'hypocenter': Point(28.709146553353872, 40.890863701462457, 11.0), 'surface': SimpleFaultSurface.from_fault_data(fault_trace, upper_seismogenic_depth, lower_seismogenic_depth, dip=dip, mesh_spacing=mesh_spacing), 'rupture_slip_direction': 0., 'occurrence_rate': 0.01, 'temporal_occurrence_model': PoissonTOM(50) } kwargs = default_arguments rupture = ParametricProbabilisticRupture(**kwargs) return rupture
def test_fault_trace_points(self): """ The fault trace must have at least two points. """ fault_trace = Line([Point(0.0, 0.0)]) self.assertRaises(ValueError, SimpleFaultSurface.check_fault_data, fault_trace, 0.0, 1.0, 90.0, 1.0)
def test_get_dip_2(self): p1 = Point(0.0, 0.0) p2 = Point(0.0635916966572, 0.0635916574897) surface = SimpleFaultSurface.from_fault_data(Line([p1, p2]), 1.0, 6.0, 30.0, 1.0) self.assertAlmostEquals(30.0, surface.get_dip(), 1)
def test_get_strike_1(self): p1 = Point(0.0, 0.0) p2 = Point(0.0635916966572, 0.0635916574897) surface = SimpleFaultSurface.from_fault_data(Line([p1, p2]), 1.0, 6.0, 89.9, 1.0) self.assertAlmostEquals(45.0, surface.get_strike(), delta=1e-4)
def test_edges_with_nonuniform_length(self): edges = [ Line([ Point(1, -20, 30), Point(1, -20.2, 30), Point(2, -19.7, 30), Point(3, -19.5, 30) ]), Line([Point(1, -20, 50), Point(1, -20.2, 50), Point(2, -19.7, 50)]) ] polygon = ComplexFaultSurface.surface_projection_from_fault_data(edges) elons = [1, 1, 2, 3] elats = [-20.2, -20., -19.7, -19.5] numpy.testing.assert_allclose(polygon.lons, elons) numpy.testing.assert_allclose(polygon.lats, elats)
def test_inclined_non_planar_surface(self): p1 = Point(0.1, 0.1, 0.0) p2 = Point(0.1, 0.117986432118, 0.0) p3 = Point(0.117986470254, 0.117986426305, 0.0) p4 = Point(0.117986470254, 0.0999999941864, 0.0) surface = SimpleFaultSurface.from_fault_data(Line([p1, p2, p3, p4]), 2.0, 4.0, 30.0, 1.0) self.assertAlmostEqual(surface.get_width(), 4.0, places=2)
def test_get_strike_2(self): p1 = Point(0.0, 0.0) p2 = Point(0.0635916966572, 0.0635916574897) p3 = Point(0.0860747816618, 0.102533437776) surface = SimpleFaultSurface.from_fault_data(Line([p1, p2, p3]), 1.0, 6.0, 89.9, 1.0) self.assertAlmostEqual(40.0, surface.get_strike(), delta=0.02)
def test_dip_left_of_fault_strike_topo(self): # when the fault is above sea level edges = [ Line([ Point(0, 1, -1), Point(0, 0, -1) ]), Line([ Point(1, 1, 0), Point(1, 0, 0)] )] with self.assertRaises(ValueError) as cm: ComplexFaultSurface.from_fault_data(edges, mesh_spacing=1) self.assertEqual( 'Surface does not conform with Aki & Richards convention', str(cm.exception) )
def test_get_dip_1(self): p1 = Point(0.0, 0.0) p2 = Point(0.0635916966572, 0.0635916574897) p3 = Point(0.0860747816618, 0.102533437776) surface = SimpleFaultSurface.from_fault_data(Line([p1, p2, p3]), 1.0, 6.0, 90.0, 1.0) self.assertAlmostEquals(90.0, surface.get_dip(), delta=1e-6)
def test_get_mesh_5(self): p1 = Point(179.9, 0.0) p2 = Point(180.0, 0.0) p3 = Point(-179.9, 0.0) fault = SimpleFaultSurface.from_fault_data(Line([p1, p2, p3]), 1.0, 6.0, 90.0, 1.0) self.assert_mesh_is(fault, test_data.TEST_5_MESH)
def test_get_fault_vertices_3d(self): p0, p1, p2, p3 = SimpleFaultSurface.get_fault_patch_vertices( Line([Point(10., 45.2), Point(10.5, 45.3), Point(10., 45.487783)]), upper_seismogenic_depth=0., lower_seismogenic_depth=14., dip=30, index_patch=1.) p4, p5, p6, p7 = SimpleFaultSurface.get_fault_patch_vertices( Line([Point(10., 45.2), Point(10.5, 45.3), Point(10., 45.487783)]), upper_seismogenic_depth=0., lower_seismogenic_depth=14., dip=30, index_patch=2.) # Test for the first patch self.assertAlmostEqual(p0.longitude, 10., delta=0.1) self.assertAlmostEqual(p0.latitude, 45.2, delta=0.1) self.assertAlmostEqual(p0.depth, 0., delta=0.1) self.assertAlmostEqual(p1.longitude, 10.5, delta=0.1) self.assertAlmostEqual(p1.latitude, 45.3, delta=0.1) self.assertAlmostEqual(p1.depth, 0., delta=0.1) self.assertAlmostEqual(p2.longitude, 10.81, delta=0.1) self.assertAlmostEqual(p2.latitude, 45.2995, delta=0.1) self.assertAlmostEqual(p2.depth, 14., delta=0.1) self.assertAlmostEqual(p3.longitude, 10.31, delta=0.1) self.assertAlmostEqual(p3.latitude, 45.1995, delta=0.1) self.assertAlmostEqual(p3.depth, 14., delta=0.1) # Test for the second patch self.assertAlmostEqual(p4.longitude, 10.5, delta=0.1) self.assertAlmostEqual(p4.latitude, 45.3, delta=0.1) self.assertAlmostEqual(p4.depth, 0., delta=0.1) self.assertAlmostEqual(p5.longitude, 10.0, delta=0.1) self.assertAlmostEqual(p5.latitude, 45.4877, delta=0.1) self.assertAlmostEqual(p5.depth, 0., delta=0.1) self.assertAlmostEqual(p6.longitude, 10.311, delta=0.1) self.assertAlmostEqual(p6.latitude, 45.4873, delta=0.1) self.assertAlmostEqual(p6.depth, 14., delta=0.1) self.assertAlmostEqual(p7.longitude, 10.81, delta=0.1) self.assertAlmostEqual(p7.latitude, 45.2995, delta=0.1) self.assertAlmostEqual(p7.depth, 14., delta=0.1)
def test_dip_90_three_points(self): polygon = SimpleFaultSurface.surface_projection_from_fault_data( Line([Point(1, -20), Point(1, -20.2), Point(2, -19.7)]), dip=90, upper_seismogenic_depth=30, lower_seismogenic_depth=50, ) elons = [1, 1, 2] elats = [-20.2, -20., -19.7] numpy.testing.assert_allclose(polygon.lons, elons) numpy.testing.assert_allclose(polygon.lats, elats)
def test_dip_90_self_intersection(self): polygon = SimpleFaultSurface.surface_projection_from_fault_data( Line([Point(1, -2), Point(2, -1.9), Point(3, -2.1), Point(4, -2)]), dip=90, upper_seismogenic_depth=10, lower_seismogenic_depth=20, ) elons = [3., 1., 2., 4.] elats = [-2.1, -2., -1.9, -2.] numpy.testing.assert_allclose(polygon.lons, elons) numpy.testing.assert_allclose(polygon.lats, elats)
def test_get_mesh_topo(self): p1 = Point(0.0, 0.0, -2.0) p2 = Point(0.0, 0.0359728811759, -2.0) p3 = Point(0.0190775080917, 0.0550503815182, -2.0) p4 = Point(0.03974514139, 0.0723925718856, -2.0) fault = SimpleFaultSurface.from_fault_data(Line([p1, p2, p3, p4]), -2.0, 2.0, 90.0, 1.0) self.assert_mesh_is(fault, test_data.TEST_TOPO_MESH)
def test_dip_left_of_fault_strike_case2(self): # real example taken from wrong fault for japan model # ('Kanto earthquake') edges = [ Line([ Point(139.268, 35.3649682834, 10.6), Point(139.579014512, 35.1780000001, 10.6) ]), Line([ Point(139.541937161, 35.378, 19.5999999911), Point(139.867999999, 35.2135133354, 19.6000000095) ]) ] with self.assertRaises(ValueError) as cm: ComplexFaultSurface.from_fault_data(edges, mesh_spacing=10) self.assertEqual( 'Surface does not conform with Aki & Richards convention', str(cm.exception))
def test_get_mesh_1(self): p1 = Point(0.0, 0.0, 0.0) p2 = Point(0.0, 0.0359728811759, 0.0) p3 = Point(0.0190775080917, 0.0550503815182, 0.0) p4 = Point(0.03974514139, 0.0723925718856, 0.0) fault = SimpleFaultSurface.from_fault_data( Line([p1, p2, p3, p4]), 0.0, 4.2426406871192848, 45.0, 1.0) self.assert_mesh_is(fault, test_data.TEST_1_MESH)
def test_dip_90_self_intersection(self): edges = [ Line([ Point(1, -2, 10), Point(2, -1.9, 10), Point(3, -2.1, 10), Point(4, -2, 10) ]), Line([ Point(1, -2, 20), Point(2, -1.9, 20), Point(3, -2.1, 20), Point(4, -2, 20) ]) ] polygon = ComplexFaultSurface.surface_projection_from_fault_data(edges) elons = [3., 1., 2., 4.] elats = [-2.1, -2., -1.9, -2.] numpy.testing.assert_allclose(polygon.lons, elons) numpy.testing.assert_allclose(polygon.lats, elats)
def get_target_sites_mesh(self, maximum_distance, spacing, vs30, vs30measured=True, z1pt0=None, z2pt5=None): """ Renders a two dimensional mesh of points over the rupture surface """ # Get bounding box of dilated rupture lowx, highx, lowy, highy = self._get_limits_maximum_rjb( maximum_distance) # Create bounding box lines and then resample at spacing ewline = Line([Point(lowx, highy, 0.), Point(highx, highy, 0.)]) nsline = Line([Point(lowx, highy, 0.), Point(lowx, lowy, 0.)]) ewline = ewline.resample(spacing) nsline = nsline.resample(spacing) xvals = np.array([pnt.longitude for pnt in ewline.points]) yvals = np.array([pnt.latitude for pnt in nsline.points]) gridx, gridy = np.meshgrid(xvals, yvals) numx, numy = np.shape(gridx) npts = numx * numy gridx = (np.reshape(gridx, npts, 1)).flatten() gridy = (np.reshape(gridy, npts, 1)).flatten() site_list = [] if not z1pt0: z1pt0 = vs30_to_z1pt0_as08(vs30) if not z2pt5: z2pt5 = z1pt0_to_z2pt5(z1pt0) for iloc in range(0, npts): site_list.append(Site(Point(gridx[iloc], gridy[iloc], 0.), vs30, vs30measured, z1pt0, z2pt5)) self.target_sites = SiteCollection(site_list) return self.target_sites
def read_fault_geometry(self, geo_dict, mesh_spacing=1.0): ''' Creates the fault geometry from the parameters specified in the dictionary. :param dict geo_dict: Sub-dictionary of main fault dictionary containing only the geometry attributes :param float mesh_spacing: Fault mesh spacing (km) :returns: Instance of SimpleFaultGeometry or ComplexFaultGeometry, depending on typology ''' if geo_dict['Fault_Typology'] == 'Simple': # Simple fault geometry raw_trace = geo_dict['Fault_Trace'] trace = Line([Point(raw_trace[ival], raw_trace[ival + 1]) for ival in range(0, len(raw_trace), 2)]) geometry = SimpleFaultGeometry(trace, geo_dict['Dip'], geo_dict['Upper_Depth'], geo_dict['Lower_Depth'], mesh_spacing) elif geo_dict['Fault_Typology'] == 'Complex': # Complex Fault Typology trace = [] for raw_trace in geo_dict['Fault_Trace']: fault_edge = Line( [Point(raw_trace[ival], raw_trace[ival + 1], raw_trace[ival + 2]) for ival in range(0, len(raw_trace), 3)]) trace.append(fault_edge) geometry = ComplexFaultGeometry(trace, mesh_spacing) else: raise ValueError('Unrecognised or unsupported fault geometry!') return geometry