def test(self): class FakeSource(object): def __init__(self, integration_distance, sites_mapping): self.integration_distance = integration_distance self.sites_mapping = sites_mapping def filter_sites_by_distance_to_source(self, integration_distance, sites): assert integration_distance is self.integration_distance return self.sites_mapping[sites] sites1 = object() sites2 = object() sites3 = object() sources = [ FakeSource(123, {sites1: None}), # all filtered out FakeSource(123, {sites2: sites3}), # partial filtering FakeSource(123, {sites1: sites1}) ] # nothing filtered out sites = [sites1, sites2, sites1] filter_func = filters.source_site_distance_filter(123) filtered = filter_func(izip(sources, sites)) self.assertIsInstance(filtered, GeneratorType) source, sites = next(filtered) self.assertIs(source, sources[1]) self.assertIs(sites, sites3) source, sites = next(filtered) self.assertIs(source, sources[2]) self.assertIs(sites, sites1) self.assertEqual(list(filtered), [])
def test_ses_generation_from_parametric_source_with_filtering(self): # generate stochastic event set (SES) from 2 area sources (area1, # area2). However, by including a single site co-located with the # area1 center, and with source site filtering of 100 km (exactly # the radius of area1), the second source (area2), which is centered # at 5., 5. (that is about 500 km from center of area1), will be # excluded. the MFD from the SES will be therefore approximately equal # to the one of area1 only. numpy.random.seed(123) sites = SiteCollection([ Site( location=Point(0., 0.), vs30=760, vs30measured=True, z1pt0=40., z2pt5=2. ) ]) ses = stochastic_event_set( [self.area1, self.area2], sites=sites, source_site_filter=filters.source_site_distance_filter(100.) ) rates = self._extract_rates(ses, time_span=self.time_span, bins=numpy.arange(5., 6.6, 0.1)) expect_rates = numpy.array( [r for m, r in self.mfd.get_annual_occurrence_rates()] ) numpy.testing.assert_allclose(rates, expect_rates, rtol=0, atol=1e-4)
def test(self): class FakeSource(object): def __init__(self, integration_distance, sites_mapping): self.integration_distance = integration_distance self.sites_mapping = sites_mapping def filter_sites_by_distance_to_source(self, integration_distance, sites): assert integration_distance is self.integration_distance return self.sites_mapping[sites] sites1 = object() sites2 = object() sites3 = object() sources = [FakeSource(123, {sites1: None}), # all filtered out FakeSource(123, {sites2: sites3}), # partial filtering FakeSource(123, {sites1: sites1})] # nothing filtered out sites = [sites1, sites2, sites1] filter_func = filters.source_site_distance_filter(123) filtered = filter_func(izip(sources, sites)) self.assertIsInstance(filtered, GeneratorType) source, sites = next(filtered) self.assertIs(source, sources[1]) self.assertIs(sites, sites3) source, sites = next(filtered) self.assertIs(source, sources[2]) self.assertIs(sites, sites1) self.assertEqual(list(filtered), [])
def classical(sources, sitecol, gsims_assoc, monitor): """ :param sources: a non-empty sequence of sources of homogeneous tectonic region type :param sitecol: a SiteCollection instance :param gsims_assoc: associations trt_model_id -> gsims :param monitor: a monitor instance :returns: an AccumDict rlz -> curves """ max_dist = monitor.oqparam.maximum_distance truncation_level = monitor.oqparam.truncation_level imtls = monitor.oqparam.imtls trt_model_id = sources[0].trt_model_id gsims = gsims_assoc[trt_model_id] curves_by_gsim = hazard_curves_per_trt( sources, sitecol, imtls, gsims, truncation_level, source_site_filter=source_site_distance_filter(max_dist), rupture_site_filter=rupture_site_distance_filter(max_dist), monitor=monitor) dic = dict(monitor=monitor) for gsim, curves in zip(gsims, curves_by_gsim): dic[trt_model_id, str(gsim)] = curves return dic
def __init__(self, source_model, sites, gmpes, imls, imts, truncation_level=None, source_integration_dist=None, rupture_integration_dist=None): """ Instatiate and preprocess :param float source_integration_dist: Integration distance for sources :param float rupture_integration_dist: Integration distance for ruptures """ self.source_model = source_model self.sites = sites self.gmpes = gmpes self.imls = imls self.imts = imts self.truncation_level = truncation_level if source_integration_dist: self.src_filter = filters.source_site_distance_filter( source_integration_dist) else: self.src_filter = filters.source_site_noop_filter if rupture_integration_dist: self.rup_filter = filters.rupture_site_distance_filter( rupture_integration_dist) else: self.rup_filter = filters.rupture_site_noop_filter self.preprocess_inputs()
def get_source_filter_condition(self): """ Return a function filtering on the maximum_distance """ src_filter = filters.source_site_distance_filter(self.hc.maximum_distance) def filter_on_distance(src): """True if the source is relevant for the site collection""" return bool(list(src_filter([(src, self.hc.site_collection)]))) return filter_on_distance
def get_source_filter_condition(self): """ Return a function filtering on the maximum_distance """ src_filter = filters.source_site_distance_filter( self.hc.maximum_distance) def filter_on_distance(src): """True if the source is relevant for the site collection""" return bool(list(src_filter([(src, self.hc.site_collection)]))) return filter_on_distance
def classical(sources, sitecol, siteidx, rlzs_assoc, monitor): """ :param sources: a non-empty sequence of sources of homogeneous tectonic region type :param sitecol: a SiteCollection instance :param siteidx: index of the first site (0 if there is a single tile) :param rlzs_assoc: a RlzsAssoc instance :param monitor: a monitor instance :returns: an AccumDict rlz -> curves """ truncation_level = monitor.oqparam.truncation_level imtls = monitor.oqparam.imtls trt_model_id = sources[0].trt_model_id # sanity check: the trt_model must be the same for all sources for src in sources[1:]: assert src.trt_model_id == trt_model_id gsims = rlzs_assoc.gsims_by_trt_id[trt_model_id] trt = sources[0].tectonic_region_type try: max_dist = monitor.oqparam.maximum_distance[trt] except KeyError: max_dist = monitor.oqparam.maximum_distance['default'] dic = AccumDict() dic.siteslice = slice(siteidx, siteidx + len(sitecol)) if monitor.oqparam.poes_disagg: sm_id = rlzs_assoc.get_sm_id(trt_model_id) dic.bbs = [BoundingBox(sm_id, sid) for sid in sitecol.sids] else: dic.bbs = [] # NB: the source_site_filter below is ESSENTIAL for performance inside # hazard_curves_per_trt, since it reduces the full site collection # to a filtered one *before* doing the rupture filtering curves_by_gsim = hazard_curves_per_trt( sources, sitecol, imtls, gsims, truncation_level, source_site_filter=source_site_distance_filter(max_dist), maximum_distance=max_dist, bbs=dic.bbs, monitor=monitor) dic.calc_times = monitor.calc_times # added by hazard_curves_per_trt dic.eff_ruptures = {trt_model_id: monitor.eff_ruptures} # idem for gsim, curves in zip(gsims, curves_by_gsim): dic[trt_model_id, str(gsim)] = curves return dic
def test_point_sources(self): sources = [ openquake.hazardlib.source.PointSource( source_id='point1', name='point1', tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST, mfd=openquake.hazardlib.mfd.EvenlyDiscretizedMFD( min_mag=4, bin_width=1, occurrence_rates=[5]), nodal_plane_distribution=openquake.hazardlib.pmf.PMF([ (1, openquake.hazardlib.geo.NodalPlane(strike=0.0, dip=90.0, rake=0.0)) ]), hypocenter_distribution=openquake.hazardlib.pmf.PMF([(1, 10)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship=openquake.hazardlib.scalerel. PeerMSR(), rupture_aspect_ratio=2, temporal_occurrence_model=PoissonTOM(1.), rupture_mesh_spacing=1.0, location=Point(10, 10)), openquake.hazardlib.source.PointSource( source_id='point2', name='point2', tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST, mfd=openquake.hazardlib.mfd.EvenlyDiscretizedMFD( min_mag=4, bin_width=2, occurrence_rates=[5, 6, 7]), nodal_plane_distribution=openquake.hazardlib.pmf.PMF([ (1, openquake.hazardlib.geo.NodalPlane(strike=0, dip=90, rake=0.0)), ]), hypocenter_distribution=openquake.hazardlib.pmf.PMF([(1, 10)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship=openquake.hazardlib.scalerel. PeerMSR(), rupture_aspect_ratio=2, temporal_occurrence_model=PoissonTOM(1.), rupture_mesh_spacing=1.0, location=Point(10, 11)), ] sites = [ openquake.hazardlib.site.Site(Point(11, 10), 1, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 16), 2, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 10.6), 3, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 10.7), 4, True, 2, 3) ] sitecol = openquake.hazardlib.site.SiteCollection(sites) from openquake.hazardlib.gsim.sadigh_1997 import SadighEtAl1997 gsims = {const.TRT.ACTIVE_SHALLOW_CRUST: SadighEtAl1997()} truncation_level = 1 imts = {'PGA': [0.1, 0.5, 1.3]} from openquake.hazardlib.calc import filters source_site_filter = self.SitesCounterSourceFilter( filters.source_site_distance_filter(30)) rupture_site_filter = self.SitesCounterRuptureFilter( filters.rupture_site_distance_filter(30)) calc_hazard_curves(sources, sitecol, imts, gsims, truncation_level, source_site_filter=source_site_filter, rupture_site_filter=rupture_site_filter) # there are two sources and four sites. The first source contains only # one rupture, the second source contains three ruptures. # # the first source has 'maximum projection radius' of 0.707 km # the second source has 'maximum projection radius' of 500.0 km # # the epicentral distances for source 1 are: [ 109.50558394, # 667.16955987, 66.71695599, 77.83644865] # the epicentral distances for source 2 are: [ 155.9412148 , # 555.97463322, 44.47797066, 33.35847799] # # Considering that the source site filtering distance is set to 30 km, # for source 1, all sites have epicentral distance larger than # 0.707 + 30 km. This means that source 1 ('point 1') is not considered # in the calculation because too far. # for source 2, the 1st, 3rd and 4th sites have epicentral distances # smaller than 500.0 + 30 km. This means that source 2 ('point 2') is # considered in the calculation for site 1, 3, and 4. # # JB distances for rupture 1 in source 2 are: [ 155.43860273, # 555.26752644, 43.77086388, 32.65137121] # JB distances for rupture 2 in source 2 are: [ 150.98882575, # 548.90356541, 37.40690285, 26.28741018] # JB distances for rupture 3 in source 2 are: [ 109.50545819, # 55.97463322, 0. , 0. ] # # Considering that the rupture site filtering distance is set to 30 km, # rupture 1 (magnitude 4) is not considered because too far, rupture 2 # (magnitude 6) affect only the 4th site, rupture 3 (magnitude 8) # affect the 3rd and 4th sites. self.assertEqual(source_site_filter.counts, [('point2', [1, 3, 4])]) self.assertEqual(rupture_site_filter.counts, [(6, [4]), (8, [3, 4])])
def ses_and_gmfs(job_id, src_ids, lt_rlz_id, task_seed, result_grp_ordinal): """ Celery task for the stochastic event set calculator. Samples logic trees and calls the stochastic event set calculator. Once stochastic event sets are calculated, results will be saved to the database. See :class:`openquake.engine.db.models.SESCollection`. Optionally (specified in the job configuration using the `ground_motion_fields` parameter), GMFs can be computed from each rupture in each stochastic event set. GMFs are also saved to the database. Once all of this work is complete, a signal will be sent via AMQP to let the control noe know that the work is complete. (If there is any work left to be dispatched, this signal will indicate to the control node that more work can be enqueued.) :param int job_id: ID of the currently running job. :param src_ids: List of ids of parsed source models from which we will generate stochastic event sets/ruptures. :param lt_rlz_id: Id of logic tree realization model to calculate for. :param int task_seed: Value for seeding numpy/scipy in the computation of stochastic event sets and ground motion fields. :param int result_grp_ordinal: The result group in which the calculation results will be placed. This ID basically corresponds to the sequence number of the task, in the context of the entire calculation. """ logs.LOG.debug(('> starting `stochastic_event_sets` task: job_id=%s, ' 'lt_realization_id=%s') % (job_id, lt_rlz_id)) numpy.random.seed(task_seed) hc = models.HazardCalculation.objects.get(oqjob=job_id) cmplt_lt_ses = None if hc.complete_logic_tree_ses: cmplt_lt_ses = models.SES.objects.get( ses_collection__output__oq_job=job_id, complete_logic_tree_ses=True) if hc.ground_motion_fields: # For ground motion field calculation, we need the points of interest # for the calculation. points_to_compute = hc.points_to_compute() imts = [haz_general.imt_to_hazardlib(x) for x in hc.intensity_measure_types] correl_model = None if hc.ground_motion_correlation_model is not None: correl_model = haz_general.get_correl_model(hc) lt_rlz = models.LtRealization.objects.get(id=lt_rlz_id) ltp = logictree.LogicTreeProcessor(hc.id) apply_uncertainties = ltp.parse_source_model_logictree_path( lt_rlz.sm_lt_path) gsims = ltp.parse_gmpe_logictree_path(lt_rlz.gsim_lt_path) sources = list(haz_general.gen_sources( src_ids, apply_uncertainties, hc.rupture_mesh_spacing, hc.width_of_mfd_bin, hc.area_source_discretization)) # Compute stochastic event sets # For each rupture generated, we can optionally calculate a GMF for ses_rlz_n in xrange(1, hc.ses_per_logic_tree_path + 1): logs.LOG.debug('> computing stochastic event set %s of %s' % (ses_rlz_n, hc.ses_per_logic_tree_path)) # This is the container for all ruptures for this stochastic event set # (specified by `ordinal` and the logic tree realization). # NOTE: Many tasks can contribute ruptures to this SES. ses = models.SES.objects.get( ses_collection__lt_realization=lt_rlz, ordinal=ses_rlz_n) sources_sites = ((src, hc.site_collection) for src in sources) ssd_filter = filters.source_site_distance_filter(hc.maximum_distance) # Get the filtered sources, ignore the site collection: filtered_sources = (src for src, _ in ssd_filter(sources_sites)) # Calculate stochastic event sets: logs.LOG.debug('> computing stochastic event sets') if hc.ground_motion_fields: gmf_cache = _create_gmf_cache(len(points_to_compute), imts) logs.LOG.debug('> computing also ground motion fields') # This will be the "container" for all computed ground motion field # results for this stochastic event set. gmf_set = models.GmfSet.objects.get( gmf_collection__lt_realization=lt_rlz, ses_ordinal=ses_rlz_n) ses_poissonian = stochastic.stochastic_event_set_poissonian( filtered_sources, hc.investigation_time) logs.LOG.debug('> looping over ruptures') rupture_ordinal = 0 for rupture in ses_poissonian: rupture_ordinal += 1 # Prepare and save SES ruptures to the db: logs.LOG.debug('> saving SES rupture to DB') _save_ses_rupture( ses, rupture, cmplt_lt_ses, result_grp_ordinal, rupture_ordinal) logs.LOG.debug('> done saving SES rupture to DB') # Compute ground motion fields (if requested) logs.LOG.debug('compute ground motion fields? %s' % hc.ground_motion_fields) if hc.ground_motion_fields: # Compute and save ground motion fields gmf_calc_kwargs = { 'rupture': rupture, 'sites': hc.site_collection, 'imts': imts, 'gsim': gsims[rupture.tectonic_region_type], 'truncation_level': hc.truncation_level, 'realizations': DEFAULT_GMF_REALIZATIONS, 'correlation_model': correl_model, 'rupture_site_filter': filters.rupture_site_distance_filter( hc.maximum_distance), } logs.LOG.debug('> computing ground motion fields') gmf_dict = gmf_calc.ground_motion_fields(**gmf_calc_kwargs) logs.LOG.debug('< done computing ground motion fields') # update the gmf cache: for k, v in gmf_dict.iteritems(): gmf_cache[k] = numpy.append( gmf_cache[k], v, axis=1) logs.LOG.debug('< Done looping over ruptures') logs.LOG.debug('%s ruptures computed for SES realization %s of %s' % (rupture_ordinal, ses_rlz_n, hc.ses_per_logic_tree_path)) logs.LOG.debug('< done computing stochastic event set %s of %s' % (ses_rlz_n, hc.ses_per_logic_tree_path)) if hc.ground_motion_fields: # save the GMFs to the DB logs.LOG.debug('> saving GMF results to DB') _save_gmfs( gmf_set, gmf_cache, points_to_compute, result_grp_ordinal) logs.LOG.debug('< done saving GMF results to DB') logs.LOG.debug('< task complete, signalling completion') base.signal_task_complete(job_id=job_id, num_items=len(src_ids))
def test_point_sources(self): sources = [ openquake.hazardlib.source.PointSource( source_id='point1', name='point1', tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST, mfd=openquake.hazardlib.mfd.EvenlyDiscretizedMFD( min_mag=4, bin_width=1, occurrence_rates=[5] ), nodal_plane_distribution=openquake.hazardlib.pmf.PMF([ (1, openquake.hazardlib.geo.NodalPlane(strike=0.0, dip=90.0, rake=0.0)) ]), hypocenter_distribution=openquake.hazardlib.pmf.PMF([(1, 10)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship= openquake.hazardlib.scalerel.PeerMSR(), rupture_aspect_ratio=2, temporal_occurrence_model=PoissonTOM(1.), rupture_mesh_spacing=1.0, location=Point(10, 10) ), openquake.hazardlib.source.PointSource( source_id='point2', name='point2', tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST, mfd=openquake.hazardlib.mfd.EvenlyDiscretizedMFD( min_mag=4, bin_width=2, occurrence_rates=[5, 6, 7] ), nodal_plane_distribution=openquake.hazardlib.pmf.PMF([ (1, openquake.hazardlib.geo.NodalPlane(strike=0, dip=90, rake=0.0)), ]), hypocenter_distribution=openquake.hazardlib.pmf.PMF([(1, 10)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship= openquake.hazardlib.scalerel.PeerMSR(), rupture_aspect_ratio=2, temporal_occurrence_model=PoissonTOM(1.), rupture_mesh_spacing=1.0, location=Point(10, 11) ), ] sites = [openquake.hazardlib.site.Site(Point(11, 10), 1, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 16), 2, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 10.6), 3, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 10.7), 4, True, 2, 3)] sitecol = openquake.hazardlib.site.SiteCollection(sites) from openquake.hazardlib.gsim.sadigh_1997 import SadighEtAl1997 gsims = {const.TRT.ACTIVE_SHALLOW_CRUST: SadighEtAl1997()} truncation_level = 1 imts = {openquake.hazardlib.imt.PGA(): [0.1, 0.5, 1.3]} from openquake.hazardlib.calc import filters source_site_filter = self.SitesCounterSourceFilter( filters.source_site_distance_filter(30) ) rupture_site_filter = self.SitesCounterRuptureFilter( filters.rupture_site_distance_filter(30) ) hazard_curves( iter(sources), sitecol, imts, gsims, truncation_level, source_site_filter=source_site_filter, rupture_site_filter=rupture_site_filter ) # there are two sources and four sites. The first source contains only # one rupture, the second source contains three ruptures. # # the first source has 'maximum projection radius' of 0.707 km # the second source has 'maximum projection radius' of 500.0 km # # the epicentral distances for source 1 are: [ 109.50558394, # 667.16955987, 66.71695599, 77.83644865] # the epicentral distances for source 2 are: [ 155.9412148 , # 555.97463322, 44.47797066, 33.35847799] # # Considering that the source site filtering distance is set to 30 km, # for source 1, all sites have epicentral distance larger than # 0.707 + 30 km. This means that source 1 ('point 1') is not considered # in the calculation because too far. # for source 2, the 1st, 3rd and 4th sites have epicentral distances # smaller than 500.0 + 30 km. This means that source 2 ('point 2') is # considered in the calculation for site 1, 3, and 4. # # JB distances for rupture 1 in source 2 are: [ 155.43860273, # 555.26752644, 43.77086388, 32.65137121] # JB distances for rupture 2 in source 2 are: [ 150.98882575, # 548.90356541, 37.40690285, 26.28741018] # JB distances for rupture 3 in source 2 are: [ 109.50545819, # 55.97463322, 0. , 0. ] # # Considering that the rupture site filtering distance is set to 30 km, # rupture 1 (magnitude 4) is not considered because too far, rupture 2 # (magnitude 6) affect only the 4th site, rupture 3 (magnitude 8) # affect the 3rd and 4th sites. self.assertEqual(source_site_filter.counts, [('point2', [1, 3, 4])]) self.assertEqual(rupture_site_filter.counts, [(6, [4]), (8, [3, 4])])
def ses_and_gmfs(job_id, src_ids, ses, task_seed): """ Celery task for the stochastic event set calculator. Samples logic trees and calls the stochastic event set calculator. Once stochastic event sets are calculated, results will be saved to the database. See :class:`openquake.engine.db.models.SESCollection`. Optionally (specified in the job configuration using the `ground_motion_fields` parameter), GMFs can be computed from each rupture in each stochastic event set. GMFs are also saved to the database. :param int job_id: ID of the currently running job. :param src_ids: List of ids of parsed source models from which we will generate stochastic event sets/ruptures. :param lt_rlz_id: Id of logic tree realization model to calculate for. :param int task_seed: Value for seeding numpy/scipy in the computation of stochastic event sets and ground motion fields. """ numpy.random.seed(task_seed) hc = models.HazardCalculation.objects.get(oqjob=job_id) # complete_logic_tree_ses flag cmplt_lt_ses = None if hc.complete_logic_tree_ses: cmplt_lt_ses = models.SES.objects.get( ses_collection__output__oq_job=job_id, ordinal=None) # preparing sources ltp = logictree.LogicTreeProcessor(hc.id) lt_rlz = ses.ses_collection.lt_realization apply_uncertainties = ltp.parse_source_model_logictree_path( lt_rlz.sm_lt_path) gsims = ltp.parse_gmpe_logictree_path(lt_rlz.gsim_lt_path) source_iter = haz_general.gen_sources( src_ids, apply_uncertainties, hc.rupture_mesh_spacing, hc.width_of_mfd_bin, hc.area_source_discretization) src_filter = filters.source_site_distance_filter(hc.maximum_distance) rup_filter = filters.rupture_site_distance_filter(hc.maximum_distance) with EnginePerformanceMonitor( 'reading site collection', job_id, ses_and_gmfs): site_collection = hc.site_collection # Compute and save stochastic event sets # For each rupture generated, we can optionally calculate a GMF with EnginePerformanceMonitor('computing ses', job_id, ses_and_gmfs): ruptures = list(stochastic.stochastic_event_set_poissonian( source_iter, hc.investigation_time, site_collection, src_filter, rup_filter)) if not ruptures: return with EnginePerformanceMonitor('saving ses', job_id, ses_and_gmfs): rupture_ids = _save_ses_ruptures(ses, ruptures, cmplt_lt_ses) if hc.ground_motion_fields: with EnginePerformanceMonitor( 'computing gmfs', job_id, ses_and_gmfs): gmf_cache = compute_gmf_cache( hc, gsims, ruptures, rupture_ids) with EnginePerformanceMonitor('saving gmfs', job_id, ses_and_gmfs): _save_gmfs(ses, gmf_cache, site_collection)
def test_point_sources(self): sources = [ openquake.hazardlib.source.PointSource(source_id='point1', name='point1', tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST, mfd=openquake.hazardlib.mfd.EvenlyDiscretizedMFD(min_mag=4, bin_width=1, occurrence_rates=[5]), nodal_plane_distribution=openquake.hazardlib.pmf.PMF([ (1, openquake.hazardlib.geo.NodalPlane(strike=0.0, dip=90.0, rake=0.0)) ]), hypocenter_distribution=openquake.hazardlib.pmf.PMF([(1, 10)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship = openquake.hazardlib.scalerel.PeerMSR(), rupture_aspect_ratio=2, rupture_mesh_spacing=1.0, location=Point(10, 10) ), openquake.hazardlib.source.PointSource(source_id='point2', name='point2', tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST, mfd=openquake.hazardlib.mfd.EvenlyDiscretizedMFD(min_mag=4, bin_width=2, occurrence_rates=[5, 6, 7]), nodal_plane_distribution=openquake.hazardlib.pmf.PMF([ (1, openquake.hazardlib.geo.NodalPlane(strike=0, dip=90, rake=0.0)), ]), hypocenter_distribution=openquake.hazardlib.pmf.PMF([(1, 10)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship = openquake.hazardlib.scalerel.PeerMSR(), rupture_aspect_ratio=2, rupture_mesh_spacing=1.0, location=Point(10, 11) ), ] sites = [openquake.hazardlib.site.Site(Point(11, 10), 1, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 16), 2, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 10.6), 3, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 10.7), 4, True, 2, 3)] sitecol = openquake.hazardlib.site.SiteCollection(sites) from openquake.hazardlib.gsim.sadigh_1997 import SadighEtAl1997 gsims = {const.TRT.ACTIVE_SHALLOW_CRUST: SadighEtAl1997()} truncation_level = 1 time_span = 1.0 imts = {openquake.hazardlib.imt.PGA(): [0.1, 0.5, 1.3]} from openquake.hazardlib.calc import filters source_site_filter = self.SitesCounterSourceFilter( filters.source_site_distance_filter(30) ) rupture_site_filter = self.SitesCounterRuptureFilter( filters.rupture_site_distance_filter(30) ) hazard_curves_poissonian( iter(sources), sitecol, imts, time_span, gsims, truncation_level, source_site_filter=source_site_filter, rupture_site_filter=rupture_site_filter ) # there are two sources and four sites. first source should # be filtered completely since it is too far from all the sites. # the second one should take only three sites -- all except (10, 16). # it generates three ruptures with magnitudes 4, 6 and 8, from which # the first one doesn't affect any of sites and should be ignored, # second only affects site (10, 10.7) and the last one affects all # three. self.assertEqual(source_site_filter.counts, [('point2', [1, 3, 4])]) self.assertEqual(rupture_site_filter.counts, [(6, [4]), (8, [1, 3, 4])])
def test_point_sources(self): sources = [ openquake.hazardlib.source.PointSource( source_id='point1', name='point1', tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST, mfd=openquake.hazardlib.mfd.EvenlyDiscretizedMFD( min_mag=4, bin_width=1, occurrence_rates=[5] ), nodal_plane_distribution=openquake.hazardlib.pmf.PMF([ (1, openquake.hazardlib.geo.NodalPlane(strike=0.0, dip=90.0, rake=0.0)) ]), hypocenter_distribution=openquake.hazardlib.pmf.PMF([(1, 10)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship= openquake.hazardlib.scalerel.PeerMSR(), rupture_aspect_ratio=2, rupture_mesh_spacing=1.0, location=Point(10, 10) ), openquake.hazardlib.source.PointSource( source_id='point2', name='point2', tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST, mfd=openquake.hazardlib.mfd.EvenlyDiscretizedMFD( min_mag=4, bin_width=2, occurrence_rates=[5, 6, 7] ), nodal_plane_distribution=openquake.hazardlib.pmf.PMF([ (1, openquake.hazardlib.geo.NodalPlane(strike=0, dip=90, rake=0.0)), ]), hypocenter_distribution=openquake.hazardlib.pmf.PMF([(1, 10)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship= openquake.hazardlib.scalerel.PeerMSR(), rupture_aspect_ratio=2, rupture_mesh_spacing=1.0, location=Point(10, 11) ), ] sites = [openquake.hazardlib.site.Site(Point(11, 10), 1, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 16), 2, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 10.6), 3, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 10.7), 4, True, 2, 3)] sitecol = openquake.hazardlib.site.SiteCollection(sites) from openquake.hazardlib.gsim.sadigh_1997 import SadighEtAl1997 gsims = {const.TRT.ACTIVE_SHALLOW_CRUST: SadighEtAl1997()} truncation_level = 1 time_span = 1.0 imts = {openquake.hazardlib.imt.PGA(): [0.1, 0.5, 1.3]} from openquake.hazardlib.calc import filters source_site_filter = self.SitesCounterSourceFilter( filters.source_site_distance_filter(30) ) rupture_site_filter = self.SitesCounterRuptureFilter( filters.rupture_site_distance_filter(30) ) hazard_curves_poissonian( iter(sources), sitecol, imts, time_span, gsims, truncation_level, source_site_filter=source_site_filter, rupture_site_filter=rupture_site_filter ) # there are two sources and four sites. first source should # be filtered completely since it is too far from all the sites. # the second one should take only three sites -- all except (10, 16). # it generates three ruptures with magnitudes 4, 6 and 8, from which # the first one doesn't affect any of sites and should be ignored, # second only affects site (10, 10.7) and the last one affects all # three. self.assertEqual(source_site_filter.counts, [('point2', [1, 3, 4])]) self.assertEqual(rupture_site_filter.counts, [(6, [4]), (8, [1, 3, 4])])