def test_hypolist_but_not_sliplist(self): simple_file = BytesIO(b"""\ <?xml version='1.0' encoding='utf-8'?> <nrml xmlns:gml="http://www.opengis.net/gml" xmlns="http://openquake.org/xmlns/nrml/0.4"> <sourceModel name="Some Source Model"> <simpleFaultSource id="3" name="Mount Diablo Thrust" tectonicRegion="Active Shallow Crust" > <simpleFaultGeometry> <gml:LineString> <gml:posList> -121.8229 37.7301 -122.0388 37.8771 </gml:posList> </gml:LineString> <dip> 45.0 </dip> <upperSeismoDepth> 10.0 </upperSeismoDepth> <lowerSeismoDepth> 20.0 </lowerSeismoDepth> </simpleFaultGeometry> <magScaleRel> WC1994 </magScaleRel> <ruptAspectRatio> 1.5 </ruptAspectRatio> <incrementalMFD binWidth="0.1" minMag="5.0" > <occurRates> 0.0010614989 0.00088291627 0.00073437777 0.0006108288 0.0005080653 </occurRates> </incrementalMFD> <rake> 30.0 </rake> <hypoList> <hypo alongStrike="0.25" downDip="0.25" weight="0.3"/> <hypo alongStrike="0.75" downDip="0.75" weight="0.7"/> </hypoList> </simpleFaultSource> </sourceModel> </nrml> """) # check that the error raised by hazardlib is wrapped correctly msg = ('node simpleFaultSource: hypo_list and slip_list have to be ' 'both given') with self.assertRaises(ValueError) as ctx: parse_source_model(simple_file, self.converter) self.assertIn(msg, str(ctx.exception))
def test_hypolist_but_not_sliplist(self): simple_file = StringIO("""\ <?xml version='1.0' encoding='utf-8'?> <nrml xmlns:gml="http://www.opengis.net/gml" xmlns="http://openquake.org/xmlns/nrml/0.4"> <sourceModel name="Some Source Model"> <simpleFaultSource id="3" name="Mount Diablo Thrust" tectonicRegion="Active Shallow Crust" > <simpleFaultGeometry> <gml:LineString> <gml:posList> -121.8229 37.7301 -122.0388 37.8771 </gml:posList> </gml:LineString> <dip> 45.0 </dip> <upperSeismoDepth> 10.0 </upperSeismoDepth> <lowerSeismoDepth> 20.0 </lowerSeismoDepth> </simpleFaultGeometry> <magScaleRel> WC1994 </magScaleRel> <ruptAspectRatio> 1.5 </ruptAspectRatio> <incrementalMFD binWidth="0.1" minMag="5.0" > <occurRates> 0.0010614989 0.00088291627 0.00073437777 0.0006108288 0.0005080653 </occurRates> </incrementalMFD> <rake> 30.0 </rake> <hypoList> <hypo alongStrike="0.25" downDip="0.25" weight="0.3"/> <hypo alongStrike="0.75" downDip="0.75" weight="0.7"/> </hypoList> </simpleFaultSource> </sourceModel> </nrml> """) # check that the error raised by hazardlib is wrapped correctly msg = ('node simpleFaultSource: hypo_list and slip_list have to be ' 'both given') with self.assertRaises(ValueError) as ctx: parse_source_model(simple_file, self.converter) self.assertIn(msg, str(ctx.exception))
def test(self): nrml_to_hazardlib = source_input.NrmlHazardlibConverter( investigation_time=50., rupture_mesh_spacing=1, # km width_of_mfd_bin=0.1, # for Truncated GR MFDs area_source_discretization=10.) with self.assertRaises(source_input.DuplicateID): source_input.parse_source_model( INVALID_SRC_MODEL, nrml_to_hazardlib)
def test_duplicate_id(self): converter = s.SourceConverter( investigation_time=50., rupture_mesh_spacing=1, width_of_mfd_bin=0.1, area_source_discretization=10, ) with self.assertRaises(s.DuplicateID): s.parse_source_model(DUPLICATE_ID_SRC_MODEL, converter)
def test_duplicate_id(self): converter = s.SourceConverter( investigation_time=50., rupture_mesh_spacing=1, width_of_mfd_bin=0.1, area_source_discretization=10, ) with self.assertRaises(s.DuplicateID): s.parse_source_model( DUPLICATE_ID_SRC_MODEL, converter)
def test_duplicate_id(self): converter = s.SourceConverter( # different from self.converter investigation_time=50., rupture_mesh_spacing=1, complex_fault_mesh_spacing=1, width_of_mfd_bin=0.1, area_source_discretization=10, ) with self.assertRaises(DuplicatedID): parse_source_model(DUPLICATE_ID_SRC_MODEL, converter)
def test_duplicate_id(self): converter = s.SourceConverter( # different from self.converter investigation_time=50., rupture_mesh_spacing=1, complex_fault_mesh_spacing=1, width_of_mfd_bin=0.1, area_source_discretization=10, ) with self.assertRaises(DuplicatedID): parse_source_model( DUPLICATE_ID_SRC_MODEL, converter)
def from_model_files(cls, limits, input_model, investigation_time=1.0, simple_mesh_spacing=1.0, complex_mesh_spacing=5.0, mfd_width=0.1, area_discretisation=10.0): """ Reads the hazard model from a file :param list limits: Grid configuration [west, east, xspc, south, north, yspc, upper, lower, zspc] :param str input_model: Path to input source model :param float investigation_time: Investigation time of Poisson model :param float simple_mesh_spacing: Rupture mesh spacing of simple fault (km) :param float complex_mesh_spacing: Rupture mesh spacing of complex fault (km) :param float mfd_width: Spacing (in magnitude units) of MFD :param float area_discretisation: Spacing of discretisation of area source (km) """ converter = SourceConverter(investigation_time, simple_mesh_spacing, complex_mesh_spacing, mfd_width, area_discretisation) full_model = parse_source_model(input_model, converter) sources = [] for model in full_model: sources.extend(list(model.sources)) return cls(limits, sources, area_discretisation)
def initialize_sources(self): """ Parse source models and validate source logic trees. It also filters the sources far away and apply uncertainties to the relevant ones. Notice that sources are automatically split. :returns: a list with the number of sources for each source model """ logs.LOG.progress("initializing sources") self.source_model_lt = logictree.SourceModelLogicTree.from_hc(self.hc) sm_paths = distinct(self.source_model_lt) nrml_to_hazardlib = source.SourceConverter( self.hc.investigation_time, self.hc.rupture_mesh_spacing, self.hc.width_of_mfd_bin, self.hc.area_source_discretization, ) # define an ordered dictionary trt_model_id -> SourceCollector self.source_collector = collections.OrderedDict() for i, (sm, weight, smpath) in enumerate(sm_paths): fname = os.path.join(self.hc.base_path, sm) apply_unc = self.source_model_lt.make_apply_uncertainties(smpath) try: source_collectors = source.parse_source_model( fname, nrml_to_hazardlib, apply_unc) except ValueError as e: if str(e) == ('Surface does not conform with Aki & ' 'Richards convention'): raise InvalidFile('''\ %s: %s. Probably you are using an obsolete model. In that case you can fix the file with the command python -m openquake.engine.tools.correct_complex_sources %s ''' % (fname, e, fname)) else: raise trts = [sc.trt for sc in source_collectors] self.source_model_lt.tectonic_region_types.update(trts) lt_model = models.LtSourceModel.objects.create( hazard_calculation=self.hc, sm_lt_path=smpath, ordinal=i, sm_name=sm, weight=weight) if self.hc.inputs.get('gsim_logic_tree'): # check TRTs gsims_by_trt = lt_model.make_gsim_lt(trts).values else: gsims_by_trt = {} # save TrtModels for each tectonic region type for sc in source_collectors: # NB: the source_collectors are ordered by number of sources # and lexicographically, so the models are in the right order trt_model_id = models.TrtModel.objects.create( lt_model=lt_model, tectonic_region_type=sc.trt, num_sources=len(sc.sources), num_ruptures=sc.num_ruptures, min_mag=sc.min_mag, max_mag=sc.max_mag, gsims=gsims_by_trt.get(sc.trt, [])).id self.source_collector[trt_model_id] = sc
def get_source_model(source_file, inv_time=50.0, simple_mesh_spacing=1.0, complex_mesh_spacing=10.0, mfd_spacing=0.1, area_discretisation=10.0): conv = SourceConverter( inv_time, simple_mesh_spacing, complex_mesh_spacing, mfd_spacing, area_discretisation) return parse_source_model(source_file, conv)
def get_source_model(source_file, inv_time=50.0, simple_mesh_spacing=1.0, complex_mesh_spacing=10.0, mfd_spacing=0.1, area_discretisation=10.0): conv = SourceConverter(inv_time, simple_mesh_spacing, complex_mesh_spacing, mfd_spacing, area_discretisation) return parse_source_model(source_file, conv)
def setUpClass(cls): cls.converter = s.SourceConverter( investigation_time=50., rupture_mesh_spacing=1, # km complex_fault_mesh_spacing=1, # km width_of_mfd_bin=1., # for Truncated GR MFDs area_source_discretization=1.) cls.source_collector = dict((sc.trt, sc) for sc in parse_source_model( MIXED_SRC_MODEL, cls.converter, lambda src: None)) cls.sitecol = site.SiteCollection(cls.SITES)
def setUpClass(cls): cls.converter = s.SourceConverter( investigation_time=50., rupture_mesh_spacing=1, # km width_of_mfd_bin=1., # for Truncated GR MFDs area_source_discretization=1.) cls.source_collector = dict( (sc.trt, sc) for sc in s.parse_source_model( MIXED_SRC_MODEL, cls.converter, lambda src: None)) cls.sitecol = site.SiteCollection(cls.SITES)
def initialize_sources(self): """ Parse source models and validate source logic trees. It also filters the sources far away and apply uncertainties to the relevant ones. Notice that sources are automatically split. :returns: a list with the number of sources for each source model """ logs.LOG.progress("initializing sources") self.source_model_lt = logictree.SourceModelLogicTree.from_hc(self.hc) sm_paths = distinct(self.source_model_lt) nrml_to_hazardlib = source.NrmlHazardlibConverter( self.hc.investigation_time, self.hc.rupture_mesh_spacing, self.hc.width_of_mfd_bin, self.hc.area_source_discretization, ) # define an ordered dictionary trt_model_id -> SourceCollector self.source_collector = collections.OrderedDict() for i, (sm, weight, smpath) in enumerate(sm_paths): fname = os.path.join(self.hc.base_path, sm) apply_unc = self.source_model_lt.make_apply_uncertainties(smpath) source_collectors = source.parse_source_model( fname, nrml_to_hazardlib, apply_unc) trts = [sc.trt for sc in source_collectors] self.source_model_lt.tectonic_region_types.update(trts) lt_model = models.LtSourceModel.objects.create( hazard_calculation=self.hc, sm_lt_path=smpath, ordinal=i, sm_name=sm, weight=weight) # save TrtModels for each tectonic region type gsims_by_trt = lt_model.make_gsim_lt(trts).values for sc in source_collectors: if not sc.trt in gsims_by_trt: gsim_file = self.hc.inputs['gsim_logic_tree'] raise ValueError( "Found in %r a tectonic region type %r inconsistent " "with the ones in %r" % (sm, sc.trt, gsim_file)) # NB: the source_collectors are ordered by number of sources # and lexicographically, so the models are in the right order trt_model_id = models.TrtModel.objects.create( lt_model=lt_model, tectonic_region_type=sc.trt, num_sources=len(sc.sources), num_ruptures=sc.num_ruptures, min_mag=sc.min_mag, max_mag=sc.max_mag, gsims=gsims_by_trt[sc.trt]).id self.source_collector[trt_model_id] = sc
def get_source_models(oqparam, source_model_lt, sitecol=None, in_memory=True): """ Build all the source models generated by the logic tree. :param oqparam: an :class:`openquake.commonlib.oqvalidation.OqParam` instance :param source_model_lt: a :class:`openquake.commonlib.logictree.SourceModelLogicTree` instance :param in_memory: if True, keep in memory the sources, else just collect the TRTs :returns: an iterator over :class:`openquake.commonlib.source.SourceModel` tuples """ converter = sourceconverter.SourceConverter( oqparam.investigation_time, oqparam.rupture_mesh_spacing, oqparam.complex_fault_mesh_spacing, oqparam.width_of_mfd_bin, oqparam.area_source_discretization) # consider only the effective realizations rlzs = logictree.get_effective_rlzs(source_model_lt) samples_by_lt_path = source_model_lt.samples_by_lt_path() for i, rlz in enumerate(rlzs): sm = rlz.value # name of the source model smpath = rlz.lt_path num_samples = samples_by_lt_path[smpath] if num_samples > 1: logging.warn('The source path %s was sampled %d times', smpath, num_samples) fname = possibly_gunzip(os.path.join(oqparam.base_path, sm)) if in_memory: apply_unc = source_model_lt.make_apply_uncertainties(smpath) try: trt_models = source.parse_source_model( fname, converter, apply_unc) except ValueError as e: if str(e) in ('Surface does not conform with Aki & ' 'Richards convention', 'Edges points are not in the right order'): raise InvalidFile('''\ %s: %s. Probably you are using an obsolete model. In that case you can fix the file with the command python -m openquake.engine.tools.correct_complex_sources %s ''' % (fname, e, fname)) else: raise else: # just collect the TRT models smodel = read_nodes(fname, lambda el: 'sourceModel' in el.tag, source.nodefactory['sourceModel']).next() trt_models = source.TrtModel.collect(smodel) trts = [mod.trt for mod in trt_models] source_model_lt.tectonic_region_types.update(trts) gsim_file = oqparam.inputs.get('gsim_logic_tree') if gsim_file: # check TRTs gsim_lt = get_gsim_lt(oqparam, trts) for trt_model in trt_models: if trt_model.trt not in gsim_lt.values: raise ValueError( "Found in %r a tectonic region type %r inconsistent " "with the ones in %r" % (sm, trt_model.trt, gsim_file)) trt_model.gsims = gsim_lt.values[trt_model.trt] else: gsim_lt = logictree.DummyGsimLogicTree() weight = rlz.weight / num_samples yield source.SourceModel( sm, weight, smpath, trt_models, gsim_lt, i, num_samples)
def get_source_models(oqparam, source_model_lt, sitecol=None, in_memory=True): """ Build all the source models generated by the logic tree. :param oqparam: an :class:`openquake.commonlib.oqvalidation.OqParam` instance :param source_model_lt: a :class:`openquake.commonlib.logictree.SourceModelLogicTree` instance :param in_memory: if True, keep in memory the sources, else just collect the TRTs :returns: an iterator over :class:`openquake.commonlib.source.SourceModel` tuples """ converter = sourceconverter.SourceConverter( oqparam.investigation_time, oqparam.rupture_mesh_spacing, oqparam.complex_fault_mesh_spacing, oqparam.width_of_mfd_bin, oqparam.area_source_discretization) # consider only the effective realizations rlzs = logictree.get_effective_rlzs(source_model_lt) samples_by_lt_path = source_model_lt.samples_by_lt_path() for i, rlz in enumerate(rlzs): sm = rlz.value # name of the source model smpath = rlz.lt_path num_samples = samples_by_lt_path[smpath] if num_samples > 1: logging.warn('The source path %s was sampled %d times', smpath, num_samples) fname = possibly_gunzip(os.path.join(oqparam.base_path, sm)) if in_memory: apply_unc = source_model_lt.make_apply_uncertainties(smpath) try: trt_models = source.parse_source_model(fname, converter, apply_unc) except ValueError as e: if str(e) in ('Surface does not conform with Aki & ' 'Richards convention', 'Edges points are not in the right order'): raise InvalidFile('''\ %s: %s. Probably you are using an obsolete model. In that case you can fix the file with the command python -m openquake.engine.tools.correct_complex_sources %s ''' % (fname, e, fname)) else: raise else: # just collect the TRT models smodel = next( read_nodes(fname, lambda el: 'sourceModel' in el.tag, source.nodefactory['sourceModel'])) trt_models = source.TrtModel.collect(smodel) trts = [mod.trt for mod in trt_models] source_model_lt.tectonic_region_types.update(trts) gsim_file = oqparam.inputs.get('gsim_logic_tree') if gsim_file: # check TRTs gsim_lt = get_gsim_lt(oqparam, trts) for trt_model in trt_models: if trt_model.trt not in gsim_lt.values: raise ValueError( "Found in %r a tectonic region type %r inconsistent " "with the ones in %r" % (sm, trt_model.trt, gsim_file)) trt_model.gsims = gsim_lt.values[trt_model.trt] else: gsim_lt = logictree.DummyGsimLogicTree() weight = rlz.weight / num_samples yield source.SourceModel(sm, weight, smpath, trt_models, gsim_lt, i, num_samples, None)