def test_1d(self): mesh = Mesh(numpy.array([1, 2, 3, 5]), numpy.array([-1, -2, 4, 0])) self.assertEqual(len(mesh), 4) mesh = Mesh(numpy.array([1, 2]), numpy.array([0, 0]), numpy.array([10, 10])) self.assertEqual(len(mesh), 2)
def test_2d(self): mesh = Mesh(numpy.array([[1, 2], [3, 5]]), numpy.array([[-1, -2], [4, 0]])) self.assertEqual(len(mesh), 4) mesh = Mesh(numpy.array([[1, 2], [5, 6]]), numpy.array([[0, 0], [10, 10]]), numpy.array([[10, 10], [30, 30]])) self.assertEqual(len(mesh), 4)
def test_meshes_equal(self): """ Tests if two meshes are equal """ mesh1 = Mesh(lons=numpy.array([1., 2., 3., 4.]), lats=numpy.array([5., 6., 7., 8.]), depths=numpy.array([0.5, 0.5, 0.5, 0.5])) mesh2 = Mesh(mesh1.lons, mesh1.lats, mesh1.depths) self.assertTrue(mesh1 == mesh2)
def test_2d_mesh(self): mesh = Mesh(numpy.array([[0., 1.], [2., 3.]]), numpy.array([[0., 0.], [0., 0.]]), None) target_mesh = Mesh( numpy.array([[3., 4., 5.], [-6., -7., 8.], [9., 10., 11.]]), numpy.array([[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]]), None) self._test(mesh, target_mesh, expected_distance_indices=[3, 3, 3, 0, 0, 3, 3, 3, 3])
def test_distance_to_2d_mesh(self): lons = numpy.array([[0., 1.], [0., 1.]]) lats = numpy.array([[1., 1.], [0., 0.]]) mesh = Mesh(lons, lats) target_lons = numpy.array([[0.25, 0.75], [0.25, 0.75]]) target_lats = numpy.array([[0.75, 0.75], [0.25, 0.25]]) target_mesh = Mesh(target_lons, target_lats) dists = mesh.get_joyner_boore_distance(target_mesh) expected_dists = numpy.zeros((2, 2)) numpy.testing.assert_equal(dists, expected_dists)
def test_2d(self): lons = numpy.array([[1.1, 2.2], [2.2, 3.3]]) lats = numpy.array([[-7, -8], [-9, -10]]) points = list(Mesh(lons, lats)) self.assertEqual(points, [Point(1.1, -7), Point(2.2, -8), Point(2.2, -9), Point(3.3, -10)]) depths = numpy.array([[11, 12], [13, 14]]) points = list(Mesh(lons, lats, depths)) self.assertEqual(points, [Point(1.1, -7, 11), Point(2.2, -8, 12), Point(2.2, -9, 13), Point(3.3, -10, 14)])
def test_wrong_indexing(self): coords = numpy.arange(16) mesh = Mesh(coords, coords, coords) with self.assertRaises(ValueError): mesh[1] coords = coords.reshape((4, 4)) mesh = Mesh(coords, coords, coords) with self.assertRaises(ValueError): mesh[1] with self.assertRaises(IndexError): mesh[1:, 5]
def test_1d(self): mesh = Mesh(numpy.array([1, 2, 3, 5]), numpy.array([-1, -2, 4, 0])) self.assertEqual(list(mesh), [Point(1, -1), Point(2, -2), Point(3, 4), Point(5, 0)]) mesh = Mesh(numpy.array([0.1, 0.2, 0.3]), numpy.array([0.9, 0.8, 0.7]), numpy.array([0.4, 0.5, 0.6])) self.assertEqual(list(mesh), [Point(0.1, 0.9, 0.4), Point(0.2, 0.8, 0.5), Point(0.3, 0.7, 0.6)])
def setUp(self): # creating first mesh x = np.arange(10.0, 11.0, 0.1) y = np.arange(45.0, 45.5, 0.1) z = np.arange(0, 25, 5) xg, yg = np.meshgrid(x, y) _, zg = np.meshgrid(x, z) self.mesh = Mesh(xg, yg, zg) # creating second mesh xga, yga = np.meshgrid(x, y) _, zga = np.meshgrid(x, z) xga[0, 0] = np.nan yga[0, 0] = np.nan self.mesha = Mesh(xga, yga, zg)
def circular_distance_from_point(self, point, distance, **kwargs): ''' Select earthquakes within a distance from a Point :param point: Centre point as instance of nhlib.geo.point.Point class :param float distance: Distance (km) :returns: Instance of :class:`openquake.hmtk.seismicity.catalogue.Catalogue` containing only selected events ''' if kwargs['distance_type'] is 'epicentral': locations = Mesh( self.catalogue.data['longitude'], self.catalogue.data['latitude'], np.zeros(len(self.catalogue.data['longitude']), dtype=float)) point = Point(point.longitude, point.latitude, 0.0) else: locations = self.catalogue.hypocentres_as_mesh() is_close = point.closer_than(locations, distance) return self.select_catalogue(is_close)
def test_rjb_calculation(self): # Test the calculation of the Rjb distance dst = self.srfc.get_joyner_boore_distance(self.mesh) if PLOTTING: _ = plt.figure() ax = plt.gca() plt.scatter(self.mesh.lons, self.mesh.lats, c=dst, edgecolors='none', s=15) plot_mesh_2d(ax, self.srfc) lo, la = self.srfc._get_external_boundary() plt.plot(lo, la, '-r') z = np.reshape(dst, self.mlons.shape) cs = plt.contour(self.mlons, self.mlats, z, 10, colors='k') _ = plt.clabel(cs) tlo, tla = self.srfc.get_tor() ax.plot(tlo, tla, '-g', lw=4) plt.title(f'{self.NAME} - Rjb') plt.show() mesh = Mesh(np.array([10.06]), np.array([44.91])) dst = self.srfc.get_joyner_boore_distance(mesh) self.assertAlmostEqual(0.0, dst[0])
def within_polygon(self, polygon, distance=None, **kwargs): ''' Select earthquakes within polygon :param polygon: Centre point as instance of nhlib.geo.polygon.Polygon class :param float distance: Buffer distance (km) (can take negative values) :returns: Instance of :class:`openquake.hmtk.seismicity.catalogue.Catalogue` containing only selected events ''' if distance: # If a distance is specified then dilate the polyon by distance zone_polygon = polygon.dilate(distance) else: zone_polygon = polygon # Make valid all events inside depth range upper_depth, lower_depth = _check_depth_limits(kwargs) valid_depth = np.logical_and( self.catalogue.data['depth'] >= upper_depth, self.catalogue.data['depth'] < lower_depth) # Events outside polygon returned to invalid assignment catalogue_mesh = Mesh(self.catalogue.data['longitude'], self.catalogue.data['latitude'], self.catalogue.data['depth']) valid_id = np.logical_and(valid_depth, zone_polygon.intersects(catalogue_mesh)) return self.select_catalogue(valid_id)
def fromdict(self, dic, weights=None): """ Populate a GriddedSource with ruptures """ assert not self.data, '%s is not empty' % self i = 0 for mag, rake, hp, probs, (start, stop) in zip(dic['magnitude'], dic['rake'], dic['hypocenter'], dic['probs_occur'], dic['slice']): mesh = Mesh(dic['mesh3d'][start:stop, 0], dic['mesh3d'][start:stop, 1], dic['mesh3d'][start:stop, 2]) surface = GriddedSurface(mesh) pmf = PMF([(prob, i) for i, prob in enumerate(probs)]) hypocenter = Point(hp[0], hp[1], hp[2]) rup = NonParametricProbabilisticRupture( mag, rake, self.tectonic_region_type, hypocenter, surface, pmf, weight=None if weights is None else weights[i]) self.data.append((rup, pmf)) i += 1
def _create_rupture(distance, magnitude, tectonic_region_type=TRT.ACTIVE_SHALLOW_CRUST): # Return a rupture with a fixed geometry located at a given r_jb distance # from a site located at (0.0, 0.0). # parameter float distance: # Joyner and Boore rupture-site distance # parameter float magnitude: # Rupture magnitude # Find the point at a given distance lonp, latp = point_at(0.0, 0.0, 90., distance) mag = magnitude rake = 0.0 tectonic_region_type = tectonic_region_type hypocenter = Point(lonp, latp, 2.5) surface = PlanarSurface.from_corner_points( Point(lonp, -1, 0.), Point(lonp, +1, 0.), Point(lonp, +1, 5.), Point(lonp, -1, 5.)) surface = SimpleFaultSurface.from_fault_data( fault_trace=Line([Point(lonp, -1), Point(lonp, 1)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=5.0, dip=90.0, mesh_spacing=1.0) # check effective rupture-site distance from openquake.hazardlib.geo.mesh import Mesh mesh = Mesh(numpy.array([0.0]), numpy.array([0.0])) assert abs(surface.get_joyner_boore_distance(mesh)-distance) < 1e-2 return BaseRupture(mag, rake, tectonic_region_type, hypocenter, surface, NonParametricSeismicSource)
def __init__(self, sites): self.indices = None self.vs30 = numpy.zeros(len(sites)) self.vs30measured = numpy.zeros(len(sites), dtype=bool) self.z1pt0 = self.vs30.copy() self.z2pt5 = self.vs30.copy() lons = self.vs30.copy() lats = self.vs30.copy() for i in xrange(len(sites)): self.vs30[i] = sites[i].vs30 self.vs30measured[i] = sites[i].vs30measured self.z1pt0[i] = sites[i].z1pt0 self.z2pt5[i] = sites[i].z2pt5 lons[i] = sites[i].location.longitude lats[i] = sites[i].location.latitude self.mesh = Mesh(lons, lats, depths=None) # protect arrays from being accidentally changed. it is useful # because we pass these arrays directly to a GMPE through # a SiteContext object and if a GMPE is implemented poorly it could # modify the site values, thereby corrupting site and all the # subsequent calculation. note that this doesn't protect arrays from # being changed by calling itemset() for arr in (self.vs30, self.vs30measured, self.z1pt0, self.z2pt5, self.mesh.lons, self.mesh.lats): arr.flags.writeable = False
def setUp(self): # Read the profiles and create the surface path = os.path.join(BASE_DATA_PATH, 'profiles07') self.prf, _ = _read_profiles(path) hsmpl = 4 vsmpl = 2 idl = False alg = False self.srfc = KiteSurface.from_profiles(self.prf, vsmpl, hsmpl, idl, alg) # Create the mesh of sites - No need to define their depth step = 0.005 plons = [] plats = [] for lo in np.arange(9.9, 10.4, step): tlo = [] tla = [] for la in np.arange(44.6, 45.3, step): tlo.append(lo) tla.append(la) plons.append(tlo) plats.append(tla) self.mlons = np.array(plons) self.mlats = np.array(plats) self.mesh = Mesh(lons=self.mlons.flatten(), lats=self.mlats.flatten())
def hypocentres_as_mesh(self): ''' Render the hypocentres to a nhlib.geo.mesh.Mesh object ''' return Mesh(self.data['longitude'], self.data['latitude'], self.data['depth'])
def setUp(self): """ """ lons = np.array([10.0, 10.0, 10.5, 11.0, 11.0, 10.5]) lats = np.array([45.0, 45.2, 45.2, 45.2, 45.0, 45.0]) deps = np.array([2.0, 10.0, 10.0, 10.0, 2.0, 2.0]) self.mesh = Mesh(lons, lats, deps)
def setUpClass(self): cfg = helpers.get_data_path('simple_fault_demo_hazard/job.ini') job = helpers.get_job(cfg) output = models.Output.objects.create(oq_job=job, display_name='test', output_type='ses') ses_coll = models.SESCollection.create(output=output) self.mesh_lons = numpy.array([0.1 * x for x in range(16)]).reshape( (4, 4)) self.mesh_lats = numpy.array([0.2 * x for x in range(16)]).reshape( (4, 4)) self.mesh_depths = numpy.array([0.3 * x for x in range(16)]).reshape( (4, 4)) sfs = SimpleFaultSurface( Mesh(self.mesh_lons, self.mesh_lats, self.mesh_depths)) ps = 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)) self.fault_rupture = models.ProbabilisticRupture.objects.create( ses_collection=ses_coll, magnitude=5, rake=0, surface=sfs, is_from_fault_source=True, is_multi_surface=False) self.source_rupture = models.ProbabilisticRupture.objects.create( ses_collection=ses_coll, magnitude=5, rake=0, surface=ps, is_from_fault_source=False, is_multi_surface=False)
def get_middle_point(self): """ If :class:`MultiSurface` is defined by a single surface, simply returns surface's middle point, otherwise find surface element closest to the surface's bounding box centroid and return corresponding middle point. Note that the concept of middle point for a multi surface is ambiguous and alternative definitions may be possible. However, this method is mostly used to define the hypocenter location for ruptures described by a multi surface (see :meth:`openquake.hazardlib.source.characteristic.CharacteristicFaultSource.iter_ruptures`). This is needed because when creating fault based sources, the rupture's hypocenter locations are not explicitly defined, and therefore an automated way to define them is required. """ if len(self.surfaces) == 1: return self.surfaces[0].get_middle_point() west, east, north, south = self.get_bounding_box() longitude, latitude = utils.get_middle_point(west, north, east, south) dists = [] for surf in self.surfaces: dists.append( surf.get_min_distance(Mesh(numpy.array([longitude]), numpy.array([latitude]), None))) dists = numpy.array(dists).flatten() idx = dists == numpy.min(dists) return numpy.array(self.surfaces)[idx][0].get_middle_point()
def setUp(self): # load data and create the mesh path = os.path.join(BASE_DATA_PATH, '..', 'data', 'virtual_fault') x = np.loadtxt(os.path.join(path, 'virtual_fault.x')) y = np.loadtxt(os.path.join(path, 'virtual_fault.y')) z = np.loadtxt(os.path.join(path, 'virtual_fault.z')) self.mesh = Mesh(x, y, z)
def _get_fault_rates(self, source, mmin, mmax=np.inf): """ Adds the rates for a simple or complex fault source :param source: Fault source as instance of :class: openquake.hazardlib.source.simple_fault.SimpleFaultSource or openquake.hazardlib.source.complex_fault.ComplexFaultSource """ for rup in list(source.iter_ruptures()): if (rup.mag < mmin) or (rup.mag > mmax): # Magnitude outside search range continue depths = rup.surface.mesh.depths.flatten() # Generate simple mesh from surface rupt_mesh = Mesh(rup.surface.mesh.lons.flatten(), rup.surface.mesh.lats.flatten(), depths) # Mesh points in polygon in_poly = self.limits.intersects(rupt_mesh) in_depth = np.logical_and(depths >= self.upper_depth, depths <= self.lower_depth) idx = np.logical_and(in_poly, in_depth) if np.any(idx): node_rate = rup.occurrence_rate / float(len(depths)) self.rates += (node_rate * np.sum(idx))
def _get_rupture(rec, geom=None, trt=None): # rec: a dictionary or a record # geom: if any, an array of floats32 convertible into a mesh if not code2cls: code2cls.update(BaseRupture.init()) if geom is None: points = F32([rec['lons'], rec['lats'], rec['depths']]).flat geom = numpy.concatenate([[1], [len(rec['lons']), 1], points]) # build surface arrays = [] num_surfaces = int(geom[0]) start = num_surfaces * 2 + 1 for i in range(1, 2 * num_surfaces, 2): s1, s2 = int(geom[i]), int(geom[i + 1]) size = s1 * s2 * 3 array = geom[start:start + size].reshape(3, s1, s2) arrays.append(array) start += size mesh = arrays[0] rupture_cls, surface_cls = code2cls[rec['code']] surface = object.__new__(surface_cls) if surface_cls is geo.PlanarSurface: surface = geo.PlanarSurface.from_array(mesh[:, 0, :]) elif surface_cls is geo.MultiSurface: if all(array.shape == (3, 1, 4) for array in arrays): # for PlanarSurfaces each array has shape (3, 1, 4) surface.__init__([ geo.PlanarSurface.from_array(array[:, 0, :]) for array in arrays ]) else: # assume KyteSurfaces surface.__init__( [geo.KiteSurface(RectangularMesh(*array)) for array in arrays]) elif surface_cls is geo.GriddedSurface: # fault surface, strike and dip will be computed surface.strike = surface.dip = None surface.mesh = Mesh(*mesh) else: # fault surface, strike and dip will be computed surface.strike = surface.dip = None surface.__init__(RectangularMesh(*mesh)) # build rupture rupture = object.__new__(rupture_cls) rupture.rup_id = rec['serial'] rupture.surface = surface rupture.mag = rec['mag'] rupture.rake = rec['rake'] rupture.hypocenter = geo.Point(*rec['hypo']) rupture.occurrence_rate = rec['occurrence_rate'] try: rupture.probs_occur = rec['probs_occur'] except (KeyError, ValueError): # rec can be a numpy record pass rupture.tectonic_region_type = trt or rec['trt'] rupture.multiplicity = rec['n_occ'] return rupture
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 get_rx_distance(self, mesh): """ For each point determine the corresponding rx distance using the GC2 configuration. See :meth:`superclass method <.base.BaseSurface.get_rx_distance>` for spec of input and result values. """ from openquake.hazardlib.site import SiteCollection if isinstance(mesh, SiteCollection): coo = numpy.array([[p.location.longitude, p.location.latitude] for p in mesh]) mesh = Mesh(coo[:, 0], coo[:, 1]) # If the GC2 calculations have already been computed (by invoking Ry0 # first) and the mesh is identical then class has GC2 attributes # already pre-calculated if not self.tmp_mesh or self.tmp_mesh != mesh: self.gc2t, self.gc2u = self.get_generalised_coordinates(mesh.lons, mesh.lats) # Update mesh self.tmp_mesh = deepcopy(mesh) # Rx coordinate is taken directly from gc2t return self.gc2t
def select_event_within_fault_distance(self, faults, distance, as_db=True): """ Selects records whose hypocentes lie within a given distance of a fault or set of faults :param list faults: Faults as a list of instances of :class:`openquake.hazardlib.geo.SimpleFaultSurface` :param float distance: Distance (nearest distance to fault) (km) for selection """ # Render record event locations to openquake.hazardlib.geo.Mesh lons, lats, depths = [], [], [] for rec in self.database.records: lons.append(rec.event.longitude) lats.append(rec.event.latitude) depths.append(rec.event.depth) db_mesh = Mesh(np.array(lons), np.array(lats), np.array(depths)) # Initially no event is allocated to any faults idx = np.zeros(len(self.database), dtype=int) for fault in faults: rrup = fault.get_min_distance(db_mesh) within_dist = rrup < distance # If within fault distance add 1 - no record of which fault is # kept idx[within_dist] += 1 # Find the events within the selected distance of any fault idx = idx > 0 if np.any(idx): idx = np.where(idx)[0] return self.select_records(idx, as_db) else: None
def _rup_to_point(distance, surface, origin, azimuth, distance_type='rjb', iter_stop=1E-5, maxiter=1000): """ """ pt0 = origin pt1 = origin.point_at(distance, 0., azimuth) r_diff = np.inf iterval = 0 while (np.fabs(r_diff) >= iter_stop) and (iterval <= maxiter): pt1mesh = Mesh(np.array([pt1.longitude]), np.array([pt1.latitude]), None) if distance_type == 'rjb': r_diff = distance - surface.get_joyner_boore_distance(pt1mesh) elif distance_type == 'rrup': r_diff = distance - surface.get_min_distance(pt1mesh) else: raise ValueError('Distance type must be rrup or rjb!') pt0 = Point(pt1.longitude, pt1.latitude) if r_diff > 0.: pt1 = pt0.point_at(r_diff, 0., azimuth) else: pt1 = pt0.point_at(r_diff, 0., (azimuth + 180.) % 360.) return pt1
def test_2d(self): lons = lats = numpy.arange(100).reshape((10, 10)) mesh = Mesh(lons, lats) submesh = mesh[:3, 5:7] self.assertEqual(submesh.lons.shape, (3, 2)) self.assertEqual(submesh.lats.shape, (3, 2)) self.assertTrue((submesh.lons == [[5, 6], [15, 16], [25, 26]]).all()) self.assertTrue((submesh.lats == submesh.lons).all()) depths = lons + 3.1 mesh = Mesh(lons, lats, depths) submesh = mesh[2:4, 2:6] self.assertEqual(submesh.lons.shape, (2, 4)) self.assertEqual(submesh.lats.shape, (2, 4)) self.assertTrue((submesh.lats == submesh.lons).all()) self.assertTrue((submesh.depths == [[25.1, 26.1, 27.1, 28.1], [35.1, 36.1, 37.1, 38.1]]).all())
def __iter__(self): self.dstore.open('r') # if needed attrs = self.dstore.get_attrs('ruptures') code2cls = {} # code -> rupture_cls, surface_cls for key, val in attrs.items(): if key.startswith('code_'): code2cls[int(key[5:])] = [classes[v] for v in val.split()] grp_trt = self.dstore['csm_info'].grp_by("trt") events = self.dstore['events'] ruptures = self.dstore['ruptures'][self.mask] rupgeoms = self.dstore['rupgeoms'][self.mask] # NB: ruptures.sort(order='serial') causes sometimes a SystemError: # <ufunc 'greater'> returned a result with an error set # this is way I am sorting with Python and not with numpy below data = sorted( (serial, ridx) for ridx, serial in enumerate(ruptures['serial'])) for serial, ridx in data: rec = ruptures[ridx] evs = events[rec['eidx1']:rec['eidx2']] if self.grp_id is not None and self.grp_id != rec['grp_id']: continue mesh = numpy.zeros((3, rec['sy'], rec['sz']), F32) for i, arr in enumerate(rupgeoms[ridx]): # i = 0, 1, 2 mesh[i] = arr.reshape(rec['sy'], rec['sz']) rupture_cls, surface_cls = code2cls[rec['code']] rupture = object.__new__(rupture_cls) rupture.serial = serial rupture.surface = object.__new__(surface_cls) rupture.mag = rec['mag'] rupture.rake = rec['rake'] rupture.seed = rec['seed'] rupture.hypocenter = geo.Point(*rec['hypo']) rupture.occurrence_rate = rec['occurrence_rate'] rupture.tectonic_region_type = grp_trt[rec['grp_id']] pmfx = rec['pmfx'] if pmfx != -1: rupture.pmf = self.dstore['pmfs'][pmfx] if surface_cls is geo.PlanarSurface: rupture.surface = geo.PlanarSurface.from_array(mesh[:, 0, :]) elif surface_cls is geo.MultiSurface: # mesh has shape (3, n, 4) rupture.surface.__init__([ geo.PlanarSurface.from_array(mesh[:, i, :]) for i in range(mesh.shape[1]) ]) elif surface_cls is geo.GriddedSurface: # fault surface, strike and dip will be computed rupture.surface.strike = rupture.surface.dip = None rupture.surface.mesh = Mesh(*mesh) else: # fault surface, strike and dip will be computed rupture.surface.strike = rupture.surface.dip = None rupture.surface.__init__(RectangularMesh(*mesh)) ebr = EBRupture(rupture, (), evs) ebr.eidx1 = rec['eidx1'] ebr.eidx2 = rec['eidx2'] # not implemented: rupture_slip_direction yield ebr
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)