def test_is_writeable(self): parser = SourceModelParser(SourceConverter(50., 1., 10, 0.1, 10.)) groups = [copy.deepcopy(grp) for grp in parser.parse_groups(ALT_MFDS)] # there are a SimpleFaultSource and a CharacteristicFaultSource fd, fname = tempfile.mkstemp(suffix='.xml') with os.fdopen(fd, 'wb'): write_source_model(fname, groups, 'Test Source Model')
def main(fname_config, label, edges_folder, out_file, *, resampling=None): """ Creates the .xml input for the interface sources """ create_folder(os.path.dirname(out_file)) # check edges folder assert os.path.exists(edges_folder) # Read the config file config = toml.load(fname_config) # Create .xml es = EdgesSet.from_files(edges_folder) src = es.get_complex_fault(section_length=float(resampling)) binw = config['bin_width'] agr = config['sources'][label]['agr'] bgr = config['sources'][label]['bgr'] mmin = config['mmin'] mmax = config['sources'][label]['mmax'] mfd = TruncatedGRMFD(min_mag=mmin, max_mag=mmax, bin_width=binw, a_val=agr, b_val=bgr) src.mfd = mfd src.rupture_mesh_spacing = 10.0 write_source_model(out_file, [src], 'Name')
def test_is_writeable(self): parser = SourceModelParser(SourceConverter(50., 1., 10, 0.1, 10.)) groups = [copy.deepcopy(grp) for grp in parser.parse_groups(ALT_MFDS)] # there are a SimpleFaultSource and a CharacteristicFaultSource fd, fname = tempfile.mkstemp(suffix='.xml') with os.fdopen(fd, 'wb'): write_source_model(fname, groups, 'Test Source Model')
def test_is_writeable(self): groups = [copy.deepcopy(grp) for grp in nrml.to_python(ALT_MFDS, conv)] # there are a SimpleFaultSource and a CharacteristicFaultSource fd, fname = tempfile.mkstemp(suffix='.xml') with os.fdopen(fd, 'wb'): write_source_model(fname, groups, 'Test Source Model')
def write_as_set_point_sources(df, model, src_id, module, subzones, model_subz, mmin, bwid, rms, tom, folder_out): srcd = model['sources'][src_id] # Looping over the points name = "" srcs = [] for idx, pnt in df.iterrows(): if subzones: srcd_sz = model_subz['sources'][pnt.id] pfx = model.get("source_prefix", "") pfx += "_" if len(pfx) else pfx sid = '{:s}{:s}_{:d}'.format(pfx, src_id, idx) trt = srcd['tectonic_region_type'] msr_str = model['msr'][trt] my_class = getattr(module, msr_str) msr = my_class() # Get mmax and set the MFD mmx = srcd['mmax'] mfd = TruncatedGRMFD(mmin, mmx, bwid, pnt.agr, pnt.bgr) key = 'rupture_aspect_ratio' rar = get_param(srcd, model['default'], key) key = 'upper_seismogenic_depth' usd = get_param(srcd, model['default'], key) key = 'lower_seismogenic_depth' lsd = get_param(srcd, model['default'], key) key = 'nodal_plane_distribution' tmp = get_param(srcd, model['default'], key) npd = _get_nodal_plane_distribution(tmp) key = 'hypocenter_distribution' tmp = get_param(srcd, model['default'], key) hyd = _get_hypocenter_distribution(tmp) if subzones: tmp = get_param(srcd_sz, model['default'], key) npd = _get_nodal_plane_distribution(tmp) loc = Point(pnt.lon, pnt.lat) src = PointSource(sid, name, trt, mfd, rms, msr, rar, tom, usd, lsd, loc, npd, hyd) srcs.append(src) # Write output file fname_out = os.path.join(folder_out, 'src_{:s}.xml'.format(src_id)) write_source_model(fname_out, srcs, 'Zone {:s}'.format(src_id))
def check_round_trip(self, fname): smodel = nrml.to_python(fname, conv) fd, name = tempfile.mkstemp(suffix='.xml') with os.fdopen(fd, 'wb'): write_source_model(name, smodel) with open(name + '.toml', 'w') as f: tomldump(smodel, f) if open(name).read() != open(fname).read(): raise Exception('Different files: %s %s' % (name, fname)) os.remove(name) os.remove(name + '.toml') return smodel
def check_round_trip(self, fname): smodel = nrml.to_python(fname, conv) fd, name = tempfile.mkstemp(suffix='.xml') with os.fdopen(fd, 'wb'): write_source_model(name, smodel) with hdf5.File.temporary() as f: for group in smodel.src_groups: hdf5write(f, group) if open(name).read() != open(fname).read(): raise Exception('Different files: %s %s' % (name, fname)) os.remove(name) return smodel
def create(label, rupture_hdf5_fname, output_folder, investigation_t, trt=TRT.SUBDUCTION_INTRASLAB): """ :param label: A string identifying the source :param rupture_hdf5_fname: Name of the .hdf5 file containing the ruptures :param output_folder: Folder where to write the .xl files :param investigation_t: Investigation time in years :param trt: Tectonic region type label """ # Open the input .hdf5 file with the ruptures f = h5py.File(rupture_hdf5_fname, 'r') if not os.path.exists(output_folder): os.mkdir(output_folder) # Create xml for mag in f['ruptures'].keys(): # Check the number of ruptures defined for the current magnitude value grp = f['ruptures'][mag] if len(grp) < 1: tmps = 'Skipping ruptures for magnitude {:.2f}'.format(float(mag)) logging.warning(tmps) continue # Set the name of the output nrml file fxml = os.path.join(output_folder, '{:s}.xml'.format(mag)) # Set the source ID mags = re.sub('\\.', 'pt', mag) sid = 'src_{:s}_{:s}'.format(label, mags) name = 'Ruptures for mag bin {:s}'.format(mags) # Creates a non-parametric seismic source src = create_source(grp, float(mag), sid, name, trt) # Create source group sgrp = SourceGroup(trt, [src]) # Create source model name = 'Source model for {:s} magnitude {:s}'.format(label, mags) mdl = SourceModel([sgrp], name, investigation_t) # Write source model write_source_model(fxml, mdl, mag) f.close()
def complex_fault_src_from_edges(edges_folder, out_nrml='source.xml'): """ :param edges_folder: :param out_nrml: """ # check edges folder assert os.path.exists(edges_folder) # Create .xml es = EdgesSet.from_files(edges_folder) src = es.get_complex_fault() write_source_model(out_nrml, [src], 'Name')
def check_round_trip(self, fname): parser = SourceModelParser(SourceConverter(50., 1., 10, 0.1, 10.)) groups = parser.parse_src_groups(fname) fd, name = tempfile.mkstemp(suffix='.xml') with os.fdopen(fd, 'wb'): write_source_model(name, groups, 'Test Source Model') with hdf5.File.temporary() as f: for group in groups: hdf5write(f, group) print('written %s' % f.path) if open(name).read() != open(fname).read(): raise Exception('Different files: %s %s' % (name, fname)) os.remove(name)
def check_round_trip(self, fname): parser = SourceModelParser(SourceConverter(50., 1., 10, 0.1, 10.)) groups = parser.parse_src_groups(fname) fd, name = tempfile.mkstemp(suffix='.xml') with os.fdopen(fd, 'wb'): write_source_model(name, groups, 'Test Source Model') with hdf5.File.temporary() as f: for group in groups: hdf5write(f, group) print('written %s' % f.path) if open(name).read() != open(fname).read(): raise Exception('Different files: %s %s' % (name, fname)) os.remove(name)
def serialise_to_nrml(self, filename, use_defaults=False): ''' Writes the source model to a nrml source model file given by the filename :param str filename: Path to output file :param bool use_defaults: Boolean to indicate whether to use default values (True) or not. If set to False, ValueErrors will be raised when an essential attribute is missing. ''' source_model = self.convert_to_oqhazardlib( PoissonTOM(1.0), 2.0, 2.0, 10.0, use_defaults=use_defaults) write_source_model(filename, source_model, name=self.name)
def test_case_65(self): # reading/writing a multiFaultSource oq = readinput.get_oqparam('job.ini', pkg=case_65) csm = readinput.get_composite_source_model(oq) tmpname = general.gettemp() out = write_source_model(tmpname, csm.src_groups) self.assertEqual(out[0], tmpname) self.assertEqual(out[1], tmpname[:-4] + '_sections.xml') # running the calculation self.run_calc(case_65.__file__, 'job.ini') [f] = export(('hcurves/mean', 'csv'), self.calc.datastore) self.assertEqualFiles('expected/hcurve-mean.csv', f, delta=1E-4) # make sure we are not breaking event_based self.run_calc(case_65.__file__, 'job.ini', calculation_mode='event_based', ses_per_logic_tree_path=100) [f] = export(('ruptures', 'csv'), self.calc.datastore) self.assertEqualFiles('expected/ruptures.csv', f, delta=1E-4) rups = extract(self.calc.datastore, 'ruptures') csv = general.gettemp(rups.array) self.assertEqualFiles('expected/full_ruptures.csv', csv, delta=1E-4) files = export(('gmf_data', 'csv'), self.calc.datastore) self.assertEqualFiles('expected/gmf_data.csv', files[0], delta=1E-4)
def serialise_to_nrml(self, filename, use_defaults=False): ''' Writes the source model to a nrml source model file given by the filename :param str filename: Path to output file :param bool use_defaults: Boolean to indicate whether to use default values (True) or not. If set to False, ValueErrors will be raised when an essential attribute is missing. ''' source_model = self.convert_to_oqhazardlib( PoissonTOM(1.0), 2.0, 2.0, 10.0, use_defaults=use_defaults) write_source_model(filename, source_model, name=self.name)
def create(label, rupture_hdf5_fname, output_folder, investigation_t): """ :param label: :param rupture_hdf5_fname: :param output_folder: """ # # f = h5py.File(rupture_hdf5_fname, 'r') if not os.path.exists(output_folder): os.mkdir(output_folder) # # trt = TRT.SUBDUCTION_INTRASLAB for mag in f['ruptures'].keys(): # # check the number of ruptures defined for the current magnitude value grp = f['ruptures'][mag] if len(grp) < 1: tmps = 'Skipping ruptures for magnitude {:.2f}'.format(float(mag)) print(tmps) logging.warning(tmps) continue # # set the name of the output nrml file fnrml = os.path.join(output_folder, '{:s}.nrml'.format(mag)) # # source ID mags = re.sub('\\.', 'pt', mag) sid = 'src_{:s}_{:s}'.format(label, mags) name = 'Ruptures for mag bin {:s}'.format(mags) # # creates a non-parametric seismic source src = create_nrml_source(grp, float(mag), sid, name, trt) # # create source group sgrp = SourceGroup(trt, [src]) # # create source model name = 'Source model for {:s} magnitude {:s}'.format(label, mags) mdl = SourceModel([sgrp], name, investigation_t) # # write source model write_source_model(fnrml, mdl, mag) f.close() print('Done')
def build_model_from_db(fault_db, xml_output=None, width_method='length_scaling', oqt_source=False, project_name=None, param_map=None, defaults=None, **kwargs): param_map_local = deepcopy(fmu.param_map) defaults_local = deepcopy(fmu.defaults) if param_map is not None: param_map_local.update(param_map) if defaults is not None: defaults_local.update(defaults) for key in kwargs: defaults_local[key] = kwargs[key] srcl = [] for fl in fault_db.db: try: sfs_dict = fmu.construct_sfs_dict(fl, width_method=width_method, param_map=param_map_local, defaults=defaults_local) print("sfs_dict = ", sfs_dict) sfs = fmu.make_fault_source(sfs_dict, oqt_source=oqt_source) print("sfs en build_model_from_db = ", sfs) srcl.append(sfs) except Exception as e: if param_map: id = fl[param_map['source_id']] print("Couldn't process Fault {}: {}".format(id, e)) else: raise if xml_output is not None: # Write the final fault model write_source_model(xml_output, srcl, project_name) else: return srcl
def df2nrml(df, model_name): ''' Write pandas DataFrame of source models to NRML. Sources are twinned by magnitude to support alternative tectonic region types for large-magnitude events. ''' if model_name.endswith('.xml'): model_name = model_name[:-4] nrml_file = model_name.replace(' ', '_') + '.xml' aseismic = df.a == 0 if any(aseismic): print('Dropping zones with no seismicity from NRML: ' + ', '.join(str(item) for item in df.loc[aseismic].index)) df = df.loc[~aseismic].copy() df = add_name_id(df) df = twin_source_by_magnitude(df) _check_columns(df) df = natural_sort(df, by='id') # this may do nothing ... source_list = source_df_to_list(df) source_model = mtkSourceModel(name=model_name, sources=source_list) source_model = source_model.convert_to_oqhazardlib(tom.PoissonTOM(1.0)) # apply per-zone discretization for item in source_model: try: item.area_discretization = df.loc[df.id == item.source_id, 'discretization'].squeeze() except KeyError: pass print('Writing: %s' % os.path.abspath(nrml_file)) write_source_model(nrml_file, source_model, name=model_name) return source_model
def remove_buffer_around_faults(fname: str, path_point_sources: str, out_path: str, dst: float): """ Remove the seismicity above a magnitude threshold for all the point sources within a buffer around faults. :param fname: The name of the file with the fault sources in .xml format :param path_point_sources: The pattern to select the .xml files of the point sources e.g. `./../m01_asc/oq/zones/src_*.xml` :param out_path: The path where to write the output .xml file :param dst: The distance in km of the buffer :returns: A .xml file with the ajusted point sources """ # Load fault sources in the SAM models binw = 0.1 sourceconv = SourceConverter(investigation_time=1.0, rupture_mesh_spacing=5.0, complex_fault_mesh_spacing=5.0, width_of_mfd_bin=binw) ssm_faults = to_python(fname, sourceconv) # Loading all the point sources in the NEW SAM model coo_pnt_src = [] pnt_srcs = [] for fname in glob.glob(path_point_sources): tssm = to_python(fname, sourceconv) tcoo = np.array([(p.location.longitude, p.location.latitude) for p in tssm[0]]) pnt_srcs.extend(tssm[0]) coo_pnt_src.extend(tcoo) coo_pnt_src = np.array(coo_pnt_src) # Getting the list of faults faults = [] for grp in ssm_faults: for s in grp: faults.append(s) # Processing faults for src in faults: # Getting the subset of point sources in the surrounding of the fault pnt_ii, sel_pnt_srcs, sel_pnt_coo, rrup = get_data( src, coo_pnt_src, pnt_srcs) if pnt_ii is not None: within_idx = np.nonzero(rrup < dst)[0] for isrc in within_idx: pnt_srcs[pnt_ii[isrc]].mfd.max_mag = 6.5 sel_pnt_srcs[isrc].mfd.max_mag = 6.5 else: continue # Fault occurrences ocf = np.array(src.mfd.get_annual_occurrence_rates()) fname_out = os.path.join(out_path, "points_ssm.xml") write_source_model(fname_out, pnt_srcs, 'Distributed seismicity') print('Created: {:s}'.format(fname_out))
def create_nrml_sources(fname_input_pattern: str, fname_config: str, folder_out: str, fname_subzone_shp: str="", fname_subzone_config: str=""): create_folder(folder_out) # If true we take some of the information from subzones subzones = (len(fname_subzone_shp) > 0 and len(fname_subzone_config) > 0) if subzones: polygons_gdf = gpd.read_file(fname_subzone_shp) model_subz = toml.load(fname_subzone_config) # This is used to instantiate the MSR module = importlib.import_module('openquake.hazardlib.scalerel') # Parsing config model = toml.load(fname_config) rms = model['rupture_mesh_spacing'] mmin = model['mmin'] bwid = model['bin_width'] tom = PoissonTOM(1.0) # Processing files for fname in glob(fname_input_pattern): src_id = os.path.basename(fname).split('.')[0] rc_id = _get_src_id(fname) df = pd.read_csv(fname) # Create a geodataframe with the points in a given zone if subzones: # Create a geodataframe with points geom = [PointShapely(xy) for xy in zip(df.lon, df.lat)] gdf = gpd.GeoDataFrame(df, crs='epsg:4326', geometry=geom) # Select subzones within a zone tdf = polygons_gdf[polygons_gdf["parent"] == src_id] # Should contain the points within df = gpd.sjoin(gdf, tdf, op='within') # This is the information on the source in the config file srcd = model['sources'][src_id] # Looping over the points srcs = [] for idx, pnt in df.iterrows(): if subzones: srcd_sz = model_subz['sources'][pnt.id] pfx = model.get("source_prefix", "") pfx += "_" if len(pfx) else pfx sid = '{:s}{:s}_{:d}'.format(pfx, src_id, idx) name = "" trt = srcd['tectonic_region_type'] msr_str = model['msr'][trt] my_class = getattr(module, msr_str) msr = my_class() # Get mmax and set the MFD mmx = srcd['mmax'] mfd = TruncatedGRMFD(mmin, mmx, bwid, pnt.agr, pnt.bgr) key = 'rupture_aspect_ratio' rar = get_param(srcd, model['default'], key) key = 'upper_seismogenic_depth' usd = get_param(srcd, model['default'], key) key = 'lower_seismogenic_depth' lsd = get_param(srcd, model['default'], key) key = 'nodal_plane_distribution' tmp = get_param(srcd, model['default'], key) npd = _get_nodal_plane_distribution(tmp) key = 'hypocenter_distribution' tmp = get_param(srcd, model['default'], key) hyd = _get_hypocenter_distribution(tmp) if subzones: tmp = get_param(srcd_sz, model['default'], key) npd = _get_nodal_plane_distribution(tmp) loc = Point(pnt.lon, pnt.lat) src = PointSource(sid, name, trt, mfd, rms, msr, rar, tom, usd, lsd, loc, npd, hyd) srcs.append(src) # Write output file fname_out = os.path.join(folder_out, 'src_{:s}.xml'.format(src_id)) write_source_model(fname_out, srcs, 'Zone {:s}'.format(src_id))
def write_as_multipoint_sources(df, model, src_id, module, subzones, model_subz, mmin, bwid, rms, tom, folder_out): # We do not support subzones in this case assert subzones is False srcd = model['sources'][src_id] # Prefix pfx = model.get("source_prefix", "") pfx += "_" if len(pfx) else pfx # Looping over the points lons = [] lats = [] avals = [] settings = False for idx, pnt in df.iterrows(): # Get mmax and set the MFD mmx = srcd['mmax'] avals.append(pnt.agr) lons.append(pnt.lon) lats.append(pnt.lat) if not settings: trt = srcd['tectonic_region_type'] msr_str = model['msr'][trt] my_class = getattr(module, msr_str) msr = my_class() key = 'rupture_aspect_ratio' rar = get_param(srcd, model['default'], key) key = 'upper_seismogenic_depth' usd = get_param(srcd, model['default'], key) key = 'lower_seismogenic_depth' lsd = get_param(srcd, model['default'], key) key = 'nodal_plane_distribution' tmp = get_param(srcd, model['default'], key) npd = _get_nodal_plane_distribution(tmp) key = 'hypocenter_distribution' tmp = get_param(srcd, model['default'], key) hyd = _get_hypocenter_distribution(tmp) name = model['sources'][src_id] mmfd = MultiMFD('truncGutenbergRichterMFD', size=len(avals), min_mag=[mmin], max_mag=[mmx], bin_width=[bwid], b_val=[pnt.bgr], a_val=avals) mesh = Mesh(np.array(lons), np.array(lats)) srcmp = MultiPointSource(src_id, name, trt, mmfd, msr, rar, usd, lsd, npd, hyd, mesh, tom) # Write output file fname_out = os.path.join(folder_out, 'src_{:s}.xml'.format(src_id)) write_source_model(fname_out, [srcmp], 'Zone {:s}'.format(src_id))
def area2pt_source(area_source_file, sources=None, investigation_time=50, rupture_mesh_spacing=10., width_of_mfd_bin=0.1, area_source_discretisation=10., filename=None, nrml_version='04', name=None): """Calls OpenQuake parsers to read area source model from source_mode.xml type file, convert to point sources and write to a new nrml source model file. :params area_source_file: nrml format file of the area source :params discretisation: Grid size (km) for the area source discretisation, which defines the distance between resulting point sources. """ if sources is None: sources = nrml2sourcelist( area_source_file, investigation_time=investigation_time, rupture_mesh_spacing=rupture_mesh_spacing, width_of_mfd_bin=width_of_mfd_bin, area_source_discretisation=area_source_discretisation) if name is None: name = '%s_points' % filename new_pt_sources = {} for source in sources: pt_sources = area_to_point_sources(source) for pt in pt_sources: pt.source_id = pt.source_id.replace(':', '') pt.name = pt.name.replace(':', '_') try: new_pt_sources[pt.tectonic_region_type].append(pt) except KeyError: new_pt_sources[pt.tectonic_region_type] = [pt] # print [method for method in dir(pt) if callable(getattr(pt, method))] # print [attribute for attribute in dir(pt)] nrml_pt_file = area_source_file[:-4] + '_pts.xml' source_group_list = [] id = 0 for trt, sources in new_pt_sources.iteritems(): source_group = SourceGroup(trt, sources=sources, id=id) id += 1 source_group_list.append(source_group) if filename is not None: if nrml_version == '04': source_list = [] for trt, sources in new_pt_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(nrml_pt_file, 'wb') as f: nrml.write([source_model], f, '%s', xmlns=NAMESPACE) # This will write version 0.5 elif nrml_version == '05': write_source_model(nrml_pt_file, source_group_list, name=filename) else: print 'Warning: nrml version not specfied, xml not created' return source_group_list
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')
def write_combined_faults_points(point_sources, fault_sources, filename, name, nrml_version='04'): """Write pts and fault sources to file :param point_sources: list without trt or dict with trt key of point sources """ print 'Writing to source model file %s' % filename ps_id_index = 1 fs_id_index = 1 if nrml_version == '04': if type(point_sources) == dict: source_list = [] for trt, sources in point_sources.iteritems(): for source in sources: source.source_id = 'PS_%i' % ps_id_index source_list.append(source) ps_id_index += 1 # id_index = max(id_index, source.source_id) elif type(point_sources) == list: source_list = point_sources for source in source_list: source.source_id = 'PS_%i' % ps_id_index source_list.append(source) ps_id_index += 1 # id_index = max(id_index, source.source_id) for fault_source in fault_sources: # id_index += 1 fault_source.source_id = "FS_%i" % fs_id_index fs_id_index += 1 source_list.append(fault_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) elif nrml_version == '05': if type(point_sources) == dict: source_group_list = [] id = 0 for trt, sources in point_sources.iteritems(): for source in sources: id_index = max(id_index, source.source_id) for trt, sources in point_sources.iteritems(): for fault_source in fault_sources: if fault_source.tectonic_region_type == trt: id_index += 1 fault_source.source_id = "%i" % id_index sources.append(fault_source) source_group = SourceGroup(trt, sources=sources, id=id) id += 1 source_group_list.append(source_group) write_source_model(filename, source_group_list, name=name) elif type(point_sources) == list: msg = 'Method not yet implemented for nrml version 0.5' raise (msg) else: print 'Warning: nrml version not specfied, xml not created'