def geo_line(self, edge): """ Utility function to convert a node of kind edge into a :class:`openquake.hazardlib.geo.Line` instance. :param edge: a node describing an edge """ with self.context(edge.LineString.posList) as plist: coords = split_coords_2d(~plist) return geo.Line([geo.Point(*p) for p in coords])
def complexGeom(utype, node, filename): if hasattr(node, 'complexFaultGeometry'): node = node.complexFaultGeometry _validate_complex_fault_geometry(utype, node, filename) spacing = node["spacing"] edges = [] for edge_node in node.nodes: coords = split_coords_3d(~edge_node.LineString.posList) edges.append(geo.Line([geo.Point(*p) for p in coords])) return edges, spacing
def test_simple(self): points = [geo.Point(0, 0), geo.Point(0.1, 0.3)] line = geo.Line(points).resample_to_num_points(3) expected_points = [ geo.Point(0, 0), geo.Point(0.05, 0.15), geo.Point(0.1, 0.3) ] self.assertEqual(line.points, expected_points) line = geo.Line(points).resample_to_num_points(4) expected_points = [ geo.Point(0, 0), geo.Point(0.0333333, 0.1), geo.Point(0.0666666, 0.2), geo.Point(0.1, 0.3) ] self.assertEqual(line.points, expected_points)
def simpleGeom(utype, node, filename): if hasattr(node, 'simpleFaultGeometry'): node = node.simpleFaultGeometry _validate_simple_fault_geometry(utype, node, filename) spacing = node["spacing"] usd, lsd, dip = (~node.upperSeismoDepth, ~node.lowerSeismoDepth, ~node.dip) coords = split_coords_2d(~node.LineString.posList) trace = geo.Line([geo.Point(*p) for p in coords]) return trace, usd, lsd, dip, spacing
def test_remove_adjacent_duplicates(self): p1 = geo.Point(0.0, 0.0, 0.0) p2 = geo.Point(0.0, 1.0, 0.0) p3 = geo.Point(0.0, 1.0, 0.0) p4 = geo.Point(0.0, 2.0, 0.0) p5 = geo.Point(0.0, 3.0, 0.0) p6 = geo.Point(0.0, 3.0, 0.0) expected = [p1, p2, p4, p5] self.assertEquals(expected, geo.Line([p1, p2, p3, p4, p5, p6]).points)
def _expected_complex(self): tgr_mfd = mfd.TruncatedGRMFD(a_val=-3.5, b_val=1.0, min_mag=5.0, max_mag=6.5, bin_width=1.0) edges = [ geo.Line([ geo.Point(-124.704, 40.363, 0.5493260E+01), geo.Point(-124.977, 41.214, 0.4988560E+01), geo.Point(-125.140, 42.096, 0.4897340E+01), ]), geo.Line([ geo.Point(-124.704, 40.363, 0.5593260E+01), geo.Point(-124.977, 41.214, 0.5088560E+01), geo.Point(-125.140, 42.096, 0.4997340E+01), ]), geo.Line([ geo.Point(-124.704, 40.363, 0.5693260E+01), geo.Point(-124.977, 41.214, 0.5188560E+01), geo.Point(-125.140, 42.096, 0.5097340E+01), ]), geo.Line([ geo.Point(-123.829, 40.347, 0.2038490E+02), geo.Point(-124.137, 41.218, 0.1741390E+02), geo.Point(-124.252, 42.115, 0.1752740E+02), ]), ] cmplx = source.ComplexFaultSource( source_id="4", name="Cascadia Megathrust", tectonic_region_type="Subduction Interface", mfd=tgr_mfd, rupture_mesh_spacing=MESH_SPACING, magnitude_scaling_relationship=scalerel.WC1994(), rupture_aspect_ratio=2.0, edges=edges, rake=30.0) return cmplx
def _expected_char_complex(self): incr_mfd = mfd.EvenlyDiscretizedMFD( min_mag=5.0, bin_width=0.1, occurrence_rates=[ 0.0010614989, 8.8291627E-4, 7.3437777E-4, 6.108288E-4, 5.080653E-4]) edges = [ geo.Line([ geo.Point(-124.704, 40.363, 0.5493260E+01), geo.Point(-124.977, 41.214, 0.4988560E+01), geo.Point(-125.140, 42.096, 0.4897340E+01), ]), geo.Line([ geo.Point(-124.704, 40.363, 0.5593260E+01), geo.Point(-124.977, 41.214, 0.5088560E+01), geo.Point(-125.140, 42.096, 0.4997340E+01), ]), geo.Line([ geo.Point(-124.704, 40.363, 0.5693260E+01), geo.Point(-124.977, 41.214, 0.5188560E+01), geo.Point(-125.140, 42.096, 0.5097340E+01), ]), geo.Line([ geo.Point(-123.829, 40.347, 0.2038490E+02), geo.Point(-124.137, 41.218, 0.1741390E+02), geo.Point(-124.252, 42.115, 0.1752740E+02), ])] complex_surface = geo.ComplexFaultSurface.from_fault_data( edges, self.complex_fault_mesh_spacing) char = source.CharacteristicFaultSource( source_id="6", name="characteristic source, complex fault", tectonic_region_type="Volcanic", mfd=incr_mfd, surface=complex_surface, rake=60.0, temporal_occurrence_model=PoissonTOM(50.0)) char.num_ruptures = char.count_ruptures() return char
def geo_lines(self, edges): """ Utility function to convert a list of edges into a list of :class:`openquake.hazardlib.geo.Line` instances. :param edge: a node describing an edge """ lines = [] for edge in edges: with context(self.fname, edge): coords = split_coords_3d(~edge.LineString.posList) lines.append(geo.Line([geo.Point(*p) for p in coords])) return lines
def test_resample_2(self): """ Line made of 3 points (aligned in the same direction) equally spaced (spacing equal to 10 km). The resampled line contains 2 points (with spacing of 30 km) consistent with the number of points as predicted by n = round(20 / 30) + 1. """ p1 = geo.Point(0.0, 0.0) p2 = geo.Point(0.0, 0.089932202939476777) p3 = geo.Point(0.0, 0.1798644058789465) self.assertEqual(2, len(geo.Line([p1, p2, p3]).resample(30.0)))
def _validate_simple_fault_geometry(utype, node, filename): try: coords = split_coords_2d(~node.LineString.posList) trace = geo.Line([geo.Point(*p) for p in coords]) except ValueError: # If the geometry cannot be created then use the LogicTreeError # to point the user to the incorrect node. Hence, if trace is # compiled successfully then len(trace) is True, otherwise it is # False trace = [] if len(trace): return raise LogicTreeError(node, filename, "'simpleFaultGeometry' node is not valid")
def _complex_to_hazardlib(src, mesh_spacing, bin_width): """Convert a NRML complex fault source to the HazardLib equivalent. See :mod:`openquake.nrmllib.models` and :mod:`openquake.hazardlib.source`. :param src: :class:`openquake.nrmllib.models.ComplexFaultRuptureModel` instance. :param float mesh_spacing: Rupture mesh spacing, in km. :param float bin_width: Truncated Gutenberg-Richter MFD (Magnitude Frequency Distribution) bin width. :returns: The HazardLib representation of the input source. """ edges_wkt = [] edges_wkt.append(src.geometry.top_edge_wkt) edges_wkt.extend(src.geometry.int_edges) edges_wkt.append(src.geometry.bottom_edge_wkt) edges = [] for edge in edges_wkt: shapely_line = wkt.loads(edge) line = geo.Line([geo.Point(*x) for x in shapely_line.coords]) edges.append(line) mf_dist = _mfd_to_hazardlib(src.mfd, bin_width) msr = scalerel.get_available_magnitude_scalerel()[src.mag_scale_rel]() cmplx = source.ComplexFaultSource( source_id=src.id, name=src.name, tectonic_region_type=src.trt, mfd=mf_dist, rupture_mesh_spacing=mesh_spacing, magnitude_scaling_relationship=msr, rupture_aspect_ratio=src.rupt_aspect_ratio, edges=edges, rake=src.rake, ) return cmplx
def _validate_complex_fault_geometry(utype, node, filename): # NB: if the geometry does not conform to the Aki & Richards convention # this will not be verified here, but will raise an error when the surface # is created valid_edges = [] for edge_node in node.nodes: try: coords = split_coords_3d(edge_node.LineString.posList.text) edge = geo.Line([geo.Point(*p) for p in coords]) except ValueError: # See use of validation error in simple geometry case # The node is valid if all of the edges compile correctly edge = [] if len(edge): valid_edges.append(True) else: valid_edges.append(False) if node["spacing"] and all(valid_edges): return raise LogicTreeError(node, filename, "'complexFaultGeometry' node is not valid")
def _complex_to_hazardlib(self, src): """Convert a NRML complex fault source to the HazardLib equivalent. See :mod:`openquake.nrmllib.models` and :mod:`openquake.hazardlib.source`. :param src: :class:`openquake.nrmllib.models.ComplexFaultRuptureModel` instance :returns: The HazardLib representation of the input source. """ edges_wkt = [] edges_wkt.append(src.geometry.top_edge_wkt) edges_wkt.extend(src.geometry.int_edges) edges_wkt.append(src.geometry.bottom_edge_wkt) edges = [] for edge in edges_wkt: shapely_line = wkt.loads(edge) line = geo.Line([geo.Point(*x) for x in shapely_line.coords]) edges.append(line) mf_dist = self._mfd_to_hazardlib(src.mfd) msr = scalerel.get_available_magnitude_scalerel()[src.mag_scale_rel]() cmplx = source.ComplexFaultSource( source_id=src.id, name=src.name, tectonic_region_type=src.trt, mfd=mf_dist, rupture_mesh_spacing=self.rupture_mesh_spacing, magnitude_scaling_relationship=msr, rupture_aspect_ratio=src.rupt_aspect_ratio, edges=edges, rake=src.rake, temporal_occurrence_model=self.default_tom, ) return cmplx
def _expected_char_simple(self): tgr_mfd = mfd.TruncatedGRMFD( a_val=-3.5, b_val=1.0, min_mag=5.0, max_mag=6.5, bin_width=1.0) fault_trace = geo.Line([geo.Point(-121.82290, 37.73010), geo.Point(-122.03880, 37.87710)]) surface = geo.SimpleFaultSurface.from_fault_data( fault_trace=fault_trace, upper_seismogenic_depth=10.0, lower_seismogenic_depth=20.0, dip=45.0, mesh_spacing=self.rupture_mesh_spacing) char = source.CharacteristicFaultSource( source_id="5", name="characteristic source, simple fault", tectonic_region_type="Volcanic", mfd=tgr_mfd, surface=surface, rake=30.0, temporal_occurrence_model=PoissonTOM(50.)) return char
def _simple_to_hazardlib(src, mesh_spacing, bin_width): """Convert a NRML simple fault source to the HazardLib equivalent. See :mod:`openquake.nrmllib.models` and :mod:`openquake.hazardlib.source`. :param src: :class:`openquake.nrmllib.models.SimpleFaultRuptureModel` instance. :param float mesh_spacing: Rupture mesh spacing, in km. :param float bin_width: Truncated Gutenberg-Richter MFD (Magnitude Frequency Distribution) bin width. :returns: The HazardLib representation of the input source. """ shapely_line = wkt.loads(src.geometry.wkt) fault_trace = geo.Line([geo.Point(*x) for x in shapely_line.coords]) mf_dist = _mfd_to_hazardlib(src.mfd, bin_width) msr = scalerel.get_available_magnitude_scalerel()[src.mag_scale_rel]() simple = source.SimpleFaultSource( source_id=src.id, name=src.name, tectonic_region_type=src.trt, mfd=mf_dist, rupture_mesh_spacing=mesh_spacing, magnitude_scaling_relationship=msr, rupture_aspect_ratio=src.rupt_aspect_ratio, upper_seismogenic_depth=src.geometry.upper_seismo_depth, lower_seismogenic_depth=src.geometry.lower_seismo_depth, fault_trace=fault_trace, dip=src.geometry.dip, rake=src.rake) return simple
def _characteristic_to_hazardlib(src, mesh_spacing, bin_width): """ Convert a NRML characteristic fault source to the HazardLib equivalent. The surface of a characteristic fault source can be one of the following: * simple fault * complex fault * one or more planar surfaces See :mod:`openquake.nrmllib.models` and :mod:`openquake.hazardlib.source`. :param src: :class:`openquake.nrmllib.models.CharacteristicSource` instance. :param float mesh_spacing: Rupture mesh spacing, in km. :param float bin_width: Truncated Gutenberg-Richter MFD (Magnitude Frequency Distribution) bin width. :returns: The HazardLib representation of the input source. """ mf_dist = _mfd_to_hazardlib(src.mfd, bin_width) if isinstance(src.surface, nrml_models.SimpleFaultGeometry): shapely_line = wkt.loads(src.surface.wkt) fault_trace = geo.Line([geo.Point(*x) for x in shapely_line.coords]) surface = geo.SimpleFaultSurface.from_fault_data( fault_trace, src.surface.upper_seismo_depth, src.surface.lower_seismo_depth, src.surface.dip, mesh_spacing) elif isinstance(src.surface, nrml_models.ComplexFaultGeometry): edges_wkt = [] edges_wkt.append(src.surface.top_edge_wkt) edges_wkt.extend(src.surface.int_edges) edges_wkt.append(src.surface.bottom_edge_wkt) edges = [] for edge in edges_wkt: shapely_line = wkt.loads(edge) line = geo.Line([geo.Point(*x) for x in shapely_line.coords]) edges.append(line) surface = geo.ComplexFaultSurface.from_fault_data(edges, mesh_spacing) else: # A collection of planar surfaces planar_surfaces = [] for planar_surface in src.surface: kwargs = planar_surface.__dict__ kwargs.update(dict(mesh_spacing=mesh_spacing)) planar_surfaces.append(geo.PlanarSurface(**kwargs)) surface = geo.MultiSurface(planar_surfaces) char = source.CharacteristicFaultSource(source_id=src.id, name=src.name, tectonic_region_type=src.trt, mfd=mf_dist, surface=surface, rake=src.rake) return char
def test(self): line = geo.Line([geo.Point(0, 0), geo.Point(0, 1), geo.Point(1, 2)]) length = line.get_length() expected_length = line.points[0].distance(line.points[1]) \ + line.points[1].distance(line.points[2]) self.assertEqual(length, expected_length)
def test_hangup(self): p1 = geo.Point(0.00899322032502, 0., 0.) p2 = geo.Point(0.01798644058385, 0., 1.) p3 = geo.Point(0.02697966087241, 0., 2.) line = geo.Line([p1, p2, p3]).resample_to_num_points(3) self.assertEqual(line.points, [p1, p2, p3])
def test_line_of_one_point(self): line = geo.Line([geo.Point(0, 0)]) self.assertRaises(AssertionError, line.resample_to_num_points, 10)