def example_calc(apply): sitecol = SiteCollection([ Site(Point(30.0, 30.0), 760., 1.0, 1.0), Site(Point(30.25, 30.25), 760., 1.0, 1.0), Site(Point(30.4, 30.4), 760., 1.0, 1.0) ]) mfd_1 = TruncatedGRMFD(4.5, 8.0, 0.1, 4.0, 1.0) mfd_2 = TruncatedGRMFD(4.5, 7.5, 0.1, 3.5, 1.1) sources = [ PointSource('001', 'Point1', 'Active Shallow Crust', mfd_1, 1.0, WC1994(), 1.0, PoissonTOM(50.0), 0.0, 30.0, Point(30.0, 30.5), PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]), PMF([(1.0, 10.0)])), PointSource('002', 'Point2', 'Active Shallow Crust', mfd_2, 1.0, WC1994(), 1.0, PoissonTOM(50.0), 0.0, 30.0, Point(30.0, 30.5), PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]), PMF([(1.0, 10.0)])) ] imtls = { 'PGA': [0.01, 0.1, 0.2, 0.5, 0.8], 'SA(0.5)': [0.01, 0.1, 0.2, 0.5, 0.8] } gsims = {'Active Shallow Crust': AkkarBommer2010()} return calc_hazard_curves(sources, sitecol, imtls, gsims, apply=apply, filter_distance='rrup')
def setUp(self): """ """ mfd_1 = TruncatedGRMFD(4.5, 8.0, 0.1, 4.0, 1.0) mfd_2 = TruncatedGRMFD(4.5, 7.5, 0.1, 3.5, 1.1) self.source_model = [ PointSource('001', 'Point1', 'Active Shallow Crust', mfd_1, 1.0, WC1994(), 1.0, PoissonTOM(50.0), 0.0, 30.0, Point(30.0, 30.5), PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]), PMF([(1.0, 10.0)])), PointSource('002', 'Point2', 'Active Shallow Crust', mfd_2, 1.0, WC1994(), 1.0, PoissonTOM(50.0), 0.0, 30.0, Point(30.0, 30.5), PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]), PMF([(1.0, 10.0)])) ] self.sites = SiteCollection([ Site(Point(30.0, 30.0), 760., True, 1.0, 1.0, 1), Site(Point(30.25, 30.25), 760., True, 1.0, 1.0, 2), Site(Point(30.4, 30.4), 760., True, 1.0, 1.0, 2) ]) self.gsims = {'Active Shallow Crust': 'AkkarBommer2010'} self.imts = ['PGA', 'SA(0.5)'] self.imls = [[0.01, 0.1, 0.2, 0.5, 0.8]]
def reference_psha_calculation_openquake(): """ Sets up the reference PSHA calculation calling OpenQuake directly. All subsequent implementations should match this example """ # Site model - 3 Sites site_model = SiteCollection([ Site(Point(30.0, 30.0), 760., True, 1.0, 1.0, 1), Site(Point(30.25, 30.25), 760., True, 1.0, 1.0, 2), Site(Point(30.4, 30.4), 760., True, 1.0, 1.0, 2) ]) # Source Model Two Point Sources mfd_1 = TruncatedGRMFD(4.5, 8.0, 0.1, 4.0, 1.0) mfd_2 = TruncatedGRMFD(4.5, 7.5, 0.1, 3.5, 1.1) source_model = [ PointSource('001', 'Point1', 'Active Shallow Crust', mfd_1, 1.0, WC1994(), 1.0, PoissonTOM(50.0), 0.0, 30.0, Point(30.0, 30.5), PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]), PMF([(1.0, 10.0)])), PointSource('002', 'Point2', 'Active Shallow Crust', mfd_2, 1.0, WC1994(), 1.0, PoissonTOM(50.0), 0.0, 30.0, Point(30.0, 30.5), PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]), PMF([(1.0, 10.0)])) ] imts = { 'PGA': [0.01, 0.1, 0.2, 0.5, 0.8], 'SA(0.5)': [0.01, 0.1, 0.2, 0.5, 0.8] } # Akkar & Bommer (2010) GMPE gsims = {'Active Shallow Crust': gsim.akkar_bommer_2010.AkkarBommer2010()} truncation_level = None return calc_hazard_curves(source_model, site_model, imts, gsims, truncation_level)
def __init__( self, source_id, name, tectonic_region_type, mfd, rupture_mesh_spacing, magnitude_scaling_relationship, rupture_aspect_ratio, temporal_occurrence_model, # complex fault specific parameters edges, rake, ): super(ComplexFaultSource, self).__init__( source_id, name, tectonic_region_type, mfd, rupture_mesh_spacing, magnitude_scaling_relationship, rupture_aspect_ratio, temporal_occurrence_model, ) NodalPlane.check_rake(rake) ComplexFaultSurface.check_fault_data(edges, rupture_mesh_spacing) self.edges = edges self.rake = rake
def __init__(self, source_id, name, tectonic_region_type, mfd, rupture_mesh_spacing, magnitude_scaling_relationship, rupture_aspect_ratio, # simple fault specific parameters upper_seismogenic_depth, lower_seismogenic_depth, fault_trace, dip, rake): super(SimpleFaultSource, self).__init__( source_id, name, tectonic_region_type, mfd, rupture_mesh_spacing, magnitude_scaling_relationship, rupture_aspect_ratio ) NodalPlane.check_rake(rake) SimpleFaultSurface.check_fault_data( fault_trace, upper_seismogenic_depth, lower_seismogenic_depth, dip, rupture_mesh_spacing ) self.fault_trace = fault_trace self.upper_seismogenic_depth = upper_seismogenic_depth self.lower_seismogenic_depth = lower_seismogenic_depth self.dip = dip self.rake = rake min_mag = self.mfd.get_min_mag() cols_rows = self._get_rupture_dimensions(float('inf'), float('inf'), min_mag) if 1 in cols_rows: raise ValueError('mesh spacing %s is too low to represent ' 'ruptures of magnitude %s' % (rupture_mesh_spacing, min_mag))
def setUp(self): """ """ #~ self.npd_as_list = [models.NodalPlane(0.5, 0., 90., 0.), #~ models.NodalPlane(0.5, 90., 90., 180.)] self.npd_as_pmf = PMF([(0.5, NodalPlane(0., 90., 0.)), (0.5, NodalPlane(90., 90., 180.))]) self.npd_as_pmf_bad = PMF([(0.5, None), (0.5, NodalPlane(90., 90., 180.))])
def __init__(self, mag, rake, tectonic_region_type, hypocenter, surface, rupture_slip_direction=None): if not mag > 0: raise ValueError('magnitude must be positive') NodalPlane.check_rake(rake) self.tectonic_region_type = tectonic_region_type self.rake = rake self.mag = mag self.hypocenter = hypocenter self.surface = surface self.rupture_slip_direction = rupture_slip_direction
def __init__(self, strike, dip, top_left, top_right, bottom_right, bottom_left, check=True): if check: if not (top_left.depth == top_right.depth and bottom_left.depth == bottom_right.depth): raise ValueError("top and bottom edges must be parallel " "to the earth surface") NodalPlane.check_dip(dip) NodalPlane.check_strike(strike) self.dip = dip self.strike = strike self.corner_lons = numpy.array([ top_left.longitude, top_right.longitude, bottom_left.longitude, bottom_right.longitude ]) self.corner_lats = numpy.array([ top_left.latitude, top_right.latitude, bottom_left.latitude, bottom_right.latitude ]) self.corner_depths = numpy.array([ top_left.depth, top_right.depth, bottom_left.depth, bottom_right.depth ]) # now set the attributes normal, d, uv1, uv2, zero_zero self._init_plane() # now we can check surface for validity dists, xx, yy = self._project(self.mesh.xyz) # "length" of the rupture is measured along the top edge length1, length2 = xx[1] - xx[0], xx[3] - xx[2] # "width" of the rupture is measured along downdip direction width1, width2 = yy[2] - yy[0], yy[3] - yy[1] self.width = (width1 + width2) / 2.0 self.length = (length1 + length2) / 2.0 if check: # calculate the imperfect rectangle tolerance # relative to surface's area tolerance = (self.width * self.length * self.IMPERFECT_RECTANGLE_TOLERANCE) if numpy.max(numpy.abs(dists)) > tolerance: logging.warning("corner points do not lie on the same plane") if length2 < 0: raise ValueError("corners are in the wrong order") if abs(length1 - length2) > tolerance: raise ValueError("top and bottom edges have different lengths")
def __init__(self, mag, rake, tectonic_region_type, hypocenter, surface, source_typology): if not mag > 0: raise ValueError("magnitude must be positive") if not hypocenter.depth > 0: raise ValueError("rupture hypocenter must have positive depth") NodalPlane.check_rake(rake) self.tectonic_region_type = tectonic_region_type self.rake = rake self.mag = mag self.hypocenter = hypocenter self.surface = surface self.source_typology = source_typology
def __init__(self, mag, rake, tectonic_region_type, hypocenter, surface, rupture_slip_direction=None, weight=None): if not mag > 0: raise ValueError('magnitude must be positive') NodalPlane.check_rake(rake) self.tectonic_region_type = tectonic_region_type self.rake = rake self.mag = mag self.hypocenter = hypocenter self.surface = surface self.rupture_slip_direction = rupture_slip_direction self.weight = weight
def __init__(self, mesh_spacing, strike, dip, top_left, top_right, bottom_right, bottom_left): super(PlanarSurface, self).__init__() if not (top_left.depth == top_right.depth and bottom_left.depth == bottom_right.depth): raise ValueError("top and bottom edges must be parallel " "to the earth surface") if not mesh_spacing > 0: raise ValueError("mesh spacing must be positive") self.mesh_spacing = mesh_spacing NodalPlane.check_dip(dip) NodalPlane.check_strike(strike) self.dip = dip self.strike = strike self.corner_lons = numpy.array([ top_left.longitude, top_right.longitude, bottom_left.longitude, bottom_right.longitude ]) self.corner_lats = numpy.array([ top_left.latitude, top_right.latitude, bottom_left.latitude, bottom_right.latitude ]) self.corner_depths = numpy.array([ top_left.depth, top_right.depth, bottom_left.depth, bottom_right.depth ]) self._init_plane() # now we can check surface for validity dists, xx, yy = self._project(self.corner_lons, self.corner_lats, self.corner_depths) # "length" of the rupture is measured along the top edge length1, length2 = xx[1] - xx[0], xx[3] - xx[2] # "width" of the rupture is measured along downdip direction width1, width2 = yy[2] - yy[0], yy[3] - yy[1] self.width = (width1 + width2) / 2.0 self.length = (length1 + length2) / 2.0 # calculate the imperfect rectangle tolerance # relative to surface's area tolerance = (self.width * self.length * self.IMPERFECT_RECTANGLE_TOLERANCE) if numpy.max(numpy.abs(dists)) > tolerance: raise ValueError("corner points do not lie on the same plane") if length2 < 0: raise ValueError("corners are in the wrong order") if abs(length1 - length2) > tolerance: raise ValueError("top and bottom edges have different lengths") if abs(xx[0] - xx[2]) > tolerance: raise ValueError("surface's angles are not right")
def __init__(self, mag, rake, tectonic_region_type, hypocenter, surface, source_typology): if not mag > 0: raise ValueError('magnitude must be positive') if not hypocenter.depth > 0: raise ValueError('rupture hypocenter must have positive depth') NodalPlane.check_rake(rake) self.tectonic_region_type = tectonic_region_type self.rake = rake self.mag = mag self.hypocenter = hypocenter self.surface = surface self.source_typology = source_typology
def __init__(self, source_id, name, tectonic_region_type, mfd, rupture_mesh_spacing, magnitude_scaling_relationship, rupture_aspect_ratio, temporal_occurrence_model, # complex fault specific parameters edges, rake): super().__init__( source_id, name, tectonic_region_type, mfd, rupture_mesh_spacing, magnitude_scaling_relationship, rupture_aspect_ratio, temporal_occurrence_model) NodalPlane.check_rake(rake) ComplexFaultSurface.check_fault_data(edges, rupture_mesh_spacing) self.edges = edges self.rake = rake
def __init__( self, source_id, name, tectonic_region_type, mfd, rupture_mesh_spacing, magnitude_scaling_relationship, rupture_aspect_ratio, temporal_occurrence_model, # simple fault specific parameters upper_seismogenic_depth, lower_seismogenic_depth, fault_trace, dip, rake, hypo_list=(), slip_list=()): super(SimpleFaultSource, self).__init__(source_id, name, tectonic_region_type, mfd, rupture_mesh_spacing, magnitude_scaling_relationship, rupture_aspect_ratio, temporal_occurrence_model) NodalPlane.check_rake(rake) SimpleFaultSurface.check_fault_data(fault_trace, upper_seismogenic_depth, lower_seismogenic_depth, dip, rupture_mesh_spacing) self.fault_trace = fault_trace self.upper_seismogenic_depth = upper_seismogenic_depth self.lower_seismogenic_depth = lower_seismogenic_depth self.dip = dip self.rake = rake min_mag, max_mag = self.mfd.get_min_max_mag() cols_rows = self._get_rupture_dimensions(float('inf'), float('inf'), min_mag) self.slip_list = slip_list self.hypo_list = hypo_list if (len(self.hypo_list) and not len(self.slip_list) or not len(self.hypo_list) and len(self.slip_list)): raise ValueError('hypo_list and slip_list have to be both given ' 'or neither given') if 1 in cols_rows: raise ValueError('mesh spacing %s is too high to represent ' 'ruptures of magnitude %s' % (rupture_mesh_spacing, min_mag))
def __init__(self, mag, rake, tectonic_region_type, hypocenter, surface, source_typology, rupture_slip_direction=None, surface_nodes=()): if not mag > 0: raise ValueError('magnitude must be positive') if not hypocenter.depth > 0: raise ValueError('rupture hypocenter must have positive depth') NodalPlane.check_rake(rake) self.tectonic_region_type = tectonic_region_type self.rake = rake self.mag = mag self.hypocenter = hypocenter self.surface = surface self.source_typology = source_typology self.surface_nodes = surface_nodes self.rupture_slip_direction = rupture_slip_direction
def setUp(self): mfd = TruncatedGRMFD(min_mag=4.0, max_mag=6.0, bin_width=0.1, a_val=2.0, b_val=1.0) msr = WC1994() tom = PoissonTOM(1.0) pol = Polygon([Point(longitude=0.0, latitude=0.0), Point(longitude=1.0, latitude=0.0), Point(longitude=1.0, latitude=1.0), Point(longitude=0.0, latitude=1.0)]) npd = PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]) hpd = PMF([(0.7, 10.), (0.3, 20.0)]) self.src1 = AreaSource(source_id='1', name='1', tectonic_region_type='Test', mfd=mfd, rupture_mesh_spacing=1, magnitude_scaling_relationship=msr, rupture_aspect_ratio=1., temporal_occurrence_model=tom, upper_seismogenic_depth=0, lower_seismogenic_depth=100., nodal_plane_distribution=npd, hypocenter_distribution=hpd, polygon=pol, area_discretization=10.)
def npd_to_pmf(nodal_plane_dist, use_default=False): """ Returns the nodal plane distribution as an instance of the PMF class """ if isinstance(nodal_plane_dist, PMF): # Aready in PMF format - return return nodal_plane_dist elif isinstance(nodal_plane_dist, list): npd_list = [] for npd in nodal_plane_dist: assert isinstance(npd, models.NodalPlane) npd_list.append( (npd.probability, NodalPlane(npd.strike, npd.dip, npd.rake))) return PMF(npd_list) else: if use_default: return PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]) else: raise ValueError('Nodal Plane distribution not defined')
def test_render_nodal_planes_as_pmf_bad_2(self): ''' Tests the workflow when nodal planes input as a PMF without probabilities summing to 1.0 ''' self.npd_as_pmf.data[1] = (0.4, NodalPlane(90., 90., 180.)) with self.assertRaises(ValueError) as ae: output = conv.render_npd(self.npd_as_pmf) self.assertEqual(ae.exception.message, 'Nodal Plane probabilities do not sum to 1.0')
def _test_broken_input(self, broken_parameter, **kwargs): with self.assertRaises(ValueError) as ae: NodalPlane(**kwargs) self.assertTrue(str(ae.exception).startswith(broken_parameter), str(ae.exception)) checker = getattr(NodalPlane, 'check_%s' % broken_parameter) with self.assertRaises(ValueError) as ae: checker(kwargs[broken_parameter]) self.assertTrue(str(ae.exception).startswith(broken_parameter), str(ae.exception))
def npd_to_pmf(nodal_plane_dist, use_default=False): """ Returns the nodal plane distribution as an instance of the PMF class """ if isinstance(nodal_plane_dist, PMF): # Aready in PMF format - return return nodal_plane_dist else: if use_default: return PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]) else: raise ValueError('Nodal Plane distribution not defined')
def __init__(self, source_id, name, tectonic_region_type, mfd, rupture_mesh_spacing, magnitude_scaling_relationship, rupture_aspect_ratio, temporal_occurrence_model, # simple fault specific parameters upper_seismogenic_depth, lower_seismogenic_depth, fault_trace, dip, rake, hypo_list=(), slip_list=()): super(SimpleFaultSource, self).__init__( source_id, name, tectonic_region_type, mfd, rupture_mesh_spacing, magnitude_scaling_relationship, rupture_aspect_ratio, temporal_occurrence_model ) NodalPlane.check_rake(rake) SimpleFaultSurface.check_fault_data( fault_trace, upper_seismogenic_depth, lower_seismogenic_depth, dip, rupture_mesh_spacing ) self.fault_trace = fault_trace self.upper_seismogenic_depth = upper_seismogenic_depth self.lower_seismogenic_depth = lower_seismogenic_depth self.dip = dip self.rake = rake min_mag, max_mag = self.mfd.get_min_max_mag() cols_rows = self._get_rupture_dimensions(float('inf'), float('inf'), min_mag) self.slip_list = slip_list self.hypo_list = hypo_list if (len(self.hypo_list) and not len(self.slip_list) or not len(self.hypo_list) and len(self.slip_list)): raise ValueError('hypo_list and slip_list have to be both given ' 'or neither given') if 1 in cols_rows: raise ValueError('mesh spacing %s is too high to represent ' 'ruptures of magnitude %s' % (rupture_mesh_spacing, min_mag))
def __init__( self, source_id, name, tectonic_region_type, mfd, rupture_mesh_spacing, magnitude_scaling_relationship, rupture_aspect_ratio, # simple fault specific parameters upper_seismogenic_depth, lower_seismogenic_depth, fault_trace, dip, rake): super(SimpleFaultSource, self).__init__(source_id, name, tectonic_region_type, mfd, rupture_mesh_spacing, magnitude_scaling_relationship, rupture_aspect_ratio) NodalPlane.check_rake(rake) SimpleFaultSurface.check_fault_data(fault_trace, upper_seismogenic_depth, lower_seismogenic_depth, dip, rupture_mesh_spacing) self.fault_trace = fault_trace self.upper_seismogenic_depth = upper_seismogenic_depth self.lower_seismogenic_depth = lower_seismogenic_depth self.dip = dip self.rake = rake min_mag = self.mfd.get_min_mag() cols_rows = self._get_rupture_dimensions(float('inf'), float('inf'), min_mag) if 1 in cols_rows: raise ValueError('mesh spacing %s is too low to represent ' 'ruptures of magnitude %s' % (rupture_mesh_spacing, min_mag))
def make_rupture(trt, mag, msr=PointMSR(), aspect_ratio=1.0, seismo=(10, 30), nodal_plane_tup=(0, 90, 0), hc_tup=(0, 0, 20), occurrence_rate=1, tom=None): hc = Point(*hc_tup) np = NodalPlane(*nodal_plane_tup) ps = object.__new__(PointSource) ps.magnitude_scaling_relationship = msr ps.upper_seismogenic_depth = seismo[0] ps.lower_seismogenic_depth = seismo[1] ps.rupture_aspect_ratio = aspect_ratio surface, nhc = ps._get_rupture_surface(mag, np, hc) rup = ParametricProbabilisticRupture( mag, np.rake, trt, hc, surface, occurrence_rate, tom) return rup
def node_to_nodal_planes(node): """ Parses the nodal plane distribution to a PMF """ if not len(node): return None npd_pmf = [] for plane in node.nodes: if not all(plane.attrib[key] for key in plane.attrib): # One plane fails - return None return None npd = NodalPlane(float(plane.attrib["strike"]), float(plane.attrib["dip"]), float(plane.attrib["rake"])) npd_pmf.append((float(plane.attrib["probability"]), npd)) return PMF(npd_pmf)
def test(self): sitecol = SiteCollection([Site(Point(30.0, 30.0), 760., 1.0, 1.0)]) mfd = TruncatedGRMFD(4.5, 8.0, 0.1, 4.0, 1.0) sources = [PointSource('001', 'Point1', 'Active Shallow Crust', mfd, 1.0, WC1994(), 1.0, PoissonTOM(50.0), 0.0, 30.0, Point(30.0, 30.5), PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]), PMF([(1.0, 10.0)]))] imtls = {'PGA': [0.01, 0.1, 0.2, 0.5, 0.8]} hc1 = calc_hazard_curves(sources, sitecol, imtls, { 'Active Shallow Crust': AkkarBommer2010()})['PGA'] hc2 = calc_hazard_curves(sources, sitecol, imtls, { 'Active Shallow Crust': SadighEtAl1997()})['PGA'] hc = .6 * hc1 + .4 * hc2 ag = AvgGMPE(b1=dict(AkkarBommer2010={'weight': .6}), b2=dict(SadighEtAl1997={'weight': .4})) hcm = calc_hazard_curves(sources, sitecol, imtls, { 'Active Shallow Crust': ag})['PGA'] # the AvgGMPE is not producing real means!! numpy.testing.assert_almost_equal(hc, hcm, decimal=3)
def setUp(self): """ """ # # coordinates of point sources lons = [10.00, 10.10, 10.20, 10.00, 10.10, 10.20, 10.00, 10.10, 10.20] lats = [45.10, 45.10, 45.10, 45.05, 45.05, 45.05, 45.00, 45.00, 45.00] deps = [10.00, 10.00, 10.00, 10.00, 10.00, 10.00, 10.00, 10.00, 10.00] self.lons = lons self.lats = lats # # set main parameters mfd = TruncatedGRMFD(min_mag=4.0, max_mag=6.0, bin_width=0.1, a_val=2.0, b_val=1.0) msr = WC1994() tom = PoissonTOM(1.0) npd = PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]) hdd = PMF([(0.7, 4.), (0.3, 8.0)]) # # create the list of sources srcs = [] for idx, (lon, lat, dep) in enumerate(zip(lons, lats, deps)): src = PointSource(source_id='1', name='Test', tectonic_region_type=TRT.ACTIVE_SHALLOW_CRUST, mfd=mfd, rupture_mesh_spacing=5.0, magnitude_scaling_relationship=msr, rupture_aspect_ratio=1.0, temporal_occurrence_model=tom, upper_seismogenic_depth=0, lower_seismogenic_depth=10., location=Point(lon, lat, dep), nodal_plane_distribution=npd, hypocenter_distribution=hdd) srcs.append(src) self.points = srcs
def test_point_surface(self): sid = 0 name = 'test' trt = TRT.ACTIVE_SHALLOW_CRUST mfd = ArbitraryMFD([7.0], [1.]) rms = 2.5 msr = WC1994() rar = 1.0 tom = PoissonTOM(1.) usd = 0.0 lsd = 20.0 loc = Point(0.0, 0.0) npd = PMF([(1.0, NodalPlane(90., 90., 90.))]) hyd = PMF([(1.0, 10.)]) src = PointSource(sid, name, trt, mfd, rms, msr, rar, tom, usd, lsd, loc, npd, hyd) rups = [r for r in src.iter_ruptures()] # Compute distances param = 'closest_point' sites = SiteCollection( [Site(Point(0.0, 0.0, 0.0)), Site(Point(-0.2, 0.0, 0.0))]) dsts = get_distances(rups[0], sites, param) # Check first point msg = 'The longitude of the first point is wrong' self.assertTrue(abs(dsts[0, 0] - 0.0) < 1e-2, msg) msg = 'The latitude of the first point is wrong' self.assertTrue(abs(dsts[0, 1] - 0.0) < 1e-2, msg) # Check second point msg = 'The longitude of the second point is wrong' self.assertTrue(abs(dsts[1, 0] + 0.1666) < 1e-2, msg) msg = 'The latitude of the second point is wrong' self.assertTrue(abs(dsts[1, 1] - 0.0) < 1e-2, msg)
dom['DEP_LOWER'] = 15 hypo_depth_dist = PMF([(0.5, dom['DEP_BEST']), (0.25, dom['DEP_LOWER']), (0.25, dom['DEP_UPPER'])]) # Define nodal planes as thrusts except for special cases str1 = dom['SHMAX'] + 90. str2 = dom['SHMAX'] + 270. str3 = dom['SHMAX'] + dom['SHMAX_SIG'] + 90. str4 = dom['SHMAX'] + dom['SHMAX_SIG'] + 270. str5 = dom['SHMAX'] - dom['SHMAX_SIG'] + 90. str6 = dom['SHMAX'] - dom['SHMAX_SIG'] + 270. strikes = [str1, str2, str3, str4, str5, str6] for i, strike in enumerate(strikes): if strike >= 360: strikes[i] = strike - 360 nodal_plane_dist = PMF([(0.34, NodalPlane(strikes[0], 30, 90)), (0.34, NodalPlane(strikes[1], 30, 90)), (0.08, NodalPlane(strikes[2], 30, 90)), (0.08, NodalPlane(strikes[3], 30, 90)), (0.08, NodalPlane(strikes[4], 30, 90)), (0.08, NodalPlane(strikes[5], 30, 90))]) if dom['CODE'] == 'WARM' or dom['CODE'] == 'WAPM': print 'Define special case for WARM' nodal_plane_dist = PMF([(0.75, NodalPlane(45, 90, 0)), (0.125, NodalPlane(strikes[0], 30, 90)), (0.125, NodalPlane(strikes[1], 30, 90))]) if dom['CODE'] == 'FMLR': print 'Define special case for FMLR, 0.5 thrust, 0.5 SS' nodal_plane_dist = PMF([(0.17, NodalPlane(strikes[0], 30, 90)),
from openquake.hmtk.comparison.rate_grids import RateGrid, RatePolygon SOURCE_MODEL_FILE = os.path.join(os.path.dirname(__file__), "rate_grid_test_model.xml") POINT_SOURCE = PointSource("PNT000", "Point 000", "Active Shallow Crust", EvenlyDiscretizedMFD(5.0, 0.1, [1.0]), 1.0, PointMSR(), 1.0, PoissonTOM(1.0), 0.0, 20.0, Point(15.05, 15.05), PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]), PMF([(1.0, 5.0)])) BORDER_POINT_SOURCE = PointSource("PNT000", "Point 000", "Active Shallow Crust", EvenlyDiscretizedMFD(5.0, 0.1, [1.0]), 1.0, PointMSR(), 1.0, PoissonTOM(1.0), 0.0, 20.0, Point(15.0, 15.0), PMF([(1.0, NodalPlane(0.0, 90.0, 0.0))]), PMF([(1.0, 5.0)]))
def _get_nodal_plane_distribution(data): out = [] for tmp in data: out.append([tmp[0], NodalPlane(tmp[1], tmp[2], tmp[3])]) return PMF(out)
def setUp(self): self.npd_as_pmf = PMF([(0.5, NodalPlane(0., 90., 0.)), (0.5, NodalPlane(90., 90., 180.))]) self.npd_as_pmf_bad = PMF([(0.5, None), (0.5, NodalPlane(90., 90., 180.))])
def combine_ss_models(filename_stem, domains_shp, params, lt, bval_key, output_dir='./', nrml_version='04', weight=1.): #, id_base = 'ASS'): """ Combine smoothed seismicity models based on tectonic region types :params filename_stem: String for the start of the xml filename for the source model, assuming generic components (non generic are inferred, e.g. bvalue and completeness model) :params domains_shp: shapefile defining tectonic domain regions :params params: list of dicts containing parameters derivded from the shapefile :bval_key key for the dicts in params as we are merging by bvalues (best, lower, upper) :params lt: LogicTree object containing relevant values and weights for Mmax :params outfile: output nrml formatted file """ dsf = shapefile.Reader(domains_shp) dom_shapes = dsf.shapes() # Get indicies of relevant fields for i, f in enumerate(dsf.fields): if f[0] == 'CODE': code_index = i - 1 if f[0] == 'TRT': trt_index = i - 1 hypo_depth_dist_nc = PMF([(0.5, 10.0), (0.25, 5.0), (0.25, 15.0)]) hypo_depth_dist_c = PMF([(0.5, 5.0), (0.25, 2.5), (0.25, 10.0)]) hypo_depth_dist_ex = hypo_depth_dist_c hypo_depth_dict = { 'Cratonic': hypo_depth_dist_c, 'Non_cratonic': hypo_depth_dist_nc, 'Extended': hypo_depth_dist_ex } # FIXME! - Temporary solution until nodal plan logic tree # info can be read directly from shapefile attributes nodal_plane_dist = PMF([(0.3, NodalPlane(0, 30, 90)), (0.2, NodalPlane(90, 30, 90)), (0.3, NodalPlane(180, 30, 90)), (0.2, NodalPlane(270, 30, 90))]) merged_pts = [] # Get mmax values and weights mmaxs = {} mmaxs_w = {} for dom in params: print 'Processing source %s' % dom['CODE'] print dom['TRT'] if dom['TRT'] == 'NCratonic': dom['TRT'] = 'Non_cratonic' # For the moment, only consider regions within AUstralia if dom['TRT'] == 'Active' or dom['TRT'] == 'Interface' or \ dom['TRT'] == 'Oceanic' or \ dom['TRT'] == 'Intraslab' or dom['CODE'] == 'NECS' or \ dom['CODE'] == 'NWO': print 'Source %s not on continental Australia, skipping' % dom[ 'CODE'] continue elif dom['TRT'] == 'Cratonic': if dom['DOMAIN'] == 1: mmax_values, mmax_weights = lt.get_weights('Mmax', 'Archean') else: mmax_values, mmax_weights = lt.get_weights( 'Mmax', 'Proterozoic') # elif dom['TRT'] == 'Active': # print 'MMax logic tree not yet defined for active crust, using extended crust' # mmax_values, mmax_weights = lt.get_weights('Mmax', 'Extended') else: mmax_values, mmax_weights = lt.get_weights('Mmax', dom['TRT']) mmax_values = [float(i) for i in mmax_values] mmax_weights = [float(i) for i in mmax_weights] print mmax_values print mmax_weights mmaxs[dom['CODE']] = mmax_values mmaxs_w[dom['CODE']] = mmax_weights pt_ids = [] #for trt, filename in filedict.iteritems(): # print trt completeness_string = 'comp' for ym in dom['COMPLETENESS']: completeness_string += '_%i_%.1f' % (ym[0], ym[1]) mmin = dom['COMPLETENESS'][0][1] filename = "%s_b%.3f_mmin%.1f_%s.xml" % (filename_stem, dom[bval_key], mmin, completeness_string) print 'Parsing %s' % filename # TA kluge - hardwire jdg547 path jdgpath = '/short/w84/NSHA18/sandpit/jdg547/NSHA2018/source_models/smoothed_seismicity/' print filename # Only keep points within domain pts = read_pt_source(filename) # shapes = np.where(trt_types for shape in dsf.shapeRecords(): # print code_index print shape.record[code_index] if shape.record[code_index] == dom['CODE']: # Check for undefined depths (-999 values) if dom['DEP_BEST'] < 0: print 'Setting best depth to 10 km' dom['DEP_BEST'] = 10 if dom['DEP_UPPER'] < 0: print 'Setting upper depth to 5 km' dom['DEP_UPPER'] = 5 if dom['DEP_LOWER'] < 0: print 'Setting lower depth to 15 km' dom['DEP_LOWER'] = 15 hypo_depth_dist = PMF([(0.5, dom['DEP_BEST']), (0.25, dom['DEP_LOWER']), (0.25, dom['DEP_UPPER'])]) # Define nodal planes as thrusts except for special cases str1 = dom['SHMAX'] + 90. str2 = dom['SHMAX'] + 270. str3 = dom['SHMAX'] + dom['SHMAX_SIG'] + 90. str4 = dom['SHMAX'] + dom['SHMAX_SIG'] + 270. str5 = dom['SHMAX'] - dom['SHMAX_SIG'] + 90. str6 = dom['SHMAX'] - dom['SHMAX_SIG'] + 270. strikes = [str1, str2, str3, str4, str5, str6] for i, strike in enumerate(strikes): if strike >= 360: strikes[i] = strike - 360 # if strikes[i] >=360: # strikes[i]=strikes[i]-360 nodal_plan_dist = PMF([(0.34, NodalPlane(strikes[0], 30, 90)), (0.34, NodalPlane(strikes[1], 30, 90)), (0.08, NodalPlane(strikes[2], 30, 90)), (0.08, NodalPlane(strikes[3], 30, 90)), (0.08, NodalPlane(strikes[4], 30, 90)), (0.08, NodalPlane(strikes[5], 30, 90))]) if dom['CODE'] == 'WARM' or dom['CODE'] == 'WAPM': print 'Define special case for WARM' nodal_plan_dist = PMF([ (0.75, NodalPlane(45, 90, 0)), (0.125, NodalPlane(strikes[0], 30, 90)), (0.125, NodalPlane(strikes[1], 30, 90)) ]) if dom['CODE'] == 'FMLR': print 'Define special case for FMLR, 0.5 thrust, 0.5 SS' nodal_plan_dist = PMF([ (0.17, NodalPlane(strikes[0], 30, 90)), (0.17, NodalPlane(strikes[1], 30, 90)), (0.04, NodalPlane(strikes[2], 30, 90)), (0.04, NodalPlane(strikes[3], 30, 90)), (0.04, NodalPlane(strikes[4], 30, 90)), (0.04, NodalPlane(strikes[5], 30, 90)), (0.17, NodalPlane(strikes[0], 90, 0)), (0.17, NodalPlane(strikes[1], 90, 0)), (0.04, NodalPlane(strikes[2], 90, 0)), (0.04, NodalPlane(strikes[3], 90, 0)), (0.04, NodalPlane(strikes[4], 90, 0)), (0.04, NodalPlane(strikes[5], 90, 0)) ]) dom_poly = Polygon(shape.shape.points) for pt in pts: pt_loc = Point(pt.location.x, pt.location.y) if pt_loc.within(dom_poly): pt.tectonic_region_type = dom['TRT'] pt.nodal_plane_distribution = nodal_plane_dist # FIXME! update based on data extracted from shapefile pt.hypocenter_distribution = hypo_depth_dist pt.rupture_aspect_ratio = 2 mfd = pt.mfd new_mfd = gr2inc_mmax(mfd, mmaxs[dom['CODE']], mmaxs_w[dom['CODE']], weight) pt.mfd = new_mfd if pt.source_id in pt_ids: print 'Point source %s already exists!' % pt.source_id print 'Skipping this source for trt %s' % zone_trt else: merged_pts.append(pt) pt_ids.append(pt.source_id) outfile = "%s_%s.xml" % (filename_stem, bval_key) outfile = os.path.join(output_dir, outfile) name = outfile.rstrip('.xml') if nrml_version == '04': nodes = list(map(obj_to_node, sorted(merged_pts))) source_model = Node("sourceModel", {"name": name}, nodes=nodes) with open(outfile, 'wb') as f: nrml.write([source_model], f, '%s', xmlns=NAMESPACE) return outfile
#print len(data[:,4]) tom = PoissonTOM(50) # Dummy temporal occurence model for building pt sources msr = Leonard2014_SCR() for j in range(len(data[:, 4])): # print smoother.data[j,:] identifier = 'FSS' + str(j) name = 'Frankel' + str(j) point = Point(data[j, 0], data[j, 1], data[j, 2]) rate = data[j, 4] aval = np.log10(rate) # aval = rate # trying this based on some testing # aval = np.log10(rate) #+ bval*completeness_table_a[0][1] # print aval mfd = TruncatedGRMFD(min_mag, max_mag, 0.1, aval, bval) hypo_depth_dist = PMF([(0.5, 10.0), (0.25, 5.0), (0.25, 15.0)]) nodal_plane_dist = PMF([(0.3, NodalPlane(0, 30, 90)), (0.2, NodalPlane(90, 30, 90)), (0.3, NodalPlane(180, 30, 90)), (0.2, NodalPlane(270, 30, 90))]) point_source = PointSource(identifier, name, 'Non_cratonic', mfd, 2, msr, 2.0, tom, 0.1, 20.0, point, nodal_plane_dist, hypo_depth_dist) source_list.append(point_source) # i+=1 # if j==1000: # break filename = "smoothed_frankel_50_3_mmin_%.1f_b%.3f_0.1.xml" % ( completeness_table_a[0][-1], bvalue) mod_name = 'smoothed_frankel_50_3_mmin_%.1f_b%.3f_0.1' % ( completeness_table_a[0][-1], bvalue)
def run_smoothing(grid_lims, smoothing_config, catalogue, completeness_table, map_config, run, overwrite=True): """Run all the smoothing """ ystart = completeness_table[-1][0] yend = catalogue.end_year catalogue_comp = deepcopy(catalogue) # Ensuring that catalogue is cleaned of earthquakes outside of # completeness period index = catalogue_comp.data['year'] >= ystart catalogue_comp.purge_catalogue(index) completeness_string = 'comp' for ym in completeness_table: completeness_string += '_%i_%.1f' % (ym[0], ym[1]) smoother_filename = 'Australia_Fixed_%i_%i_b%.3f_mmin_%.1f_0.1%s.csv' % ( smoothing_config["BandWidth"], smoothing_config["Length_Limit"], bvalue, completeness_table[0][1], completeness_string) filename = smoother_filename[:-4] + '.xml' if os.path.exists(filename) and not overwrite: print '%s already created, not overwriting!' % filename return smoother = SmoothedSeismicity( [105., 160., 0.1, -47., -5, 0.1, 0., 20., 20.], bvalue=smoothing_config['bvalue']) print 'Running smoothing' smoothed_grid = smoother.run_analysis( catalogue_comp, smoothing_config, completeness_table=completeness_table) smoother.write_to_csv(smoother_filename) from openquake.hazardlib.nrml import SourceModelParser, write, NAMESPACE from openquake.baselib.node import Node from openquake.hazardlib import nrml from openquake.hazardlib.sourcewriter import obj_to_node # Build nrml input file of point sources source_list = [] #i=0 min_mag = 4.5 max_mag = 7.8 bval = bvalue # just define as 1 for time being # Read in data again to solve number fomatting issue in smoother.data # For some reason it just returns 0 for all a values try: data = np.genfromtxt(smoother_filename, delimiter=',', skip_header=1) except ValueError: print 'Something wrong with file %s' % smoother_filename sys.exit() tom = PoissonTOM( 50) # Dummy temporal occurence model for building pt sources msr = Leonard2014_SCR() for j in range(len(data[:, 4])): # print smoother.data[j,:] identifier = 'FSS' + str(j) + '_' + str(run) name = 'Frankel' + str(j) + '_' + str(run) point = Point(data[j, 0], data[j, 1], data[j, 2]) annual_rate = data[j, 4] / (yend - ystart + 1) aval = np.log10(annual_rate) + smoothing_config[ 'bvalue'] * completeness_table[0][1] mfd = TruncatedGRMFD(min_mag, max_mag, 0.1, aval, bval) hypo_depth_dist = PMF([(0.5, 10.0), (0.25, 5.0), (0.25, 15.0)]) nodal_plane_dist = PMF([(0.3, NodalPlane(0, 30, 90)), (0.2, NodalPlane(90, 30, 90)), (0.3, NodalPlane(180, 30, 90)), (0.2, NodalPlane(270, 30, 90))]) point_source = PointSource(identifier, name, 'Non_cratonic', mfd, 2, msr, 2.0, tom, 0.1, 20.0, point, nodal_plane_dist, hypo_depth_dist) source_list.append(point_source) nodes = list(map(obj_to_node, sorted(source_list))) source_model = Node("sourceModel", {"name": name}, nodes=nodes) with open(filename, 'wb') as f: nrml.write([source_model], f, '%s', xmlns=NAMESPACE) # Creating a basemap - input a cconfiguration and (if desired) a title title = 'Smoothed seismicity rate for learning \nperiod %i 2017, Mmin = %.1f' % ( completeness_table[0][0], completeness_table[0][1]) basemap1 = HMTKBaseMap(map_config, 'Smoothed seismicity rate') # Adding the smoothed grip to the basemap sym = (2., 3., 'cx') x, y = basemap1.m(smoother.data[:, 0], smoother.data[:, 1]) basemap1.m.scatter(x, y, marker='s', c=np.log10(smoother.data[:, 4]), cmap=plt.cm.coolwarm, zorder=10, lw=0, vmin=-6.5, vmax=1.5) basemap1.m.drawcoastlines(linewidth=1, zorder=50) # Add coastline on top basemap1.m.drawmeridians( np.arange(map_config['min_lat'], map_config['max_lat'], 5)) basemap1.m.drawparallels( np.arange(map_config['min_lon'], map_config['max_lon'], 5)) plt.colorbar(label='log10(Smoothed rate per cell)') plt.legend() figname = smoother_filename[:-4] + '_smoothed_rates_map.png' plt.savefig(figname)
from openquake.hazardlib.calc.filters import SourceFilter, FarAwayRupture from openquake.hazardlib.mfd import EvenlyDiscretizedMFD from openquake.hazardlib.sourceconverter import SourceConverter # ######################## rupture calculator ############################ # U16 = numpy.uint16 U32 = numpy.uint32 U64 = numpy.uint64 F32 = numpy.float32 # DEFAULT VALUES FOR UCERF BACKGROUND MODELS DEFAULT_MESH_SPACING = 1.0 DEFAULT_TRT = "Active Shallow Crust" HDD = PMF([(0.2, 3.0), (0.6, 6.0), (0.2, 9.0)]) NPD = PMF([(0.15, NodalPlane(0.0, 90.0, 0.0)), (0.15, NodalPlane(45.0, 90.0, 0.0)), (0.15, NodalPlane(90.0, 90.0, 0.0)), (0.15, NodalPlane(135.0, 90.0, 0.0)), (0.05, NodalPlane(0.0, 45.0, 90.)), (0.05, NodalPlane(45.0, 45.0, 90.)), (0.05, NodalPlane(90.0, 45.0, 90.)), (0.05, NodalPlane(135.0, 45.0, 90.)), (0.05, NodalPlane(180.0, 45.0, 90.)), (0.05, NodalPlane(225.0, 45.0, 90.)), (0.05, NodalPlane(270.0, 45.0, 90.)), (0.05, NodalPlane(325.0, 45.0, 90.))]) class ImperfectPlanarSurface(PlanarSurface): """
def test_corner_cases(self): np = NodalPlane(strike=0, dip=0.001, rake=-180 + 1e-5) self.assertEqual((np.strike, np.dip, np.rake), (0, 0.001, -180 + 1e-5)) np = NodalPlane(strike=360 - 1e-5, dip=90, rake=+180) self.assertEqual((np.strike, np.dip, np.rake), (360 - 1e-5, 90, +180))
def pt2fault_distance(pt_sources, fault_sources, min_distance=5.0, filename='source_model.xml', buffer_distance=100., nrml_version='04', name=None): """Calculate distances from a pt source rupture plane to the fault sources to then reduce Mmax on events that are within a certain distance :param pt_sources: list of PointSource objects :param fault_sources: List of FaultSource objects :param min_distance: Minimum distance (km) within which we want a point source rupture to be from a fault. :param filename: Name of output nrml file for revised pt source model :param buffer_distance: Km, initial filter to only process pts within this distance from the fault """ if name is None: name = filename[:-4] + '_geom_filtered' id_index = 0 # We need to re-number all sources to avoid duplicate ids # Extract the points of the fault source mesh fault_lons = [] fault_lats = [] fault_depths = [] for fault in fault_sources: whole_fault_surface = SimpleFaultSurface.from_fault_data( fault.fault_trace, fault.upper_seismogenic_depth, fault.lower_seismogenic_depth, fault.dip, fault.rupture_mesh_spacing) fault_lons.append(whole_fault_surface.mesh.lons.flatten()) fault_lats.append(whole_fault_surface.mesh.lats.flatten()) fault_depths.append(whole_fault_surface.mesh.depths.flatten()) fault_lons = np.concatenate(fault_lons) fault_lats = np.concatenate(fault_lats) fault_depths = np.concatenate(fault_depths) min_fault_lon = np.min(fault_lons) max_fault_lon = np.max(fault_lons) min_fault_lat = np.min(fault_lats) max_fault_lat = np.max(fault_lats) # Generate ruptures for point sources minimum_distance_list = [] revised_point_sources = { 'Cratonic': [], 'Non_cratonic': [], 'Extended': [], 'Banda': [] } for pt in pt_sources: print 'Looping over point sources' # For speeding things up filter based on initial distances # to find points very far from or very close to a fault mfd_type = type(pt.mfd).__name__ pt_depths = [] for probs, depths in pt.hypocenter_distribution.data: pt_depths.append(depths) np_probs = [] np_list = [] for prob, nodal_plane in pt.nodal_plane_distribution.data: np_probs.append(prob) np_list.append(nodal_plane) centroid_distances = [] for pt_depth in pt_depths: centroid_distances.append( distance(pt.location.longitude, pt.location.latitude, pt_depth, fault_lons, fault_lats, fault_depths)) centroid_distances = np.array(centroid_distances).flatten() # print 'Minimum distance', min(centroid_distances) # print 'Maximum distance', max(centroid_distances) if (min(centroid_distances)) > buffer_distance: # Keep point as it, not within buffer distance of any faults revised_point_sources[pt.tectonic_region_type].append(pt) continue if (min(centroid_distances)) < min_distance: # Discard point sources as too close to a fault print 'Discarding point source, too close to a fault' continue rupture_mags = [] rupture_lons = [] rupture_lats = [] rupture_depths = [] rupture_strikes = [] rupture_dips = [] ruptures = pt.iter_ruptures() for rupture in ruptures: rupture_mags.append(rupture.mag) rupture_lons.append(rupture.surface.corner_lons) rupture_lats.append(rupture.surface.corner_lats) rupture_depths.append(rupture.surface.corner_depths) rupture_strikes.append(rupture.surface.strike) rupture_dips.append(rupture.surface.dip) rupture_mags = np.array(rupture_mags).flatten() # make the same length as the corners rupture_mags = np.repeat(rupture_mags, 4) rupture_strikes = np.repeat(rupture_strikes, 4) rupture_dips = np.repeat(rupture_dips, 4) rupture_lons = np.array(rupture_lons).flatten() rupture_lats = np.array(rupture_lats).flatten() rupture_depths = np.array(rupture_depths).flatten() print 'Doing meshgrid' lons1, lons2 = np.meshgrid(fault_lons, rupture_lons) lats1, lats2 = np.meshgrid(fault_lats, rupture_lats) depths1, depths2 = np.meshgrid(fault_depths, rupture_depths) # Calculate distance from pt to all fault print 'Distance calculations' distances = distance(lons1, lats1, depths1, lons2, lats2, depths2) closest_distance_to_faults = np.min(distances) print 'Shortest pt to fault distance is', closest_distance_to_faults minimum_distance_list.append(closest_distance_to_faults) # Find where the distance is less than the threshold min_distance too_close_lons = lons2[np.where(distances < min_distance)] too_close_lats = lats2[np.where(distances < min_distance)] if too_close_lons.size > 0: lon_indices = np.where(np.in1d(rupture_lons, too_close_lons))[0] lat_indices = np.where(np.in1d(rupture_lats, too_close_lats))[0] too_close_mags = rupture_mags[np.intersect1d( lon_indices, lat_indices)] too_close_strikes = rupture_strikes[np.intersect1d( lon_indices, lat_indices)] too_close_dips = rupture_dips[np.intersect1d( lon_indices, lat_indices)] # print 'Magnitudes of rupture close to fault', too_close_mags # print 'Strikes of rupture close to fault', too_close_strikes # print 'Dips of rupture close to fault', too_close_dips unique_strikes = np.unique(rupture_strikes) unique_dips = np.unique(rupture_dips) src_name_index = 0 for prob, nodal_plane in pt.nodal_plane_distribution.data: id_index += 1 src_name_index += 1 # We are now splitting the source into many with different # combinations of Mmaxs and nodal planes new_pt = copy.deepcopy(pt) new_pt.source_id = "%i" % id_index new_pt.name = new_pt.name + ("_%i" % src_name_index) new_np = NodalPlane(nodal_plane.strike, nodal_plane.dip, nodal_plane.rake) new_np_distribution = PMF([ (1.0, new_np) ]) # weight of nodal plane is 1 as making # a separate source # Calculate new rates based on probability of original nodal plane new_pt.nodal_plane_distribution = new_np_distribution if mfd_type == 'TruncatedGRMFD': b_val = pt.mfd.b_val # rescale a value in log sapce a_val = np.log10(np.power(10, pt.mfd.a_val) * prob) #*area_src_weight)) new_pt.mfd.modify_set_ab(a_val, b_val) elif mfd_type == 'EvenlyDiscretizedMFD': mag_bins, rates = zip( *pt.mfd.get_annual_occurrence_rates()) mag_bins = np.array(mag_bins) rates = np.array(rates) new_rates = rates * prob #*area_src_weight) new_pt.mfd.modify_set_mfd(new_pt.mfd.min_mag, new_pt.mfd.bin_width, list(new_rates)) else: msg = 'Weighting method for mfd type %s not yet defined' % mfd_type raise (msg) pair_index = np.where( np.logical_and(too_close_strikes == nodal_plane.strike, too_close_dips == nodal_plane.dip)) # Deal with intersecting cases if len(pair_index[0]) > 0: intersecting_magnitudes = too_close_mags[pair_index] minimum_magnitude_intersecting_fault = min( intersecting_magnitudes) if minimum_magnitude_intersecting_fault >= \ (pt.mfd.min_mag + pt.mfd.bin_width): new_mmax = minimum_magnitude_intersecting_fault - \ pt.mfd.bin_width if mfd_type == 'TruncatedGRMFD': new_pt.mfd.max_mag = new_mmax if mfd_type == 'EvenlyDiscretizedMFD': trimmed_rates = new_rates[np.where( mag_bins <= new_mmax)] else: print 'Minimum magnitude intersects fault, discarding source' continue else: pass # Append revised source for given nodal plane distribution to # list of revised sources print 'Appending revised source' revised_point_sources[pt.tectonic_region_type].append(new_pt) else: id_index += 1 pt.source_id = "%i" % id_index 'Appending original source' revised_point_sources[pt.tectonic_region_type].append(pt) if len(minimum_distance_list) > 0: print 'Overall minimum distance (km):', min(minimum_distance_list) # Write pts to source model on their own source_model_file = filename print 'Writing to source model file %s' % source_model_file if nrml_version == '04': source_list = [] for trt, sources in revised_point_sources.iteritems(): for source in sources: source_list.append(source) nodes = list(map(obj_to_node, sorted(source_list))) source_model = Node("sourceModel", {"name": name}, nodes=nodes) with open(source_model_file, 'wb') as f: nrml.write([source_model], f, '%s', xmlns=NAMESPACE) elif nrml_version == '05': source_group_list = [] id = 0 for trt, sources in revised_point_sources.iteritems(): source_group = SourceGroup(trt, sources=sources, id=id) id += 1 source_group_list.append(source_group) write_source_model(source_model_file, source_group_list, name=name) else: print 'Warning: nrml version not specfied, xml not created' # Write pts to source model with faults source_model_file = filename[:-4] + '_inc_faults.xml' name = name + '_inc_faults' write_combined_faults_points(revised_point_sources, fault_sources, source_model_file, name, nrml_version='04')