Esempio n. 1
0
 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')
Esempio n. 2
0
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')
Esempio n. 3
0
 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')
Esempio n. 4
0
 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))
Esempio n. 6
0
 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
Esempio n. 7
0
 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()
Esempio n. 9
0
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')
Esempio n. 10
0
 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)
Esempio n. 11
0
 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)
Esempio n. 12
0
    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)
Esempio n. 13
0
    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)
Esempio n. 14
0
    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)
Esempio n. 15
0
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')
Esempio n. 16
0
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
Esempio n. 18
0
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))
Esempio n. 21
0
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
Esempio n. 22
0
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')
Esempio n. 23
0
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'