def polygon(self): """ The convex hull of the underlying mesh of points """ lons, lats = [], [] for rup, pmf in self.data: if isinstance(rup.surface, MultiSurface): for sfc in rup.surface.surfaces: lons.extend(sfc.mesh.lons.flat) lats.extend(sfc.mesh.lats.flat) else: lons.extend(rup.surface.mesh.lons.flat) lats.extend(rup.surface.mesh.lats.flat) condition = numpy.isfinite(lons).astype(int) lons = numpy.extract(condition, lons) lats = numpy.extract(condition, lats) points = numpy.zeros(len(lons), [('lon', F32), ('lat', F32)]) points['lon'] = numpy.round(lons, 5) points['lat'] = numpy.round(lats, 5) points = numpy.unique(points) mesh = Mesh(points['lon'], points['lat']) return mesh.get_convex_hull()
def test_many_points(self): lons = numpy.array([0.7, 0.6, 0.4, 0.6, 0.3, 0.9, 0.5, 0.4]) lats = numpy.array([0.8, 0.5, 0.2, 0.7, 0.2, 0.4, 0.9, 0.4]) mesh = Mesh(lons, lats, None) polygon = mesh.get_convex_hull() elons = [0.4, 0.3, 0.5, 0.7, 0.9] elats = [0.2, 0.2, 0.9, 0.8, 0.4] numpy.testing.assert_allclose(polygon.lons, elons) numpy.testing.assert_allclose(polygon.lats, elats)
def test_two_points(self): mesh = Mesh(numpy.array([-10., -11.]), numpy.array([-12., -13.]), None) polygon = mesh.get_convex_hull() self.assertIsInstance(polygon, Polygon) elons = [-10.99996704, -11.0000323, -11.00003296, -10.00003295, -9.99996795, -9.99996705] elats = [-13.00003147, -13.00003212, -12.99996853, -11.99996865, -11.99996776, -12.00003135] numpy.testing.assert_allclose(polygon.lons, elons) numpy.testing.assert_allclose(polygon.lats, elats)
def polygon(self): """ The convex hull of the underlying mesh of points """ lons = numpy.concatenate( [rup.surface.mesh.lons.flatten() for rup, pmf in self.data]) lats = numpy.concatenate( [rup.surface.mesh.lats.flatten() for rup, pmf in self.data]) points = numpy.zeros(len(lons), [('lon', F32), ('lat', F32)]) points['lon'] = numpy.round(lons, 5) points['lat'] = numpy.round(lats, 5) points = numpy.unique(points) mesh = Mesh(points['lon'], points['lat']) return mesh.get_convex_hull()
def polygon(self): """ The convex hull of the underlying mesh of points """ lons = [] lats = [] for rup, pmf in self.data: lons.extend(rup.surface.mesh.lons.flat) lats.extend(rup.surface.mesh.lats.flat) points = numpy.zeros(len(lons), [('lon', F32), ('lat', F32)]) numpy.around(lons, 5, points['lon']) numpy.around(lats, 5, points['lat']) points = numpy.unique(points) mesh = Mesh(points['lon'], points['lat']) return mesh.get_convex_hull()
class MultiPointSource(ParametricSeismicSource): """ MultiPointSource class, used to describe point sources with different MFDs and the same rupture_mesh_spacing, magnitude_scaling_relationship, rupture_aspect_ratio, temporal_occurrence_model, upper_seismogenic_depth, lower_seismogenic_depth, nodal_plane_distribution, hypocenter_distribution """ code = b'M' MODIFICATIONS = set(()) def __init__(self, source_id, name, tectonic_region_type, mfd, magnitude_scaling_relationship, rupture_aspect_ratio, # point-specific parameters (excluding location) upper_seismogenic_depth, lower_seismogenic_depth, nodal_plane_distribution, hypocenter_distribution, mesh, temporal_occurrence_model=None): assert len(mfd) == len(mesh), (len(mfd), len(mesh)) rupture_mesh_spacing = None super().__init__( source_id, name, tectonic_region_type, mfd, rupture_mesh_spacing, magnitude_scaling_relationship, rupture_aspect_ratio, temporal_occurrence_model) self.upper_seismogenic_depth = upper_seismogenic_depth self.lower_seismogenic_depth = lower_seismogenic_depth self.nodal_plane_distribution = nodal_plane_distribution self.hypocenter_distribution = hypocenter_distribution self.mesh = mesh def __iter__(self): for i, (mfd, point) in enumerate(zip(self.mfd, self.mesh)): name = '%s:%s' % (self.source_id, i) ps = PointSource( name, name, self.tectonic_region_type, mfd, self.rupture_mesh_spacing, self.magnitude_scaling_relationship, get(self.rupture_aspect_ratio, i), self.temporal_occurrence_model, get(self.upper_seismogenic_depth, i), get(self.lower_seismogenic_depth, i), point, self.nodal_plane_distribution, self.hypocenter_distribution) ps.num_ruptures = ps.count_ruptures() ps.scaling_rate = getattr(self, 'scaling_rate', 1) yield ps def __len__(self): return len(self.mfd) def iter_ruptures(self, **kwargs): """ Yield the ruptures of the underlying point sources """ for ps in self: for rupture in ps.iter_ruptures(**kwargs): yield rupture def count_ruptures(self): """ See :meth:`openquake.hazardlib.source.base.BaseSeismicSource.count_ruptures` for description of parameters and return value. """ return (len(self.get_annual_occurrence_rates()) * len(self.nodal_plane_distribution.data) * len(self.hypocenter_distribution.data)) def get_bounding_box(self, maxdist): """ Bounding box containing all the point sources, enlarged by the maximum distance. """ return utils.get_bounding_box([ps.location for ps in self], maxdist) @property def polygon(self): """ The polygon containing all points """ return self.mesh.get_convex_hull() def __toh5__(self): npd = [(prob, np.strike, np.dip, np.rake) for prob, np in self.nodal_plane_distribution.data] hdd = self.hypocenter_distribution.data points = [(p.x, p.y) for p in self.mesh] mfd = self.mfd.kwargs.copy() for k, vals in mfd.items(): if k in ('occurRates', 'magnitudes'): mfd[k] = [numpy.array(lst, F32) for lst in vals] else: mfd[k] = numpy.array(vals, F32) dic = {'nodal_plane_distribution': numpy.array(npd, npd_dt), 'hypocenter_distribution': numpy.array(hdd, hdd_dt), 'mesh': numpy.array(points, mesh_dt), 'rupture_aspect_ratio': self.rupture_aspect_ratio, 'upper_seismogenic_depth': self.upper_seismogenic_depth, 'lower_seismogenic_depth': self.lower_seismogenic_depth, self.mfd.kind: mfd} attrs = {'source_id': self.source_id, 'name': self.name, 'magnitude_scaling_relationship': self.magnitude_scaling_relationship.__class__.__name__, 'tectonic_region_type': self.tectonic_region_type} return dic, attrs def __fromh5__(self, dic, attrs): self.source_id = attrs['source_id'] self.name = attrs['name'] self.tectonic_region_type = attrs['tectonic_region_type'] self.magnitude_scaling_relationship = SCALEREL[ attrs['magnitude_scaling_relationship']] npd = dic.pop('nodal_plane_distribution').value hdd = dic.pop('hypocenter_distribution').value mesh = dic.pop('mesh').value self.rupture_aspect_ratio = dic.pop('rupture_aspect_ratio').value self.lower_seismogenic_depth = dic.pop('lower_seismogenic_depth').value self.upper_seismogenic_depth = dic.pop('upper_seismogenic_depth').value [(mfd_kind, mfd)] = dic.items() self.nodal_plane_distribution = PMF([ (prob, NodalPlane(strike, dip, rake)) for prob, strike, dip, rake in npd]) self.hypocenter_distribution = PMF(hdd) self.mesh = Mesh(mesh['lon'], mesh['lat']) kw = {k: dset.value for k, dset in mfd.items()} kw['size'] = len(mesh) kw['kind'] = mfd_kind self.mfd = MultiMFD(**kw) def wkt(self): """ :returns: the geometry as a wkt string """ return self.mesh.get_convex_hull().wkt