def test_inclined_surface(self): corners = [Point(-0.00317958, -0.00449661, 4.64644661), Point(-0.00317958, 0.00449661, 4.64644661), Point(0.00317958, 0.00449661, 5.35355339), Point(0.00317958, -0.00449661, 5.35355339)] surface = PlanarSurface(1, 0.0, 45.0, *corners) self.assertAlmostEqual(surface.get_width(), 1.0, places=3)
def test_nine_positions(self): def v2p(*vectors): # "vectors to points" return [Point(*coords) for coords in zip(*geo_utils.cartesian_to_spherical( numpy.array(vectors, dtype=float) ))] corners = v2p([6370, 0, -0.5], [6370, 0, 0.5], [6369, 2, 0.5], [6369, 2, -0.5]) surface = PlanarSurface(1, 2, 3, *corners) # first three positions: point projection is above the top edge dists = surface.get_min_distance(Mesh.from_points_list( v2p([6371, 0, -1.5], [6371, 0, 1.5], [6371, 0, 0.33]) )) self.assertTrue(numpy.allclose(dists, [2 ** 0.5, 2 ** 0.5, 1.0], atol=1e-4)) # next three positions: point projection is below the bottom edge dists = surface.get_min_distance(Mesh.from_points_list( v2p([6368, 2, -1.5], [6368, 2, 1.5], [6368, 2, -0.45]) )) self.assertTrue(numpy.allclose(dists, [2 ** 0.5, 2 ** 0.5, 1.0], atol=1e-4)) # next three positions: point projection is left to rectangle, # right to it or lies inside dists = surface.get_min_distance(Mesh.from_points_list( v2p([6369.5, 1, -1.5], [6369.5, 1, 1.5], [6369.5, 1, -0.1]) )) self.assertTrue(numpy.allclose(dists, [1, 1, 0], atol=1e-4))
def test8_strike_of_45_degrees(self): corners = [Point(-0.05, -0.05, 8), Point(0.05, 0.05, 8), Point(0.05, 0.05, 9), Point(-0.05, -0.05, 9)] surface = PlanarSurface(1, 45, 60, *corners) sites = Mesh.from_points_list([Point(0.05, 0)]) self.assertAlmostEqual(surface.get_rx_distance(sites)[0], 3.9313415355436705, places=4)
def test_point_outside(self): corners = [Point(0.1, -0.1, 1), Point(-0.1, -0.1, 1), Point(-0.1, 0.1, 2), Point(0.1, 0.1, 2)] surface = PlanarSurface(1, 270, 45, *corners) sites = Mesh.from_points_list( [ Point(-0.2, -0.2), Point(1, 1, 1), Point(4, 5), Point(0.8, 0.01), Point(0.2, -0.15), Point(0.02, -0.12), Point(-0.14, 0), Point(-3, 3), Point(0.05, 0.15, 10), ] ) dists = surface.get_joyner_boore_distance(sites) expected_dists = [ Point(-0.2, -0.2).distance(Point(-0.1, -0.1)), Point(1, 1).distance(Point(0.1, 0.1)), Point(4, 5).distance(Point(0.1, 0.1)), Point(0.8, 0.01).distance(Point(0.1, 0.01)), Point(0.2, -0.15).distance(Point(0.1, -0.1)), Point(0.02, -0.12).distance(Point(0.02, -0.1)), Point(-0.14, 0).distance(Point(-0.1, 0)), Point(-3, 3).distance(Point(-0.1, 0.1)), Point(0.05, 0.15).distance(Point(0.05, 0.1)), ] self.assertTrue(numpy.allclose(dists, expected_dists, atol=0.05))
def test_point_on_the_border(self): corners = [Point(0.1, -0.1, 1), Point(-0.1, -0.1, 1), Point(-0.1, 0.1, 2), Point(0.1, 0.1, 2)] surface = PlanarSurface(1, 270, 45, *corners) sites = Mesh.from_points_list([Point(-0.1, 0.04), Point(0.1, 0.03)]) dists = surface.get_joyner_boore_distance(sites) expected_dists = [0] * 2 self.assertTrue(numpy.allclose(dists, expected_dists))
def test_point_inside(self): corners = [Point(-1, -1, 1), Point(1, -1, 1), Point(1, 1, 2), Point(-1, 1, 2)] surface = PlanarSurface(10, 90, 45, *corners) sites = Mesh.from_points_list([Point(0, 0), Point(0, 0, 20), Point(0.1, 0.3)]) dists = surface.get_joyner_boore_distance(sites) expected_dists = [0] * 3 self.assertTrue(numpy.allclose(dists, expected_dists))
def test2(self): surface = PlanarSurface( 10, 20, 30, Point(3.9, 2.2, 10), Point(4.90402718, 3.19634248, 10), Point(5.9, 2.2, 90), Point(4.89746275, 1.20365263, 90) ) plons, plats, pdepths = [[4., 4.3, 3.1], [1.5, 1.7, 3.5], [11., 12., 13.]] dists, xx, yy = surface._project(plons, plats, pdepths) lons, lats, depths = surface._project_back(dists, xx, yy) aaae = numpy.testing.assert_array_almost_equal aaae(lons, plons) aaae(lats, plats) aaae(depths, pdepths)
def test_against_mesh_to_mesh(self): corners = [Point(2.6, 3.7, 20), Point(2.90102155, 3.99961567, 20), Point(3.2, 3.7, 75), Point(2.89905849, 3.40038407, 75)] surface = PlanarSurface(0.5, 45, 70, *corners) lons, lats = numpy.meshgrid(numpy.linspace(2.2, 3.6, 7), numpy.linspace(3.4, 4.2, 7)) sites = Mesh(lons, lats, depths=None) res1 = surface.get_closest_points(sites) res2 = super(PlanarSurface, surface).get_closest_points(sites) aae = numpy.testing.assert_almost_equal # precision up to ~1 km aae(res1.lons, res2.lons, decimal=2) aae(res1.lats, res2.lats, decimal=2) aae(res1.depths, res2.depths, decimal=0)
class PlanarSurfaceGetClosestPointsTestCase(unittest.TestCase): corners = [Point(-0.1, -0.1, 0), Point(0.1, -0.1, 0), Point(0.1, 0.1, 2), Point(-0.1, 0.1, 2)] surface = PlanarSurface(10, 90, 45, *corners) def test_point_above_surface(self): sites = Mesh.from_points_list([Point(0, 0), Point(-0.03, 0.05, 0.5)]) res = self.surface.get_closest_points(sites) self.assertIsInstance(res, Mesh) aae = numpy.testing.assert_almost_equal aae(res.lons, [0, -0.03], decimal=4) aae(res.lats, [-0.00081824, 0.04919223]) aae(res.depths, [1.0113781, 1.50822185]) def test_corner_is_closest(self): sites = Mesh.from_points_list( [Point(-0.11, 0.11), Point(0.14, -0.12, 10), Point(0.3, 0.2, 0.5), Point(-0.6, -0.6, 0.3)] ) res = self.surface.get_closest_points(sites) aae = numpy.testing.assert_almost_equal aae(res.lons, [-0.1, 0.1, 0.1, -0.1], decimal=4) aae(res.lats, [0.1, -0.1, 0.1, -0.1]) aae(res.depths, [2, 0, 2, 0], decimal=5) def test_top_or_bottom_edge_is_closest(self): sites = Mesh.from_points_list([Point(-0.04, -0.28, 0), Point(0.033, 0.15, 0)]) res = self.surface.get_closest_points(sites) aae = numpy.testing.assert_almost_equal aae(res.lons, [-0.04, 0.033], decimal=5) aae(res.lats, [-0.1, 0.1], decimal=5) aae(res.depths, [0, 2], decimal=2) def test_left_or_right_edge_is_closest(self): sites = Mesh.from_points_list([Point(-0.24, -0.08, 0.55), Point(0.17, 0.07, 0)]) res = self.surface.get_closest_points(sites) aae = numpy.testing.assert_almost_equal aae(res.lons, [-0.1, 0.1], decimal=5) aae(res.lats, [-0.08, 0.07], decimal=3) aae(res.depths, [0.20679306, 1.69185737]) def test_against_mesh_to_mesh(self): corners = [Point(2.6, 3.7, 20), Point(2.90102155, 3.99961567, 20), Point(3.2, 3.7, 75), Point(2.89905849, 3.40038407, 75)] surface = PlanarSurface(0.5, 45, 70, *corners) lons, lats = numpy.meshgrid(numpy.linspace(2.2, 3.6, 7), numpy.linspace(3.4, 4.2, 7)) sites = Mesh(lons, lats, depths=None) res1 = surface.get_closest_points(sites) res2 = super(PlanarSurface, surface).get_closest_points(sites) aae = numpy.testing.assert_almost_equal # precision up to ~1 km aae(res1.lons, res2.lons, decimal=2) aae(res1.lats, res2.lats, decimal=2) aae(res1.depths, res2.depths, decimal=0)
def assert_successfull_creation(self, mesh_spacing, strike, dip, tl, tr, br, bl): surface1 = PlanarSurface(mesh_spacing, strike, dip, tl, tr, br, bl) translated = surface1.translate(tl, tr).translate(tr, tl) for surface in [surface1, translated]: self.assertIsInstance(surface, PlanarSurface) self.assertEqual(surface.top_left, tl) self.assertEqual(surface.top_right, tr) self.assertEqual(surface.bottom_left, bl) self.assertEqual(surface.bottom_right, br) self.assertEqual(surface.mesh_spacing, mesh_spacing) self.assertEqual(surface.strike, strike) self.assertEqual(surface.get_strike(), strike) self.assertEqual(surface.dip, dip) self.assertEqual(surface.get_dip(), dip) self.assertAlmostEqual(surface.length, tl.distance(tr), delta=0.2) self.assertAlmostEqual(surface.width, tl.distance(bl), delta=0.2)
def assert_successfull_creation(self, mesh_spacing, strike, dip, tl, tr, br, bl): surface1 = PlanarSurface(mesh_spacing, strike, dip, tl, tr, br, bl) translated = surface1.translate(tl, tr).translate(tr, tl) for surface in [surface1, translated]: self.assertIsInstance(surface, PlanarSurface) self.assertEqual(surface.top_left, tl) self.assertEqual(surface.top_right, tr) self.assertEqual(surface.bottom_left, bl) self.assertEqual(surface.bottom_right, br) self.assertEqual(surface.mesh_spacing, mesh_spacing) self.assertEqual(surface.strike, strike) self.assertEqual(surface.get_strike(), strike) self.assertEqual(surface.dip, dip) self.assertEqual(surface.get_dip(), dip) self.assertIsNone(surface._mesh) self.assertAlmostEqual(surface.length, tl.distance(tr), delta=0.2) self.assertAlmostEqual(surface.width, tl.distance(bl), delta=0.2)
def test1(self): lons, lats, depths = geo_utils.cartesian_to_spherical( numpy.array([[60, -10, -10], [60, -10, 10], [60, 10, 10], [60, 10, -10]], float) ) surface = PlanarSurface(10, 20, 30, *Mesh(lons, lats, depths)) aaae = numpy.testing.assert_array_almost_equal plons, plats, pdepths = geo_utils.cartesian_to_spherical( numpy.array([[60, -10, -10], [59, 0, 0], [70, -11, -10]], float) ) dists, xx, yy = surface._project(plons, plats, pdepths) aaae(xx, [0, 10, 0]) aaae(yy, [0, 10, -1]) aaae(dists, [0, 1, -10]) lons, lats, depths = surface._project_back(dists, xx, yy) aaae(lons, plons) aaae(lats, plats) aaae(depths, pdepths)
def test_point_outside(self): corners = [Point(0.1, -0.1, 1), Point(-0.1, -0.1, 1), Point(-0.1, 0.1, 2), Point(0.1, 0.1, 2)] surface = PlanarSurface(1, 270, 45, *corners) sites = Mesh.from_points_list([ Point(-0.2, -0.2), Point(1, 1, 1), Point(4, 5), Point(0.8, 0.01), Point(0.2, -0.15), Point(0.02, -0.12), Point(-0.14, 0), Point(-3, 3), Point(0.05, 0.15, 10) ]) dists = surface.get_joyner_boore_distance(sites) expected_dists = [ Point(-0.2, -0.2).distance(Point(-0.1, -0.1)), Point(1, 1).distance(Point(0.1, 0.1)), Point(4, 5).distance(Point(0.1, 0.1)), Point(0.8, 0.01).distance(Point(0.1, 0.01)), Point(0.2, -0.15).distance(Point(0.1, -0.1)), Point(0.02, -0.12).distance(Point(0.02, -0.1)), Point(-0.14, 0).distance(Point(-0.1, 0)), Point(-3, 3).distance(Point(-0.1, 0.1)), Point(0.05, 0.15).distance(Point(0.05, 0.1)) ] self.assertTrue(numpy.allclose(dists, expected_dists, atol=0.05))
def make_rupture(rupture_class, **kwargs): default_arguments = { 'mag': 5.5, 'rake': 123.45, 'tectonic_region_type': const.TRT.STABLE_CONTINENTAL, 'hypocenter': Point(5, 6, 7), 'surface': PlanarSurface(10, 11, 12, Point(0, 0, 1), Point(1, 0, 1), Point(1, 0, 2), Point(0, 0, 2)), 'source_typology': object() } default_arguments.update(kwargs) kwargs = default_arguments rupture = rupture_class(**kwargs) for key in kwargs: assert getattr(rupture, key) is kwargs[key] return rupture
def _get_rupture_surface(self, mag, nodal_plane, hypocenter): """ Create and return rupture surface object with given properties. :param mag: Magnitude value, used to calculate rupture dimensions, see :meth:`_get_rupture_dimensions`. :param nodal_plane: Instance of :class:`nhlib.geo.nodalplane.NodalPlane` describing the rupture orientation. :param hypocenter: Point representing rupture's hypocenter. :returns: Instance of :class:`~nhlib.geo.surface.planar.PlanarSurface`. """ assert self.upper_seismogenic_depth <= hypocenter.depth \ and self.lower_seismogenic_depth >= hypocenter.depth rdip = math.radians(nodal_plane.dip) # precalculated azimuth values for horizontal-only and vertical-only # moves from one point to another on the plane defined by strike # and dip: azimuth_right = nodal_plane.strike azimuth_down = (azimuth_right + 90) % 360 azimuth_left = (azimuth_down + 90) % 360 azimuth_up = (azimuth_left + 90) % 360 rup_length, rup_width = self._get_rupture_dimensions(mag, nodal_plane) # calculate the height of the rupture being projected # on the vertical plane: rup_proj_height = rup_width * math.sin(rdip) # and it's width being projected on the horizontal one: rup_proj_width = rup_width * math.cos(rdip) # half height of the vertical component of rupture width # is the vertical distance between the rupture geometrical # center and it's upper and lower borders: hheight = rup_proj_height / 2 # calculate how much shallower the upper border of the rupture # is than the upper seismogenic depth: vshift = self.upper_seismogenic_depth - hypocenter.depth + hheight # if it is shallower (vshift > 0) than we need to move the rupture # by that value vertically. if vshift < 0: # the top edge is below upper seismogenic depth. now we need # to check that we do not cross the lower border. vshift = self.lower_seismogenic_depth - hypocenter.depth - hheight if vshift > 0: # the bottom edge of the rupture is above the lower sesmogenic # depth. that means that we don't need to move the rupture # as it fits inside seismogenic layer. vshift = 0 # if vshift < 0 than we need to move the rupture up by that value. # now we need to find the position of rupture's geometrical center. # in any case the hypocenter point must lie on the surface, however # the rupture center might be off (below or above) along the dip. rupture_center = hypocenter if vshift != 0: # we need to move the rupture center to make the rupture fit # inside the seismogenic layer. hshift = abs(vshift / math.tan(rdip)) rupture_center = rupture_center.point_at( horizontal_distance=hshift, vertical_increment=vshift, azimuth=(azimuth_up if vshift < 0 else azimuth_down)) # now we can find four corner points of the rupture rectangle. # we find the point that is on the same depth than the rupture # center but lies on the right border of its surface: right_center = rupture_center.point_at(horizontal_distance=rup_length / 2.0, vertical_increment=0, azimuth=azimuth_right) # than we get the right bottom corner: right_bottom = right_center.point_at( horizontal_distance=rup_proj_width / 2.0, vertical_increment=rup_proj_height / 2.0, azimuth=azimuth_down) # and other three points can be easily found by stepping from # already known points horizontally only by rupture length # (to get to left point from right one) or horizontally and # vertically (to get to top edge from bottom). right_top = right_bottom.point_at(horizontal_distance=rup_proj_width, vertical_increment=-rup_proj_height, azimuth=azimuth_up) left_top = right_top.point_at(horizontal_distance=rup_length, vertical_increment=0, azimuth=azimuth_left) left_bottom = right_bottom.point_at(horizontal_distance=rup_length, vertical_increment=0, azimuth=azimuth_left) return PlanarSurface(self.rupture_mesh_spacing, nodal_plane.strike, nodal_plane.dip, left_top, right_top, right_bottom, left_bottom)
def test(self): corners = [Point(-0.05, -0.05, 8), Point(0.05, 0.05, 8), Point(0.05, 0.05, 9), Point(-0.05, -0.05, 9)] surface = PlanarSurface(1, 45, 60, *corners) self.assertEqual(surface.get_top_edge_depth(), 8)
def test_vertical_surface(self): corners = [Point(-0.05, -0.05, 8), Point(0.05, 0.05, 8), Point(0.05, 0.05, 10), Point(-0.05, -0.05, 10)] surface = PlanarSurface(1, 45, 60, *corners) self.assertAlmostEqual(surface.get_width(), 2.0, places=4)
def _test1to7surface(self): corners = [Point(0, 0, 8), Point(-0.1, 0, 8), Point(-0.1, 0, 9), Point(0, 0, 9)] surface = PlanarSurface(1, 90, 60, *corners) return surface
def test_2(self): surface = PlanarSurface(1, 2, 3, *test_data.TEST_7_RUPTURE_6_CORNERS) sites = Mesh.from_points_list([Point(-0.25, 0.25)]) self.assertAlmostEqual(40.1213468, surface.get_min_distance(sites)[0], places=1)
def test_3(self): surface = PlanarSurface(1, 2, 3, *test_data.TEST_7_RUPTURE_2_CORNERS) sites = Mesh.from_points_list([Point(0, 0)]) self.assertAlmostEqual(7.01186304977, surface.get_min_distance(sites)[0], places=2)
def test_4(self): surface = PlanarSurface(1, 2, 3, *test_data.TEST_7_RUPTURE_2_CORNERS) sites = Mesh.from_points_list([Point(-0.3, 0.4)]) self.assertAlmostEqual(55.6159556, surface.get_min_distance(sites)[0], delta=0.6)
def assert_failed_creation(self, mesh_spacing, strike, dip, corners, exc, msg): with self.assertRaises(exc) as ae: PlanarSurface(mesh_spacing, strike, dip, *corners) self.assertEqual(ae.exception.message, msg)
def _surface(self, corners): return PlanarSurface(1.0, 0.0, 90.0, *corners)