コード例 #1
0
 def testcase01(self):
     config = {'time_distance_window': 'GardnerKnopoffWindow',
               'fs_time_prop': 0.9}
     decluster(catalogue_hmtk_fname=self.catalogue,
               declustering_meth='GardnerKnopoffType1',
               declustering_params=config,
               output_path=self.tmp,
               labels=['a', 'b'],
               tr_fname=self.classification,
               subcatalogues=True,
               fmat='pkl')
     #
     # Read first mainshock catalogue
     a_fname = os.path.join(self.tmp, 'catalogue_dec__a.pkl')
     self.assertTrue(os.path.exists(a_fname))
     cat = _load_catalogue(a_fname)
     self.assertTrue(len(cat.data['magnitude'] == 1))
     self.assertAlmostEqual(cat.data['magnitude'][0], 6.0)
     #
     # Read second mainshock catalogue
     b_fname = os.path.join(self.tmp, 'catalogue_dec__b.pkl')
     self.assertTrue(os.path.exists(b_fname))
     cat = _load_catalogue(b_fname)
     self.assertTrue(len(cat.data['magnitude'] == 1))
     self.assertAlmostEqual(cat.data['magnitude'][0], 6.1)
     #
     # Check that the third mainshock catalogue does not exist
     c_fname = os.path.join(self.tmp, 'catalogue_dec__c.pkl')
     self.assertFalse(os.path.exists(c_fname))
コード例 #2
0
def compute_mmax(fname_input_pattern: str, fname_config: str, label: str):
    """
    This function assignes an mmax value to each source with a catalogue
    file as selected by the provided `fname_input_pattern`.
    """

    if isinstance(fname_input_pattern, str):
        fname_list = glob(fname_input_pattern)
    else:
        fname_list = fname_input_pattern

    # Parsing config
    model = toml.load(fname_config)

    # Processing files
    for fname in sorted(fname_list):

        src_id = _get_src_id(fname)

        # Processing catalogue
        tcat = _load_catalogue(fname)

        if tcat is None or len(tcat.data['magnitude']) < 2:
            continue

        tmp = "{:.5e}".format(np.max(tcat.data['magnitude']))
        model['sources'][src_id]['mmax_{:s}'.format(label)] = float(tmp)

    # Saving results into the config file
    with open(fname_config, 'w') as fou:
        fou.write(toml.dumps(model))
        print('Updated {:s}'.format(fname_config))
コード例 #3
0
def catalogue_declustering(fname: str,
                           output_folder: str,
                           *,
                           subcatalogues: bool = False):
    """
    Decluster a catalogue
    """

    create_folder(output_folder)
    create_folder('./tmp')

    # Create a fake file with the classification. We use a fake classification
    # since earthquakes in this analysis are just from stable crust
    tr_fname = './tmp/fake.hdf5'
    cat = _load_catalogue(fname)
    label = np.ones_like(np.array(cat['magnitude']))
    f = h5py.File(tr_fname, 'w')
    _ = f.create_dataset("undef", data=label)
    f.close()

    labels = ['undef']

    # Declustering with the classical GK algorithm
    declustering_meth = 'GardnerKnopoffType1'
    declustering_params = {
        'time_distance_window': 'GardnerKnopoffWindow',
        'fs_time_prop': 0.9
    }
    out = decluster(fname,
                    declustering_meth,
                    declustering_params,
                    output_folder,
                    labels=labels,
                    tr_fname=tr_fname,
                    subcatalogues=subcatalogues,
                    olab='_gk',
                    save_af=True,
                    fix_defaults=True)

    declustering_meth = 'GardnerKnopoffType1'
    declustering_params = {
        'time_distance_window': 'UhrhammerWindow',
        'fs_time_prop': 0.9
    }
    out = decluster(fname,
                    declustering_meth,
                    declustering_params,
                    output_folder,
                    labels=labels,
                    tr_fname=tr_fname,
                    subcatalogues=subcatalogues,
                    olab='_uh',
                    save_af=True,
                    fix_defaults=True)

    declustering_meth = 'GardnerKnopoffType1'
    declustering_params = {
        'time_distance_window': 'GruenthalWindow',
        'fs_time_prop': 0.9
    }
    _ = decluster(fname,
                  declustering_meth,
                  declustering_params,
                  output_folder,
                  labels=labels,
                  tr_fname=tr_fname,
                  subcatalogues=subcatalogues,
                  olab='_gr',
                  save_af=True,
                  fix_defaults=True)
コード例 #4
0
def main(fname: str, *, example_flag: bool = False):
    """ Compares SES against a catalogue given a .toml configuration file """

    # Print an example of configuration file
    if example_flag:
        print_example()
        exit()

    # Load the .toml file containing the information required
    config_main = toml.load(fname)
    path = os.path.dirname(fname)

    print('Root path: {:s}'.format(path))

    # Read information in the config file
    fname_catalogues = []
    for tmp_name in config_main['main']['catalogues']:
        # If not absolute
        if not re.search('^/', tmp_name):
            tmp_name = os.path.join(path, tmp_name)
            assert os.path.exists(tmp_name)
            print('Catalogue: {:s}'.format(tmp_name))
        fname_catalogues.append(tmp_name)
    calc_id = config_main['main']['calc_id']
    ses_duration = config_main['main']['ses_duration']
    polygon_fname = os.path.join(path, config_main['main']['polygon'])
    output_dir = os.path.join(path, config_main['main']['output_dir'])
    descr = config_main['main']['description']
    binw = config_main['main'].get('bin_width', 0.2)
    min_magnitude = config_main['main'].get('min_magnitude', None)

    if ('tectonic_region' not in config_main['main']
            or config_main['main']['tectonic_region'] in ['', 'none', 'None']):
        tectonic_region = None
    else:
        tectonic_region = int(config_main['main']['tectonic_region'])

    # Checking
    msg = 'The polygon file does not exist:\n{:s}'.format(polygon_fname)
    assert os.path.exists(polygon_fname), msg
    if not os.path.exists(output_dir):
        create_folder(output_dir)

    # Reading ruptures from the datastore
    dstore = read(calc_id)
    dfr = dstore.read_df('ruptures')
    dfr = gpd.GeoDataFrame(dfr,
                           geometry=gpd.points_from_xy(dfr.hypo_0, dfr.hypo_1))
    if tectonic_region is not None:
        dfr = dfr.loc[dfr['trt_smr'] == tectonic_region]

    # Reading geojson polygon and create the shapely geometry
    with open(polygon_fname) as json_file:
        data = json.load(json_file)
    polygon = data['features'][0]['geometry']
    tmp = eval(geoj.dumps(polygon))
    geom = shape(tmp)

    # Get region limits
    coo = []
    for poly in geom.geoms:
        coo += list(zip(*poly.exterior.coords.xy))
    coo = np.array(coo)
    minlo = np.min(coo[:, 0])
    minla = np.min(coo[:, 1])
    maxlo = np.max(coo[:, 0])
    maxla = np.max(coo[:, 1])
    region = "{:f}/{:f}/{:f}/{:f}".format(minlo, maxlo, minla, maxla)

    # Read catalogue
    for i, fname in enumerate(fname_catalogues):
        if i == 0:
            tcat = _load_catalogue(fname)
        else:
            tcat.concatenate(_load_catalogue(fname))

    # Create a dataframe from the catalogue
    dfcat = to_df(tcat)
    dfcat = gpd.GeoDataFrame(dfcat,
                             geometry=gpd.points_from_xy(
                                 dfcat.longitude, dfcat.latitude))
    dfcat.head(n=1)

    # Select the events within the polygon and convert from df to catalogue
    idx = dfcat.within(geom)
    selcat_df = dfcat.loc[idx]
    selcat = from_df(selcat_df)

    if 'completeness_table' in config_main['main']:
        ctab = config_main['main']['completeness_table']
        ctab = np.array(ctab)
    else:
        fname_config = os.path.join(path, config_main['main']['fname_config'])
        msg = 'The config file does not exist:\n{:s}'.format(fname_config)
        assert os.path.exists(fname_config), msg
        config = toml.load(fname_config)
        completeness_label = config_main['main']['completeness_label']
        _, ctab = get_mmax_ctab(config, completeness_label)

    if len(selcat_df.magnitude) < 2:
        print('The catalogue contains less than 2 earthquakes')
        return

    selcat.data["dtime"] = selcat.get_decimal_time()
    cent_mag, t_per, n_obs = get_completeness_counts(selcat, ctab, binw)
    tmp = n_obs / t_per
    hiscml_cat = np.array([np.sum(tmp[i:]) for i in range(0, len(tmp))])

    # Take into account possible multiple occurrences in the SES
    df = dfr.loc[dfr.index.repeat(dfr.n_occ)]
    assert len(df) == np.sum(dfr.n_occ)

    # SES histogram
    idx = dfr.within(geom)
    bins = np.arange(min_magnitude, 9.0, binw)
    hisr, _ = np.histogram(df.loc[idx].mag, bins=bins)
    hisr = hisr / ses_duration
    hiscml = np.array([np.sum(hisr[i:]) for i in range(0, len(hisr))])

    # Plotting
    fig = plt.figure(figsize=(7, 5))
    # - cumulative
    plt.plot(bins[:-1], hiscml, '--x', label='SES')
    plt.plot(cent_mag - binw / 2, hiscml_cat, '-.x', label='Catalogue')
    # - incremental
    plt.bar(cent_mag,
            n_obs / t_per,
            width=binw * 0.7,
            fc='none',
            ec='red',
            alpha=0.5,
            align='center')
    plt.bar(bins[1:] - binw / 2,
            hisr,
            width=binw * 0.6,
            fc='none',
            ec='blue',
            alpha=0.5)
    plt.yscale('log')
    _ = plt.xlabel('Magnitude')
    _ = plt.ylabel('Annual frequency of exceedance')
    plt.grid()
    plt.legend()
    plt.title(descr)
    # - set xlim
    xlim = list(fig.gca().get_xlim())
    xlim[0] = min_magnitude if min_magnitude is not None else xlim[0]
    plt.xlim(xlim)
    plt.savefig(os.path.join(output_dir, 'ses.png'))

    # Plot map with the SES
    fig = pygmt.Figure()
    fig.basemap(region=region, projection="M15c", frame=True)
    fig.coast(land="#666666", water="skyblue")
    pygmt.makecpt(cmap="jet", series=[0, 300])
    fig.plot(x=dfr.loc[idx].hypo_0,
             y=dfr.loc[idx].hypo_1,
             style="c",
             color=dfr.loc[idx].hypo_2,
             cmap=True,
             size=0.01 * (1.5**dfr.loc[idx].mag),
             pen="black")
    fig.show()
    fig.savefig(os.path.join(output_dir, 'map_ses.png'))

    # Plot map with catalogue
    fig = pygmt.Figure()
    fig.basemap(region=region, projection="M15c", frame=True)
    fig.coast(land="#666666", water="skyblue")
    pygmt.makecpt(cmap="jet", series=[0, 300])
    fig.plot(x=selcat_df.longitude,
             y=selcat_df.latitude,
             style="c",
             color=selcat_df.depth,
             cmap=True,
             size=0.01 * (1.5**selcat_df.magnitude),
             pen="black")
    fig.show()
    fig.savefig(os.path.join(output_dir, 'map_eqks.png'))

    # Depth histogram
    deptw = 10.
    mmin = 5.0
    dfs = df.loc[idx]
    bins = np.arange(0.0, 200.0, deptw)
    fig = plt.figure()
    hisr, _ = np.histogram(dfs[dfs.mag > mmin].hypo_2, bins=bins)
    hiscat, _ = np.histogram(selcat_df[selcat_df.magnitude > mmin].depth,
                             bins=bins)
    fig = plt.Figure(figsize=(5, 8))
    plt.barh(bins[:-1],
             hisr / sum(hisr),
             align='edge',
             height=deptw * 0.6,
             fc='lightgreen',
             ec='blue',
             label='ses')
    plt.barh(bins[:-1],
             hiscat / sum(hiscat),
             align='edge',
             height=deptw * 0.5,
             fc='white',
             ec='red',
             alpha=0.5,
             lw=1.5,
             label='catalogue')
    for dep, val in zip(bins[:-1], hiscat):
        if val > 0:
            plt.text(val / sum(hiscat), dep, s='{:.2f}'.format(val))
    plt.gca().invert_yaxis()
    _ = plt.ylabel('Depth [km]')
    _ = plt.xlabel('Count')
    plt.grid()
    plt.legend()
    plt.title(descr)
    plt.savefig(os.path.join(output_dir, 'depth_normalized.png'))
コード例 #5
0
def decluster(catalogue_hmtk_fname, declustering_meth, declustering_params,
              output_path, labels=None, tr_fname=None, subcatalogues=False,
              fmat='csv', olab='', save_af=False, out_fname_ext='',
              fix_defaults=False):
    """
    :param str catalogue_hmtk_fname:
        Full path to the file containing the initial catalogue
    :param str declustering_meth:
        A string indicating the type of declustering
    :param dict declustering_params:
        Parameters required by the declustering algorithm
    :param str output_path:
        Folder where the output catalogue/s will be created
    :param list labels:
        It can be a string or a list of strings
    :param str tr_fname:
        An .hdf5 file containing the TR classification of the catalogue
    :param bool subcatalogues:
        When true creates subcatalogues per tectonic region
    :param str fmat:
        Can be either 'csv' or 'pkl'
    :param str olab:
        Optional label for output catalogues
    :param boolean save_af:
        Save aftershocks and foreshocks
    :param str out_fname_ext:
        String to be added to the putput filename
    :param str fix_defaults:
        Fix defaults values when missing
    """

    # Check if the initial catalogue file exists
    msg = 'Catalogue {:s} is missing'.format(catalogue_hmtk_fname)
    assert os.path.exists(catalogue_hmtk_fname), msg

    # Create output filename
    lbl = 'all'
    if labels is not None and len(out_fname_ext) == 0:
        labels = [labels] if isinstance(labels, str) else labels
        if len(labels) < 2:
            lbl = labels[0]
        else:
            lbl = '-'.join([l for l in labels])
        assert tr_fname is not None
        assert os.path.exists(tr_fname)
        ext = '_dec_{:s}_{:s}.{:s}'.format(olab, lbl, fmat)
    else:
        ext = '_dec_{:s}_{:s}.{:s}'.format(olab, out_fname_ext, fmat)

    # Output filename
    out_fname = Path(os.path.basename(catalogue_hmtk_fname)).stem+ext
    if output_path is not None:
        assert os.path.exists(output_path)
    else:
        output_path = os.path.dirname(catalogue_hmtk_fname)
    out_fname = os.path.abspath(os.path.join(output_path, out_fname))

    # Read the catalogue and adding default values
    cat = _load_catalogue(catalogue_hmtk_fname)
    if fix_defaults:
        cat = _add_defaults(cat)
    cato = copy.deepcopy(cat)

    # Select earthquakes belonging to a given TR. When necessary combining
    # multiple TRs, use label <TR_1>,<TR_2>AND...
    idx = numpy.full(cat.data['magnitude'].shape, True, dtype=bool)
    sumchk = 0
    if labels is not None and tr_fname is not None:
        f = h5py.File(tr_fname, 'r')
        idx = numpy.array([False for i in range(len(f[labels[0]]))])
        for lab in labels:
            idx_tmp = f[lab][:]
            idx[numpy.where(idx_tmp.flatten())] = True
            print(lab, sum(idx_tmp.flatten()))
            sumchk += sum(idx_tmp.flatten())
        f.close()
    idx = idx.flatten()

    # Filter catalogue
    num_eqks_sub = len(cat.data['magnitude'])
    if labels is not None:
        sel = CatalogueSelector(cat, create_copy=False)
        sel.select_catalogue(idx)
        num_eqks_sub = len(cat.data['magnitude'])
        assert sumchk == num_eqks_sub

    # Declustering
    vcl, flag = dec(declustering_params, declustering_meth, cat)

    # Save foreshocks and aftershocks
    catt = copy.deepcopy(cat)
    catt.select_catalogue_events(numpy.where(flag != 0)[0])
    if save_af:
        ext = '_dec_af_{:s}_{:s}.{:s}'.format(olab, lbl, fmat)
        outfa_fname = Path(os.path.basename(catalogue_hmtk_fname)).stem+ext
        outfa_fname = os.path.abspath(os.path.join(output_path, outfa_fname))

    # Select mainshocks
    cat.select_catalogue_events(numpy.where(flag == 0)[0])
    tmps = 'Number of earthquakes in the original subcatalogue: {:d}'
    print('Total eqks       : {:d}'.format(num_eqks_sub))
    num_main = len(cat.data['magnitude'])
    num_foaf = len(catt.data['magnitude'])
    print('Mainshocks       : {:d}'.format(num_main))
    print('Fore/Aftershocks : {:d}'.format(num_foaf))
    assert num_main + num_foaf == num_eqks_sub

    # Save output
    if fmat == 'csv':
        cat.write_catalogue(out_fname)
        print('Writing catalogue to file: {:s}'.format(out_fname))
        if save_af:
            catt.write_catalogue(outfa_fname)
    elif fmat == 'pkl':
        fou = open(out_fname, 'wb')
        pickle.dump(cat, fou)
        fou.close()
        if save_af:
            fou = open(outfa_fname, 'wb')
            pickle.dump(catt, fou)
            fou.close()

    # Create subcatalogues
    icat = numpy.nonzero(idx)[0]
    if subcatalogues:
        f = h5py.File(tr_fname, 'r')
        for lab in labels:
            #
            # Select mainshocks in a given tectonic region
            jjj = numpy.where(flag == 0)[0]
            tmpi = numpy.full((len(idx)), False, dtype=bool)
            tmpi[icat[jjj.astype(int)]] = True
            idx_tmp = f[lab][:].flatten()
            kkk = numpy.logical_and(tmpi, idx_tmp)
            if save_af:
                jjj = numpy.where(flag != 0)[0]
                tmpi = numpy.full((len(idx)), False, dtype=bool)
                tmpi[icat[jjj.astype(int)]] = True
                idx_tmp = f[lab][:].flatten()
                jjj = numpy.logical_and(tmpi, idx_tmp)
            #
            # Create output catalogue
            tsel = CatalogueSelector(cato, create_copy=True)
            ooo = tsel.select_catalogue(kkk)
            if save_af:
                aaa = tsel.select_catalogue(jjj)
            #
            # Info
            tmps = 'Cat: {:s}\n'
            tmps += '    Earthquakes: {:5d} Mainshocks {:5d} {:4.1f}%'
            pct = sum(kkk)/sum(idx_tmp)*100.
            tmpr = '    mmin: {:5.2f} mmax {:5.2f}'
            tmpsum1 = int(sum(idx_tmp))
            tmpsum2 = int(sum(kkk))
            logging.info(tmps.format(lab, tmpsum1, tmpsum2, pct))
            print(tmps.format(lab, tmpsum1, tmpsum2, pct))
            print(tmpr.format(min(ooo.data['magnitude']),
                              max(ooo.data['magnitude'])))
            #
            # Output filename
            ext = '_dec_{:s}_{:s}.{:s}'.format(olab, lab, fmat)
            tcat_fname = Path(os.path.basename(catalogue_hmtk_fname)).stem+ext
            tmps = os.path.join(output_path, tcat_fname)
            tcat_fname = os.path.abspath(tmps)
            if save_af:
                ext = '_dec_af_{:s}_{:s}.{:s}'.format(olab, lab, fmat)
                tcataf_fname = Path(
                    os.path.basename(catalogue_hmtk_fname)).stem + ext
                tmps = os.path.join(output_path, tcataf_fname)
                tcataf_fname = os.path.abspath(tmps)
            #
            # Dumping data into the pickle file
            if ooo is not None:
                if fmat == 'csv':
                    ooo.write_catalogue(tcat_fname)
                    if save_af:
                        aaa.write_catalogue(tcataf_fname)
                elif fmat == 'pkl':
                    fou = open(tcat_fname, 'wb')
                    pickle.dump(ooo, fou)
                    fou.close()
                    if save_af:
                        fou = open(tcataf_fname, 'wb')
                        pickle.dump(aaa, fou)
                        fou.close()
            else:
                tstr = 'Catalogue for region {:s} is empty'.format(lab)
                logging.warning(tstr)
        f.close()

    outl = [out_fname]
    if save_af:
        outl.append(outfa_fname)

    return [out_fname]
コード例 #6
0
def create_mtd(catalogue_fname,
               label,
               tr_fname,
               cumulative,
               store,
               mwid=0.1,
               twid=20.,
               pmint=None,
               pmaxt=None,
               ylim=None):
    """
    :param catalogue_fname:
    :param label:
    :param tr_fname:
    """
    mwid = float(mwid)
    twid = float(twid)
    if pmint is not None:
        pmint = int(pmint)
    if pmaxt is not None:
        pmaxt = int(pmaxt)
    #
    # loading catalogue
    if isinstance(catalogue_fname, str):
        cat = _load_catalogue(catalogue_fname)
    elif isinstance(catalogue_fname, Catalogue):
        cat = catalogue_fname
    else:
        raise ValueError('Unknown instance')

    # Check catalogue
    if cat is None or len(cat.data['magnitude']) < 1:
        return None

    # Select earthquakes belonging to a given TR
    idx = numpy.full(cat.data['magnitude'].shape, True, dtype=bool)
    if label is not None and tr_fname is not None:
        f = h5py.File(tr_fname, 'r')
        idx = f[label][:]
        f.close()
    #
    # select catalogue
    sel = CatalogueSelector(cat, create_copy=False)
    sel.select_catalogue(idx)
    start = datetime.datetime(pmint, 1, 1) if pmint is not None else None
    stop = datetime.datetime(pmaxt, 12, 31) if pmaxt is not None else None
    sel.within_time_period(start, stop)

    # Check if the catalogue contains earthquakes
    if len(cat.data['magnitude']) < 1:
        return None

    #
    # find rounded min and max magnitude
    mmin, mmax = _get_extremes(cat.data['magnitude'], mwid)
    tmin, tmax = _get_extremes(cat.data['year'], twid)
    if ylim is not None:
        mmin = ylim[0]
        mmax = ylim[1]
    #
    #
    if pmint is None:
        pmint = tmin
    if pmaxt is None:
        pmaxt = tmax
    #
    # histogram
    bins_ma = numpy.arange(mmin, mmax + mwid * 0.01, mwid)
    bins_time = numpy.arange(tmin, tmax + twid * 0.01, twid)
    his, _, _ = numpy.histogram2d(cat.data['year'],
                                  cat.data['magnitude'],
                                  bins=(bins_time, bins_ma))
    his = his.T
    #
    # complementary cumulative
    if cumulative:
        ccu = numpy.zeros_like(his)
        for i in range(his.shape[1]):
            cc = numpy.cumsum(his[::-1, i])
            ccu[:, i] = cc[::-1]
    #
    # plotting
    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1)
    #
    #
    X, Y = numpy.meshgrid(bins_time, bins_ma)
    if cumulative:
        his = ccu
    pcm = ax.pcolormesh(X,
                        Y,
                        his,
                        norm=colors.LogNorm(vmin=1e-1, vmax=his.max()),
                        cmap='BuGn')
    #
    # plotting number of occurrences
    for it, vt in enumerate(bins_time[:-1]):
        for im, vm in enumerate(bins_ma[:-1]):
            ax.text(vt + twid / 2,
                    vm + mwid / 2,
                    '{:.0f}'.format(his[im, it]),
                    fontsize=7,
                    ha='center')

    #
    # plotting colorbar
    cb = fig.colorbar(pcm, ax=ax, extend='max')
    cb.set_label('Number of occurrences')
    #
    # finishing the plot
    plt.ylabel('Magnitude')
    plt.xlabel('Time')
    if label is not None:
        plt.title('label: {:s}'.format(label))
    plt.grid(linestyle='-')

    return fig
コード例 #7
0
def completeness_analysis(fname,
                          idxs,
                          years,
                          mags,
                          binw,
                          ref_mag,
                          bgrlim,
                          src_id,
                          folder_out_figs,
                          rewrite=False):

    tcat = _load_catalogue(fname)
    tcat = _add_defaults(tcat)
    tcat.data["dtime"] = tcat.get_decimal_time()
    print('\nSOURCE:', src_id)
    print('Catalogue contains {:d} events'.format(len(tcat.data['magnitude'])))

    # See http://shorturl.at/adsvA
    fname_disp = 'dispositions.npy'
    perms = np.load(fname_disp)
    mags = np.flipud(np.load('mags.npy'))
    years = np.load('years.npy')

    wei_conf = {'magnitude_interval': binw, 'reference_magnitude': 0.0}
    weichert = Weichert()
    rate = -1e10
    save = []
    mags = np.array(mags)

    for prm in perms:

        idx = prm.astype(int)
        tmp = np.array([(y, m) for y, m in zip(years, mags[idx])])
        ctab = clean_completeness(tmp)

        try:
            cent_mag, t_per, n_obs = get_completeness_counts(tcat, ctab, binw)
            bval, sigb, aval, siga = weichert.calculate(tcat, wei_conf, ctab)

            tmp_rate = 10**(-bval * ref_mag + aval)
            if tmp_rate > rate and bval <= bgrlim[1] and bval >= bgrlim[0]:
                rate = tmp_rate
                save = [aval, bval, rate, ctab]

                gwci = get_weichert_confidence_intervals
                lcl, ucl, ex_rates, ex_rates_scaled = gwci(
                    cent_mag, n_obs, t_per, bval)

                mmax = max(tcat.data['magnitude'])
                wei = [
                    cent_mag, n_obs, binw, t_per, ex_rates_scaled, lcl, ucl,
                    mmax, aval, bval
                ]

        except RuntimeWarning:
            logging.debug('Skipping', ctab)

        except UserWarning:
            logging.debug('Skipping', ctab)

        except:
            logging.debug('Skipping', ctab)

    if True:
        fmt = 'Maximum annual rate for {:.1f}: {:.4f}'
        print(fmt.format(ref_mag, save[2]))
        fmt = 'GR a and b                 : {:.4f} {:.4f}'
        print(fmt.format(save[0], save[1]))
        print('Completeness:\n', save[3])

    _weichert_plot(wei[0],
                   wei[1],
                   wei[2],
                   wei[3],
                   wei[4],
                   wei[5],
                   wei[6],
                   wei[7],
                   wei[8],
                   wei[9],
                   src_id=src_id)

    # Saving figure
    if folder_out_figs is not None:
        ext = 'png'
        fmt = 'fig_mfd_{:s}.{:s}'
        figure_fname = os.path.join(folder_out_figs, fmt.format(src_id, ext))
        plt.savefig(figure_fname, format=ext)
        plt.close()

    return save
コード例 #8
0
ファイル: plt_mtd.py プロジェクト: GEMScienceTools/oq-mbtk
def create_mtd(catalogue_fname,
               label,
               tr_fname,
               cumulative,
               store,
               mwid=0.1,
               twid=20.,
               pmint=None,
               pmaxt=None,
               ylim=None):
    """
    :param catalogue_fname:
    :param label:
    :param tr_fname:
    """
    mwid = float(mwid)
    twid = float(twid)
    if pmint is not None:
        pmint = int(pmint)
    if pmaxt is not None:
        pmaxt = int(pmaxt)
    #
    # loading catalogue
    if isinstance(catalogue_fname, str):
        cat = _load_catalogue(catalogue_fname)
    elif isinstance(catalogue_fname, Catalogue):
        cat = catalogue_fname
    else:
        raise ValueError('Unknown instance')

    # Check catalogue
    if cat is None or len(cat.data['magnitude']) < 1:
        return None

    # Select earthquakes belonging to a given TR
    idx = numpy.full(cat.data['magnitude'].shape, True, dtype=bool)
    if label is not None and tr_fname is not None:
        f = h5py.File(tr_fname, 'r')
        idx = f[label][:]
        f.close()
    #
    # select catalogue
    sel = CatalogueSelector(cat, create_copy=False)
    sel.select_catalogue(idx)
    start = datetime.datetime(pmint, 1, 1) if pmint is not None else None
    stop = datetime.datetime(pmaxt, 12, 31) if pmaxt is not None else None
    sel.within_time_period(start, stop)

    # Check if the catalogue contains earthquakes
    if len(cat.data['magnitude']) < 1:
        return None

    # Get matrix
    bins_time, bins_ma, his = get_mtd(cat, mwid, twid, ylim, cumulative)

    # Plotting
    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1)
    X, Y = numpy.meshgrid(bins_time, bins_ma)
    tmp_col = colors.LogNorm(vmin=1e-1, vmax=his.max())
    pcm = ax.pcolormesh(X, Y, his, norm=tmp_col, cmap='BuGn')

    # Plotting number of occurrences
    for it, vt in enumerate(bins_time[:-1]):
        for im, vm in enumerate(bins_ma[:-1]):
            ax.text(vt + twid / 2,
                    vm + mwid / 2,
                    '{:.0f}'.format(his[im, it]),
                    fontsize=7,
                    ha='center')

    # Plotting colorbar
    cb = fig.colorbar(pcm, ax=ax, extend='max')
    cb.set_label('Number of occurrences')

    # Finishing the plot
    plt.ylabel('Magnitude')
    plt.xlabel('Time')
    if label is not None:
        plt.title('label: {:s}'.format(label))
    plt.grid(linestyle='-')

    return fig
コード例 #9
0
def plot_mfd(catalogue_fname,
             grd,
             label,
             store,
             tr_fname,
             compl_table=None,
             mwid=0.1,
             upper_mag=11.,
             title='',
             xlim=None,
             ylim=None,
             figsize=None):
    """
    This function plots the incremental and complementary cumulative
    distribution of the earthquakes included in a catalogue file.

    :param catalogue_fname:
        Full path to the hmtk formatted catalogue
    :param label:
        If the user provides a tectonic regionalisation file, this label (or
        list of labels with the format LAB1, LAB2) defines the tectonic regions
        to be selected.
    :param tr_fname:
        Full path to the .hdf5 file containing the TR
    :param compl_table:
        A :class:`numpy.ndarray` instance of shape (2, n) where the first
        column contains years in a decreasing order and the second column
        contains magnitude (generally) in an increasing order
    :param grd:
        A boolean indicating the need to compute GR parameters
    :param upper_mag:
        The upper magnitude threshold used to filter the catalogue. This is
        useful for example in cases when it is interesting to fit only the
        exponential component of a magnitude-frequency distribution.
    :return:
        A tuple containing the output of the Weichert method in the following
        order: gr_pars
    """
    mwid = float(mwid)
    #
    # loading catalogue
    cat = _load_catalogue(catalogue_fname)
    #
    # select earthquakes belonging to a given TR
    idx = numpy.full(cat.data['magnitude'].shape, True, dtype=bool)
    if label is not None and tr_fname is not None:
        f = h5py.File(tr_fname, 'r')
        idx = f[label][:]
        f.close()
    #
    # select catalogue
    sel = CatalogueSelector(cat, create_copy=False)
    sel.select_catalogue(idx)
    sel.within_magnitude_range(-1, upper_mag)
    tmps = 'Selecting earthquakes below magnitude {:.2f}'
    logging.info(tmps.format(upper_mag))
    #
    # find rounded min and max magnitude
    mmin, mmax = _get_extremes(cat.data['magnitude'], mwid)
    tmin, tmax = _get_extremes(cat.data['year'], 10)
    #
    # compute histogram
    bins = numpy.arange(mmin, mmax + mwid * 0.01, mwid)
    his, _ = numpy.histogram(cat.data['magnitude'], bins)
    #
    # plotting
    if figsize is None:
        figsize = (8, 6)
    fig = plt.figure(figsize=figsize)
    ax = fig.add_subplot(1, 1, 1)
    #
    # add cumulative plot
    cs = numpy.cumsum(his[::-1])
    plt.bar(bins[:-1], cs[::-1], mwid, align='edge', ec='cyan', fc='none')
    plt.plot(bins[:-1] + mwid / 2, cs[::-1], '-r', label='cumulative')
    #
    # add incremental plot
    plt.bar(bins[:-1], his, mwid, align='edge', ec='orange', fc='none')
    plt.plot(bins[:-1] + mwid / 2, his, '-b', label='incremental')
    #
    #
    if grd:
        if compl_table is None:
            compl_table = numpy.array([[tmin, mmin]])
        agr, bgr, asig, bsig = _compute_mfd(cat, compl_table, mwid)
    #
    # info
    num = len(cat.data['magnitude'])
    print('Number of earthquakes in the catalogue          : {:d}'.format(num))
    num = max(cs)
    print('Maximum value in the c. cumulative distribution : {:d}'.format(num))
    #
    # finish plot
    plt.legend()
    plt.yscale('log')
    plt.ylabel('Number of earthquakes')
    plt.xlabel('Magnitude')
    if label is not None:
        plt.title('label: {:s}'.format(label))
    plt.grid(linestyle='-')
    if grd:
        plt.text(0.65,
                 0.70,
                 'bval: %.3f (sigma=%.3f)' % (bgr, bsig),
                 horizontalalignment='left',
                 verticalalignment='center',
                 fontsize=8,
                 transform=ax.transAxes)
        plt.text(0.65,
                 0.75,
                 'aval: %.3f (sigma=%.3f)' % (agr, asig),
                 horizontalalignment='left',
                 verticalalignment='center',
                 fontsize=8,
                 transform=ax.transAxes)
        #
        #
        ascaled = numpy.log10(10**agr * (tmax - tmin))
        v = 10.**(-bins * bgr + ascaled)
        plt.plot(bins, v, '--g', lw=2)
    #
    # set limits
    if xlim is not None:
        plt.xlim(xlim)
    if ylim is not None:
        plt.ylim(ylim)
    #
    # Set title
    plt.title(title)
    #
    # Storing figure
    if store is not None:
        lbl = ''
        ext = 'png'
        if label is not None:
            lbl = label
        figure_fname = 'fig_mfd_{:s}.{:s}'.format(lbl, ext)
        plt.savefig(figure_fname, format=ext)
    else:
        plt.show()

    out = (bins[:-1] + mwid / 2, numpy.array([float(h) for h in his]))
    if grd:
        return out, (agr, bgr, asig, bsig)
    else:
        return out, None
コード例 #10
0
def compute_a_value(fname_input_pattern: str,
                    bval: float,
                    fname_config: str,
                    folder_out: str,
                    use: str = '',
                    folder_out_figs: str = None,
                    plt_show=False):
    """
    This function assignes an a-value to each source with a file selected by
    the provided `fname_input_pattern`.
    """

    if len(use) > 0:
        use = get_list(use)

    # Processing input parameters
    bval = float(bval)
    if folder_out is not None:
        create_folder(folder_out)
    if folder_out_figs is not None:
        create_folder(folder_out_figs)

    if isinstance(fname_input_pattern, str):
        fname_list = glob(fname_input_pattern)
    else:
        fname_list = fname_input_pattern

    # Parsing config
    model = toml.load(fname_config)
    binw = model['bin_width']

    # Processing files
    for fname in sorted(fname_list):

        # Get source ID
        src_id = _get_src_id(fname)
        if len(use) > 0 and src_id not in use:
            continue
        print(fname)

        mmax, ctab = get_mmax_ctab(model, src_id)

        # Processing catalogue
        tcat = _load_catalogue(fname)

        if tcat is None or len(tcat.data['magnitude']) < 2:
            continue

        # Completeness analysis
        tcat = _add_defaults(tcat)
        tcat.data["dtime"] = tcat.get_decimal_time()
        try:
            cent_mag, t_per, n_obs = get_completeness_counts(tcat, ctab, binw)
            if cent_mag is None:
                print('   Completeness analysis failed')
                continue
        except ValueError:
            print('   Completeness analysis failed')
            continue

        df = pd.DataFrame()
        df['mag'] = cent_mag
        df['deltaT'] = t_per
        df['nobs'] = n_obs
        fout = os.path.join(folder_out, 'occ_count_zone_{:s}'.format(src_id))
        df.to_csv(fout, index=False)

        # Computing GR a
        if 'sources' not in model:
            model['sources'] = {}
        if src_id not in model['sources']:
            model['sources'][src_id] = {}

        exrs = get_exrs(df, bval)
        aval = get_agr(df.mag[0] - binw / 2, bval, exrs[0])

        tmp = "{:.5e}".format(aval)
        model['sources'][src_id]['agr_counting'] = float(tmp)

        tmp = "{:.5e}".format(bval)
        model['sources'][src_id]['bgr_counting'] = float(tmp)

        gwci = get_weichert_confidence_intervals
        lcl, ucl, ex_rates, ex_rates_scaled = gwci(cent_mag, n_obs, t_per,
                                                   bval)

        _ = plt.figure()
        ax = plt.gca()
        plt.plot(cent_mag, n_obs / t_per, 'o', markerfacecolor='none')
        plt.plot(cent_mag - binw / 2,
                 ex_rates_scaled,
                 's',
                 markerfacecolor='none',
                 color='red')

        plt.plot(cent_mag - binw / 2, lcl, '--', color='black')
        plt.plot(cent_mag - binw / 2, ucl, '--', color='black')

        xmag = numpy.arange(cent_mag[0] - binw / 2, mmax - 0.01 * binw,
                            binw / 2)
        exra = (10.0**(aval - bval * xmag) - 10.0**(aval - bval * mmax))
        plt.plot(xmag, exra, '--', lw=3, color='green')

        plt.yscale('log')
        plt.xlabel('Magnitude')
        plt.ylabel('Annual rate of exceedance')
        plt.text(0.75,
                 0.95,
                 'Fixed b_GR = {:.2f}'.format(bval),
                 transform=ax.transAxes)
        plt.grid(which='major', color='grey')
        plt.grid(which='minor', linestyle='--', color='lightgrey')
        plt.title(src_id)

        if plt_show:
            plt.show()

        # Saving figures
        if folder_out_figs is not None:
            ext = 'png'
            fmt = 'fig_mfd_{:s}.{:s}'
            figure_fname = os.path.join(folder_out_figs,
                                        fmt.format(src_id, ext))

            plt.savefig(figure_fname, format=ext)
            plt.close()

    # Saving results into the config file
    with open(fname_config, 'w') as fou:
        fou.write(toml.dumps(model))
        print('Updated {:s}'.format(fname_config))
コード例 #11
0
def weichert_analysis(fname_input_pattern,
                      fname_config,
                      folder_out=None,
                      folder_out_figs=None,
                      skip=[],
                      binw=None,
                      plt_show=False):
    """
    Computes GR parameters for a set of catalogues stored in a .csv file

    :param fname_input_pattern:
        It can be either a string (definining a pattern) or a list of
        .csv files. The file names must have the source ID at the end. The
        delimiter of the source ID on the left is `_`
    :param fname_config:
        The name of the .toml configuration file
    :param folder_out:
        The folder where to store the files with the counting of occurrences
    :param folder_out_figs:
        The folder where to store the figures
    :param skip:
        A list with the IDs of the sources to skip
    """

    if folder_out is not None:
        create_folder(folder_out)
    if folder_out_figs is not None:
        create_folder(folder_out_figs)

    # Parsing config
    if fname_config is not None:
        model = toml.load(fname_config)

    if binw is None and fname_config is not None:
        binw = model['bin_width']
    else:
        binw = 0.1

    if isinstance(fname_input_pattern, str):
        fname_list = [f for f in glob(fname_input_pattern)]
    else:
        fname_list = fname_input_pattern

    # Processing files
    for fname in sorted(fname_list):

        print(fname)

        # Get source ID
        src_id = _get_src_id(fname)
        if src_id in skip:
            print("   skipping")
            continue

        if 'sources' in model:
            if (src_id in model['sources']
                    and 'mmax' in model['sources'][src_id]):
                mmax = model['sources'][src_id]['mmax']
            else:
                mmax = model['default']['mmax']
            if (src_id in model['sources']
                    and 'completeness_table' in model['sources'][src_id]):
                key_tmp = 'completeness_table'
                ctab = numpy.array(model['sources'][src_id][key_tmp])
                print('Using source specific completeness')
            else:
                ctab = numpy.array(model['default']['completeness_table'])
        else:
            mmax = model['default']['mmax']
            ctab = numpy.array(model['default']['completeness_table'])

        # Processing catalogue
        tcat = _load_catalogue(fname)

        if tcat is None or len(tcat.data['magnitude']) < 2:
            print('    Source {:s} has less than 2 eqks'.format(src_id))
            continue

        tcat.data["dtime"] = tcat.get_decimal_time()
        cent_mag, t_per, n_obs = get_completeness_counts(tcat, ctab, binw)

        if folder_out is not None:
            df = pd.DataFrame()
            df['mag'] = cent_mag
            df['deltaT'] = t_per
            df['nobs'] = n_obs
            fmt = 'occ_count_zone_{:s}'
            fout = os.path.join(folder_out, fmt.format(src_id))
            df.to_csv(fout, index=False)

        # Computing GR a and b
        tcat = _add_defaults(tcat)
        weichert_config = {
            'magnitude_interval': binw,
            'reference_magnitude': 0.0
        }
        weichert = Weichert()
        bval_wei, sigmab, aval_wei, sigmaa = weichert.calculate(
            tcat, weichert_config, ctab)

        # Computing confidence intervals
        gwci = get_weichert_confidence_intervals
        lcl, ucl, ex_rates, ex_rates_scaled = gwci(cent_mag, n_obs, t_per,
                                                   bval_wei)

        if 'sources' not in model:
            model['sources'] = {}
        if src_id not in model['sources']:
            model['sources'][src_id] = {}

        tmp = "{:.5e}".format(aval_wei)
        model['sources'][src_id]['agr_weichert'] = float(tmp)
        tmp = "{:.3f}".format(bval_wei)
        model['sources'][src_id]['bgr_weichert'] = float(tmp)

        _ = plt.figure()
        ax = plt.gca()
        plt.plot(cent_mag, n_obs / t_per, 'o', markerfacecolor='none')
        plt.plot(cent_mag - binw / 2,
                 ex_rates_scaled,
                 's',
                 markerfacecolor='none',
                 color='red')

        plt.plot(cent_mag - binw / 2, lcl, '--', color='darkgrey')
        plt.plot(cent_mag - binw / 2, ucl, '--', color='darkgrey')

        xmag = numpy.arange(cent_mag[0] - binw / 2, mmax - 0.01 * binw,
                            binw / 2)
        exra = (10.0**(aval_wei - bval_wei * xmag) -
                10.0**(aval_wei - bval_wei * mmax))
        plt.plot(xmag, exra, '--', lw=3, color='green')

        plt.yscale('log')
        plt.xlabel('Magnitude')
        plt.ylabel('Annual rate of exceedance')
        plt.text(0.75,
                 0.95,
                 'b_GR = {:.2f}'.format(bval_wei),
                 transform=ax.transAxes)
        plt.grid(which='major', color='grey')
        plt.grid(which='minor', linestyle='--', color='lightgrey')
        plt.title(src_id)

        if plt_show:
            plt.show()

        # Saving figures
        if folder_out_figs is not None:
            ext = 'png'
            fmt = 'fig_mfd_{:s}.{:s}'
            figure_fname = os.path.join(folder_out_figs,
                                        fmt.format(src_id, ext))

            plt.savefig(figure_fname, format=ext)
            plt.close()

    # Saving results into the config file
    if fname_config is not None:
        with open(fname_config, 'w') as f:
            f.write(toml.dumps(model))
            print('Updated {:s}'.format(fname_config))