def test_get_area1(self): pntsa = npoints_towards(lon=0.32, lat=0.0, depth=0.0, azimuth=45, hdist=10.0, vdist=0.0, npoints=2) pntsb = npoints_towards(lon=pntsa[0][1], lat=pntsa[1][1], depth=pntsa[2][1], azimuth=45 + 90, hdist=10.0, vdist=10.0, npoints=2) pntsc = npoints_towards(lon=0.32, lat=0.0, depth=0.0, azimuth=45 + 90, hdist=10.0, vdist=10.0, npoints=2) tmp = Point(pntsc[0][1], pntsc[1][1], pntsc[2][1]) prf3 = Line([Point(0.32, 0, 0), tmp]) tmp1 = Point(pntsa[0][1], pntsa[1][1], pntsa[2][1]) tmp2 = Point(pntsb[0][1], pntsb[1][1], pntsb[2][1]) prf4 = Line([tmp1, tmp2]) sfcb = KiteSurface.from_profiles([prf3, prf4], 0.2, 0.2) computed = sfcb.get_area() expected = 10.0 * 14.14 msg = 'Multi fault surface: area is wrong' aae(expected, computed, decimal=-1, err_msg=msg)
def test_zero_distance(self): lon, lat, depth, azimuth = 12, 34, 56, 78 lons, lats, depths = geodetic.npoints_towards( lon, lat, depth, azimuth, hdist=0, vdist=0, npoints=5 ) expected_lons = [lon] * 5 expected_lats = [lat] * 5 expected_depths = [depth] * 5 assert_aeq(lons, expected_lons) assert_aeq(lats, expected_lats) assert_aeq(depths, expected_depths)
def test_zero_distance(self): lon, lat, depth, azimuth = 12, 34, 56, 78 lons, lats, depths = geodetic.npoints_towards( lon, lat, depth, azimuth, hdist=0, vdist=0, npoints=5 ) expected_lons = [lon] * 5 expected_lats = [lat] * 5 expected_depths = [depth] * 5 self.assertTrue(numpy.allclose(lons, expected_lons)) self.assertTrue(numpy.allclose(lats, expected_lats)) self.assertTrue(numpy.allclose(depths, expected_depths))
def setUp(self): # First surface - Almost vertical dipping to south prf1 = Line([Point(0, 0, 0), Point(0, -0.00001, 20.)]) prf2 = Line([Point(0.15, 0, 0), Point(0.15, -0.00001, 20.)]) prf3 = Line([Point(0.3, 0, 0), Point(0.3, -0.00001, 20.)]) sfca = KiteSurface.from_profiles([prf1, prf2, prf3], 1., 1.) # Second surface - Strike to NE and dip to SE pntsa = npoints_towards(lon=0.32, lat=0.0, depth=0.0, azimuth=45, hdist=10.0, vdist=0.0, npoints=2) pntsb = npoints_towards(lon=pntsa[0][1], lat=pntsa[1][1], depth=pntsa[2][1], azimuth=45 + 90, hdist=10.0, vdist=10.0, npoints=2) pntsc = npoints_towards(lon=0.32, lat=0.0, depth=0.0, azimuth=45 + 90, hdist=10.0, vdist=10.0, npoints=2) tmp = Point(pntsc[0][1], pntsc[1][1], pntsc[2][1]) prf3 = Line([Point(0.32, 0, 0), tmp]) tmp1 = Point(pntsa[0][1], pntsa[1][1], pntsa[2][1]) tmp2 = Point(pntsb[0][1], pntsb[1][1], pntsb[2][1]) prf4 = Line([tmp1, tmp2]) sfcb = KiteSurface.from_profiles([prf3, prf4], 0.2, 0.2) # Create surface and mesh needed for the test self.msrf = MultiSurface([sfca, sfcb]) self.coo = np.array([[-0.1, 0.0], [0.0, 0.1]]) self.mesh = Mesh(self.coo[:, 0], self.coo[:, 1])
def compute_profiles(self, bffer): """ Compute the profile for each cross-section using the slab mesh. :param bffer: Buffer distance [km] from the plane of the cross-section used to find the points. """ hspacing = 5.0 slab_points = copy.copy(self.points) # Set values in the range [-180, 180] idx = numpy.nonzero(self.points[:, 0] > 180) if len(idx[0]): slab_points[idx[0], 0] = slab_points[idx[0], 0] - 360. # Loop over the cross-sections self.profiles = {} for ics, cs in enumerate(self.cross_sections): pnts = copy.copy(slab_points) # Get min and max longitude and latitude values minlo, maxlo, minla, maxla, qual = cs.get_mm() # Find the nodes of the grid within a certain distance from the # plane of the cross-section if qual == 0: minlo, maxlo, minla, maxla, qual = cs.get_mm(2.0) idxslb, dsts = cs.get_grd_nodes_within_buffer( pnts[:, 0], pnts[:, 1], bffer, minlo, maxlo, minla, maxla) if qual == 1: idxslb, dsts = cs.get_grd_nodes_within_buffer_idl( pnts[:, 0], pnts[:, 1], bffer, minlo, maxlo, minla, maxla) # Check if the array with cross-section data is not empty if idxslb is None: continue # Points num = numpy.ceil(cs.length[0]/hspacing).astype(int) psec = npoints_towards(cs.olo, cs.ola, 0.0, cs.strike[0], cs.length[0], 0., num) p = pnts[idxslb, :] interp = LinearNDInterpolator(p[:, 0:2], p[:, 2]) z = interp(psec[0], psec[1]) iii = numpy.isfinite(z) pro = numpy.concatenate((numpy.expand_dims(psec[0][iii], axis=1), numpy.expand_dims(psec[1][iii], axis=1), numpy.expand_dims(z[iii], axis=1)), axis=1) pro[:, 2] *= -1 self.profiles['{:03d}'.format(ics)] = pro
def test_input_as_int(self): lons, lats, depths = geodetic.npoints_towards( lon=0, lat=0, depth=0, azimuth=0, hdist=0, vdist=5, npoints=7 ) expected_lons = [0, 0, 0, 0, 0, 0, 0] expected_lats = [0, 0, 0, 0, 0, 0, 0] expected_depths = [0, 0.8333333, 1.6666667, 2.5, 3.3333333, 4.1666667, 5] numpy.testing.assert_almost_equal(lons, expected_lons) numpy.testing.assert_almost_equal(lats, expected_lats) numpy.testing.assert_almost_equal(depths, expected_depths) self.assertEqual(lons[0], 0) self.assertEqual(lats[0], 0) self.assertEqual(depths[0], 0)
def test(self): lons, lats, depths = geodetic.npoints_towards( lon=-30.5, lat=23.6, depth=55, azimuth=-100.5, hdist=400, vdist=-40, npoints=5 ) expected_lons = [-30.5, -31.46375358, -32.42503446, -33.3837849, -34.33995063] expected_lats = [23.6, 23.43314083, 23.26038177, 23.08178673, 22.8974212] expected_depths = [55, 45, 35, 25, 15] self.assertTrue(numpy.allclose(lons, expected_lons)) self.assertTrue(numpy.allclose(lats, expected_lats)) self.assertTrue(numpy.allclose(depths, expected_depths)) # the first point should be exactly the same # as the original starting point self.assertEqual(lons[0], -30.5) self.assertEqual(lats[0], 23.6) self.assertEqual(depths[0], 55)
def test_topo(self): lons, lats, depths = geodetic.npoints_towards( lon=-30.5, lat=23.6, depth=2, azimuth=-100.5, hdist=400, vdist=-4, npoints=5 ) expected_lons = [-30.5, -31.46375358, -32.42503446, -33.3837849, -34.33995063] expected_lats = [23.6, 23.43314083, 23.26038177, 23.08178673, 22.8974212] expected_depths = [2, 1, 0, -1, -2] assert_aeq(lons, expected_lons) assert_aeq(lats, expected_lats) assert_aeq(depths, expected_depths) # the first point should be exactly the same # as the original starting point self.assertEqual(lons[0], -30.5) self.assertEqual(lats[0], 23.6) self.assertEqual(depths[0], 2)
def _resample_profile(line, sampling_dist): # TODO split this function into smaller components. """ :parameter line: An instance of :class:`openquake.hazardlib.geo.line.Line` :parameter sampling_dist: A scalar definining the distance [km] used to sample the profile :returns: An instance of :class:`openquake.hazardlib.geo.line.Line` """ lo = [pnt.longitude for pnt in line.points] la = [pnt.latitude for pnt in line.points] de = [pnt.depth for pnt in line.points] # Set projection g = Geod(ellps='WGS84') # Add a tolerance length to the last point of the profile # check that final portion of the profile is not vertical if abs(lo[-2] - lo[-1]) > 1e-5 and abs(la[-2] - la[-1]) > 1e-5: az12, _, odist = g.inv(lo[-2], la[-2], lo[-1], la[-1]) odist /= 1e3 slope = np.arctan((de[-1] - de[-2]) / odist) hdist = TOL * sampling_dist * np.cos(slope) vdist = TOL * sampling_dist * np.sin(slope) endlon, endlat, _ = g.fwd(lo[-1], la[-1], az12, hdist * 1e3) lo[-1] = endlon la[-1] = endlat de[-1] = de[-1] + vdist az12, _, odist = g.inv(lo[-2], la[-2], lo[-1], la[-1]) # Checking odist /= 1e3 slopec = np.arctan((de[-1] - de[-2]) / odist) assert abs(slope - slopec) < 1e-3 else: de[-1] = de[-1] + TOL * sampling_dist # Initialise the cumulated distance cdist = 0. # Get the azimuth of the profile azim = azimuth(lo[0], la[0], lo[-1], la[-1]) # Initialise the list with the resampled nodes idx = 0 resampled_cs = [Point(lo[idx], la[idx], de[idx])] # Set the starting point slo = lo[idx] sla = la[idx] sde = de[idx] # Resampling while 1: # Check loop exit condition if idx > len(lo) - 2: break # Compute the distance between the starting point and the next point # on the profile segment_len = distance(slo, sla, sde, lo[idx + 1], la[idx + 1], de[idx + 1]) # Search for the point if cdist + segment_len > sampling_dist: # This is the lenght of the last segment-fraction needed to # obtain the sampling distance delta = sampling_dist - cdist # Compute the slope of the last segment and its horizontal length. # We need to manage the case of a vertical segment TODO segment_hlen = distance(slo, sla, 0., lo[idx + 1], la[idx + 1], 0.) if segment_hlen > 1e-5: segment_slope = np.arctan((de[idx + 1] - sde) / segment_hlen) else: segment_slope = 90. # Horizontal and vertical lenght of delta delta_v = delta * np.sin(segment_slope) delta_h = delta * np.cos(segment_slope) # Add a new point to the cross section pnts = npoints_towards(slo, sla, sde, azim, delta_h, delta_v, 2) # Update the starting point slo = pnts[0][-1] sla = pnts[1][-1] sde = pnts[2][-1] resampled_cs.append(Point(slo, sla, sde)) # Reset the cumulative distance cdist = 0. else: cdist += segment_len idx += 1 slo = lo[idx] sla = la[idx] sde = de[idx] # Check the distances along the profile coo = [[pnt.longitude, pnt.latitude, pnt.depth] for pnt in resampled_cs] coo = np.array(coo) for i in range(0, coo.shape[0] - 1): dst = distance(coo[i, 0], coo[i, 1], coo[i, 2], coo[i + 1, 0], coo[i + 1, 1], coo[i + 1, 2]) if abs(dst - sampling_dist) > 0.1 * sampling_dist: raise ValueError('Wrong distance between points along the profile') return Line(resampled_cs)
def _resample_edge_with_direction(edge, sampling_dist, reference_idx, direct=+1): """ :param edge: :param sampling_dist: :param reference_idx: :param direct: """ # # checking that the increment is either 1 or -1 assert abs(direct) == 1 # # create three lists: one with longitude, one with latitude and one with # depth lo = [pnt.longitude for pnt in edge.points] la = [pnt.latitude for pnt in edge.points] de = [pnt.depth for pnt in edge.points] # # initialise the variable used to store the cumulated distance cdist = 0. # # initialise the list with the resampled nodes idx = reference_idx resampled_cs = [Point(lo[idx], la[idx], de[idx])] # # set the starting point slo = lo[idx] sla = la[idx] sde = de[idx] # # get the azimuth of the first segment on the edge in the given direction azim = azimuth(lo[idx], la[idx], lo[idx + direct], la[idx + direct]) # # resampling old_dst = 1.e10 while 1: # # this is a sanity check assert idx <= len(lo) - 1 # # check loop exit condition if direct > 0 and idx > len(lo) - 1: break if direct < 0 and idx < 1: break # # compute the distance between the starting point and the next point # on the profile segment_len = distance(slo, sla, sde, lo[idx + direct], la[idx + direct], de[idx + direct]) # # search for the point if cdist + segment_len > sampling_dist: # # check if segment_len > old_dst: print(segment_len, '>', old_dst) raise ValueError('The segment length is increasing') else: old_dst = segment_len # # this is the lenght of the last segment-fraction needed to # obtain the sampling distance delta = sampling_dist - cdist # # compute the slope of the last segment and its horizontal length. # we need to manage the case of a vertical segment TODO segment_hlen = distance(slo, sla, 0., lo[idx + direct], la[idx + direct], 0.) segment_slope = np.arctan((de[idx + direct] - sde) / segment_hlen) # # horizontal and vertical lenght of delta delta_v = delta * np.sin(segment_slope) delta_h = delta * np.cos(segment_slope) # # add a new point to the cross section pnts = npoints_towards(slo, sla, sde, azim, delta_h, delta_v, 2) # # update the starting point slo = pnts[0][-1] sla = pnts[1][-1] sde = pnts[2][-1] # # checking distance between the reference point and latest point # included in the resampled section pnt = resampled_cs[-1] checkd = distance(slo, sla, sde, pnt.longitude, pnt.latitude, pnt.depth) # >>> TOLERANCE if (cdist < 1e-2 and abs(checkd - sampling_dist) > 0.05 * sampling_dist): print(checkd, sampling_dist) msg = 'Segment distance different than sampling dst' raise ValueError(msg) # # updating the resample cross-section resampled_cs.append(Point(slo, sla, sde)) # # tot = distance(lo[idx], la[idx], de[idx], lo[idx + direct], la[idx + direct], de[idx + direct]) downd = distance(slo, sla, sde, lo[idx], la[idx], de[idx]) upd = distance(slo, sla, sde, lo[idx + direct], la[idx + direct], de[idx + direct]) # # >>> TOLERANCE if abs(tot - (downd + upd)) > tot * 0.05: print(' upd, downd, tot', upd, downd, tot) print(abs(tot - (downd + upd))) raise ValueError('Distances are not matching') # # reset the cumulative distance cdist = 0. else: # print('aa', cdist, segment_len, sampling_dist) # print(' ', idx, len(lo)-1, direct) # # old_dst = 1.e10 cdist += segment_len idx += direct slo = lo[idx] sla = la[idx] sde = de[idx] # # get the azimuth of the profile if idx < len(lo) - 1: azim = azimuth(lo[idx], la[idx], lo[idx + direct], la[idx + direct]) else: break # # return resampled_cs
def rsmpl_unsure(ix, iy, sampling_dist): direct = 1 idx = 0 # # create three lists: one with longitude, one with latitude and one with # depth lo = list(ix) la = list(iy) de = list(numpy.zeros_like(ix)) # # initialise the variable used to store the cumulated distance cdist = 0. # # set the starting point slo = lo[idx] sla = la[idx] sde = de[idx] # # get the azimuth of the first segment on the edge in the given direction azim = azimuth(lo[idx], la[idx], lo[idx + direct], la[idx + direct]) # # initialise the list with the resampled nodes resampled_cs = [[lo[idx], la[idx], azim]] # # resampling while 1: # # this is a sanity check assert idx <= len(lo) - 1 # # check loop exit condition if direct > 0 and idx > len(lo) - 1: break # # compute the distance between the starting point and the next point # on the profile segment_len = distance(slo, sla, sde, lo[idx + direct], la[idx + direct], de[idx + direct]) # # search for the point if cdist + segment_len > sampling_dist: # # this is the lenght of the last segment-fraction needed to # obtain the sampling distance delta = sampling_dist - cdist # # add a new point to the cross section pnts = npoints_towards(slo, sla, sde, azim, delta, 0., 2) # # update the starting point slo = pnts[0][-1] sla = pnts[1][-1] sde = pnts[2][-1] resampled_cs.append([slo, sla, azim]) # # reset the cumulative distance cdist = 0. else: cdist += segment_len idx += direct slo = lo[idx] sla = la[idx] sde = de[idx] # # get the azimuth of the profile if idx < len(lo) - 1: azim = azimuth(lo[idx], la[idx], lo[idx + direct], la[idx + direct]) else: break # code.interact(local=locals()) return numpy.array(resampled_cs)
def _resample_profile(line, sampling_dist): """ :parameter line: An instance of :class:`openquake.hazardlib.geo.line.Line` :parameter sampling_dist: A scalar definining the distance used to sample the profile :returns: An instance of :class:`openquake.hazardlib.geo.line.Line` """ lo = [pnt.longitude for pnt in line.points] la = [pnt.latitude for pnt in line.points] de = [pnt.depth for pnt in line.points] # # initialise the cumulated distance cdist = 0. # # get the azimuth of the profile azim = azimuth(lo[0], la[0], lo[-1], la[-1]) # # initialise the list with the resampled nodes idx = 0 resampled_cs = [Point(lo[idx], la[idx], de[idx])] # # set the starting point slo = lo[idx] sla = la[idx] sde = de[idx] # # resampling while 1: # # check loop exit condition if idx > len(lo) - 2: break # # compute the distance between the starting point and the next point # on the profile segment_len = distance(slo, sla, sde, lo[idx + 1], la[idx + 1], de[idx + 1]) # # search for the point if cdist + segment_len > sampling_dist: # # this is the lenght of the last segment-fraction needed to # obtain the sampling distance delta = sampling_dist - cdist # # compute the slope of the last segment and its horizontal length. # We need to manage the case of a vertical segment TODO segment_hlen = distance(slo, sla, 0., lo[idx + 1], la[idx + 1], 0.) segment_slope = np.arctan((de[idx + 1] - sde) / segment_hlen) # # horizontal and vertical lenght of delta delta_v = delta * np.sin(segment_slope) delta_h = delta * np.cos(segment_slope) # # add a new point to the cross section pnts = npoints_towards(slo, sla, sde, azim, delta_h, delta_v, 2) # # update the starting point slo = pnts[0][-1] sla = pnts[1][-1] sde = pnts[2][-1] resampled_cs.append(Point(slo, sla, sde)) # # reset the cumulative distance cdist = 0. else: cdist += segment_len idx += 1 slo = lo[idx] sla = la[idx] sde = de[idx] line = Line(resampled_cs) return line