Example #1
0
    def test_catalogue_selection(self):
        # Tests the tools for selecting events within the catalogue
        self.catalogue.data['longitude'] = np.arange(1.,6., 1.)
        self.catalogue.data['latitude'] = np.arange(6., 11., 1.)
        self.catalogue.data['depth'] = np.ones(5, dtype=bool)

        # No events selected
        flag_none = np.zeros(5, dtype=bool)
        selector0 = CatalogueSelector(self.catalogue)
        test_cat1 = selector0.select_catalogue(flag_none)
        self.assertEqual(len(test_cat1.data['longitude']), 0)
        self.assertEqual(len(test_cat1.data['latitude']), 0)
        self.assertEqual(len(test_cat1.data['depth']), 0)

        # All events selected
        flag_all = np.ones(5, dtype=bool)
        test_cat1 = selector0.select_catalogue(flag_all)
        self.assertTrue(np.allclose(test_cat1.data['longitude'],
                                    self.catalogue.data['longitude']))
        self.assertTrue(np.allclose(test_cat1.data['latitude'],
                                    self.catalogue.data['latitude']))
        self.assertTrue(np.allclose(test_cat1.data['depth'],
                                    self.catalogue.data['depth']))

        # Some events selected
        flag_1 = np.array([True, False, True, False, True])
        test_cat1 = selector0.select_catalogue(flag_1)
        self.assertTrue(np.allclose(test_cat1.data['longitude'],
                                    np.array([1., 3., 5.])))
        self.assertTrue(np.allclose(test_cat1.data['latitude'],
                                    np.array([6., 8., 10])))
        self.assertTrue(np.allclose(test_cat1.data['depth'],
                                    np.array([1., 1., 1.])))
Example #2
0
    def test_catalogue_selection(self):
        # Tests the tools for selecting events within the catalogue
        self.catalogue.data['longitude'] = np.arange(1., 6., 1.)
        self.catalogue.data['latitude'] = np.arange(6., 11., 1.)
        self.catalogue.data['depth'] = np.ones(5, dtype=bool)

        # No events selected
        flag_none = np.zeros(5, dtype=bool)
        selector0 = CatalogueSelector(self.catalogue)
        test_cat1 = selector0.select_catalogue(flag_none)
        self.assertEqual(len(test_cat1.data['longitude']), 0)
        self.assertEqual(len(test_cat1.data['latitude']), 0)
        self.assertEqual(len(test_cat1.data['depth']), 0)

        # All events selected
        flag_all = np.ones(5, dtype=bool)
        test_cat1 = selector0.select_catalogue(flag_all)
        self.assertTrue(np.allclose(test_cat1.data['longitude'],
                                    self.catalogue.data['longitude']))
        self.assertTrue(np.allclose(test_cat1.data['latitude'],
                                    self.catalogue.data['latitude']))
        self.assertTrue(np.allclose(test_cat1.data['depth'],
                                    self.catalogue.data['depth']))

        # Some events selected
        flag_1 = np.array([True, False, True, False, True])
        test_cat1 = selector0.select_catalogue(flag_1)
        self.assertTrue(np.allclose(test_cat1.data['longitude'],
                                    np.array([1., 3., 5.])))
        self.assertTrue(np.allclose(test_cat1.data['latitude'],
                                    np.array([6., 8., 10])))
        self.assertTrue(np.allclose(test_cat1.data['depth'],
                                    np.array([1., 1., 1.])))
Example #3
0
def get_unclassified(tot_lab, pck_fname, out_cata, path_out):
    """
    Create a text file (.csv formatted) with the unclassified earthquakes

    :param tot_lab:

    :param pck_fname:
        Name of the pickle file with the catalogue
    :param out_cata:
        Name of the .csv output catalogue
    :param path_out:
        Path to output folder
    """

    # ID of the unclassified earthquakes
    tr_undef = abs(tot_lab - 1)

    # Load the catalogue of unclassified earthquakes
    catalogue = pickle.load(open(pck_fname, 'rb'))

    # Select the unclassified
    selector = CatalogueSelector(catalogue, create_copy=False)
    catalogue = selector.select_catalogue(tr_undef)
    print('')
    print('# earthquakes: {:d}'.format(len(catalogue.data['longitude'])))

    # Sub-catalogue
    csv_filename = out_cata + "_TR_unclassified.csv"
    csv_filename = os.path.join(path_out, csv_filename)

    # Write the purged catalogue
    csvcat = CsvCatalogueWriter(csv_filename)
    csvcat.write_file(catalogue)
    print("Catalogue successfully written to %s" % csv_filename)
Example #4
0
    def set_catalogue(self, catalogue, bffer=75.):
        """
        """
        print('setting catalogue')
        _, _, _, _, qual = self.csec.get_mm()

        if qual == 1:
            idxs = self.csec.get_eqks_within_buffer_idl(catalogue, bffer)
        else:
            idxs = self.csec.get_eqks_within_buffer(catalogue, bffer)
        boo = numpy.zeros_like(catalogue.data['magnitude'], dtype=int)
        boo[idxs] = 1
        selector = CatalogueSelector(catalogue, create_copy=True)
        newcat = selector.select_catalogue(boo)
        self.ecat = newcat
Example #5
0
def main(argv):

    filename = argv[0]
    parser = CsvCatalogueParser(filename)
    cat = parser.read_file()

    output_path = './catalogue_ori.p'
    fou = open(output_path, 'wb')
    pickle.dump(cat, fou)
    fou.close()

    lomin = -180
    lomax = +180
    lamin = -90
    lamax = +90

    if len(argv) > 1:
        lomin = float(argv[1])
    if len(argv) > 2:
        lomax = float(argv[2])
    if len(argv) > 3:
        lamin = float(argv[3])
    if len(argv) > 4:
        lamax = float(argv[4])

    idxo = numpy.nonzero((cat.data['longitude'] >= lomin)
                         & (cat.data['longitude'] <= lomax)
                         & (cat.data['latitude'] >= lamin)
                         & (cat.data['latitude'] <= lamax))
    idxs = idxo[0].astype(int)

    boo = numpy.zeros_like(cat.data['magnitude'], dtype=int)
    boo[idxs] = 1

    selector = CatalogueSelector(cat, create_copy=True)
    newcat = selector.select_catalogue(boo)

    output_path = './catalogue_ext.p'
    fou = open(output_path, 'wb')
    pickle.dump(newcat, fou)
    fou.close()
Example #6
0
    def set_catalogue(self, catalogue, bffer=75.):
        """
        :param catalogue:
            An instance of
            :class:`openquake.hmtk.seismicity.catalogue.Catalogue`
        :param buffer:
            A float defining the maximum distance [km] from the cross-section
            used to select seismicity
        """
        print('setting catalogue')
        _, _, _, _, qual = self.csec.get_mm()

        if qual == 1:
            idxs = self.csec.get_eqks_within_buffer_idl(catalogue, bffer)
        else:
            idxs = self.csec.get_eqks_within_buffer(catalogue, bffer)
        boo = numpy.zeros_like(catalogue.data['magnitude'], dtype=int)
        boo[idxs] = 1
        selector = CatalogueSelector(catalogue, create_copy=True)
        newcat = selector.select_catalogue(boo)
        self.ecat = newcat
Example #7
0
def get_catalogue(cat_pickle_fname, treg_filename, label):
    """
    :param cat_pickle_fname:
    :param treg_filename:
    :param label:
    """
    #
    # loading TR
    if treg_filename is not None:
        f = h5py.File(treg_filename, 'r')
        tr = f[label][:]
        f.close()
    #
    # loading the catalogue
    # catalogue = pickle.load(open(cat_pickle_fname, 'rb'))
    catalogue = load_catalogue(cat_pickle_fname)
    catalogue.sort_catalogue_chronologically()
    #
    # if a label and a TR are provided we filter the catalogue
    if treg_filename is not None:
        selector = CatalogueSelector(catalogue, create_copy=False)
        catalogue = selector.select_catalogue(tr)
    return catalogue
Example #8
0
def create_catalogue(model,
                     catalogue,
                     area_source_ids_list=None,
                     polygon=None):
    """
    Select earthquakes within the polygon delineating an area source

    :parameter model:
        An :class:`openquake.mbt.oqt_project.OQtModel` instance
    :parameter catalogue:
        A hmtk-formatted catalogue
    :parameter area_source_ids_list:
        The list of source ID to be used for the selection. The IDs are the
        ones of one or several sources in the `sources` attribute of the
        `model` instance.
    :parameter polygon:
        A polygon (used when the area_source_ids_list is None).
    :returns:
        Returns an hmtk-formatted catalogue containing only the earthquakes
        inside the polygon
    """
    #
    #
    if area_source_ids_list is not None and len(area_source_ids_list) > 1:
        msg = 'We do not support the selection for multiple sources'
        raise ValueError(msg)
    #
    #
    if area_source_ids_list is not None:
        # Process the area source
        src_id = area_source_ids_list[0]
        src = model.sources[src_id]
        # Set the geometry
        if 'polygon' in src.__dict__:
            # The source has a polygon
            pass
        elif src_id in model.nrml_sources:
            # Set the polygon from nrml
            src.polygon = model.nrml_sources[src_id].polygon
            src.name = model.nrml_sources[src_id].name
            src.source_id = model.nrml_sources[src_id].source_id
        else:
            print('The source does not have a geometry assigned')
            return None
    elif polygon is not None:
        assert isinstance(polygon, Polygon)
        src_id = 'user_defined'
        src = OQtSource('id', 'AreaSource')
        src.name = 'dummy'
        src.polygon = polygon
    else:
        msg = 'Either a polygon or a list of src id must be defined'
        raise ValueError(msg)
    #
    #
    neqk = len(catalogue.data['longitude'])
    sel_idx = numpy.full((neqk), False, dtype=bool)
    pnt_idxs = [i for i in range(0, neqk)]
    idxs = get_idx_points_inside_polygon(catalogue.data['longitude'],
                                         catalogue.data['latitude'],
                                         src.polygon.lons,
                                         src.polygon.lats,
                                         pnt_idxs,
                                         buff_distance=0.)
    sel_idx[idxs] = True
    #
    # Select earthquakes
    cat = deepcopy(catalogue)
    selector = CatalogueSelector(cat, create_copy=False)
    selector.select_catalogue(sel_idx)
    #
    # set label
    labels = ['%s' % src_id for i in range(0, len(cat.data['longitude']))]
    cat.data['comment'] = labels
    # Complete the composite subcatalogue
    return cat
Example #9
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]
Example #10
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
    def classify(self, compute_distances, remove_from):
        """
        :param bool compute_distances:
            A boolean indicating if distances between earthquakes and the
            subduction surface should be computed. If False the distances
            stored in `self.distance_folder` will be used.
        :param list remove_from:
            A list of labels identifying TR from where the earthquakes assigned
            to this TR must be removed
        """
        #
        # set parameters
        treg_filename = self.treg_filename
        distance_folder = self.distance_folder
        edges_folder = self.edges_folder
        distance_buffer_below = self.distance_buffer_below
        distance_buffer_above = self.distance_buffer_above
        catalogue_filename = self.catalogue_filename
        lower_depth = self.lower_depth
        if lower_depth is None:
            lower_depth = 400
        #
        # open log file and prepare the group
        flog = h5py.File(self.log_fname, 'a')
        if self.label not in flog.keys():
            grp = flog.create_group('/{:s}'.format(self.label))
        else:
            grp = flog['/{:s}'.format(self.label)]
        #
        # read the catalogue
        catalogue = get_catalogue(catalogue_filename)
        neq = len(catalogue.data['longitude'])
        f = h5py.File(treg_filename, "a")
        if self.label in f.keys():
            treg = f[self.label]
        else:
            treg = np.full((neq), False, dtype=bool)
        #
        # create the spatial index
        sidx = get_rtree_index(catalogue)
        #
        # build the complex fault surface
        tedges = _read_edges(edges_folder)
        surface = build_complex_surface_from_edges(edges_folder)
        mesh = surface.mesh
        #
        # create polygon encompassing the mesh
        plo = list(mesh.lons[0, :])
        pla = list(mesh.lats[0, :])
        #
        plo += list(mesh.lons[:, -1])
        pla += list(mesh.lats[:, -1])
        #
        plo += list(mesh.lons[-1, ::-1])
        pla += list(mesh.lats[-1, ::-1])
        #
        plo += list(mesh.lons[::-1, 0])
        pla += list(mesh.lats[::-1, 0])
        #
        # set variables used in griddata
        data = np.array([mesh.lons.flatten().T, mesh.lats.flatten().T]).T
        values = mesh.depths.flatten().T

        ddd = np.array([
            mesh.lons.flatten().T,
            mesh.lats.flatten().T,
            mesh.depths.flatten()
        ]).T
        if self.label not in flog.keys():
            grp.create_dataset('mesh', data=ddd)
        #
        # set bounding box of the subduction surface
        min_lo_sub = np.amin(mesh.lons)
        min_la_sub = np.amin(mesh.lats)
        max_lo_sub = np.amax(mesh.lons)
        max_la_sub = np.amax(mesh.lats)
        #
        # select earthquakes within the bounding box
        idxs = sorted(
            list(
                sidx.intersection(
                    (min_lo_sub - DELTA, min_la_sub - DELTA, 0,
                     max_lo_sub + DELTA, max_la_sub + DELTA, lower_depth))))
        #
        # Select earthquakes within the bounding box of the surface
        # projection of the fault
        sidx = get_idx_points_inside_polygon(catalogue.data['longitude'][idxs],
                                             catalogue.data['latitude'][idxs],
                                             plo,
                                             pla,
                                             idxs,
                                             buff_distance=5000.)
        #
        # Select earthuakes and store indexes of selected ones
        ccc = []
        idxs = []
        for idx in sidx:
            #
            # Preselection based on magitude and time of occurrence
            if ((catalogue.data['magnitude'][idx] >= self.low_mag) &
                (catalogue.data['magnitude'][idx] <= self.upp_mag) &
                (catalogue.data['year'][idx] >= self.low_year) &
                (catalogue.data['year'][idx] <= self.upp_year)):
                idxs.append(idx)
                #
                # Update the log file
                ccc.append([
                    catalogue.data['longitude'][idx],
                    catalogue.data['latitude'][idx],
                    catalogue.data['depth'][idx]
                ])
        if self.label not in flog.keys():
            grp.create_dataset('cat', data=np.array(ccc))
        #
        # Prepare array for the selection of the catalogue
        flags = np.full((len(catalogue.data['longitude'])), False, dtype=bool)
        flags[idxs] = True
        #
        # Create a selector for the catalogue and select earthquakes within
        # bounding box
        sel = CatalogueSelector(catalogue, create_copy=True)
        cat = sel.select_catalogue(flags)
        self.cat = cat
        #
        # If none of the earthquakes in the catalogue is in the bounding box
        # used for the selection we stop the processing
        if len(cat.data['longitude']) < 1:
            f = h5py.File(treg_filename, "a")
            if self.label in f.keys():
                del f[self.label]
            f[self.label] = treg
            f.close()
            return
        #
        # compute distances between the earthquakes in the catalogue and
        # the surface of the fault
        out_filename = os.path.join(distance_folder,
                                    'dist_{:s}.pkl'.format(self.label))
        #
        #
        surf_dist = get_distances_from_surface(cat, surface)
        """
        if compute_distances:
            tmps = 'Computing distances'
            logging.info(tmps.format(out_filename))
            surf_dist = get_distances_from_surface(cat, surface)
            pickle.dump(surf_dist, open(out_filename, 'wb'))
        else:
            if not os.path.exists(out_filename):
                raise IOError('Distance file does not exist')
            surf_dist = pickle.load(open(out_filename, 'rb'))
            tmps = 'Loading distances from file: {:s}'
            logging.info(tmps.format(out_filename))
            tmps = '    number of values loaded: {:d}'
            logging.info(tmps.format(len(surf_dist)))
        """
        #
        # info
        neqks = len(cat.data['longitude'])
        tmps = 'Number of eqks in the new catalogue     : {:d}'
        logging.info(tmps.format(neqks))
        #
        # Calculate the depth of the top of the slab for every earthquake
        # location
        points = np.array(
            [[lo, la]
             for lo, la in zip(cat.data['longitude'], cat.data['latitude'])])
        #
        # compute the depth of the top of the slab at every epicenter
        # sub_depths = griddata(data, values, (points[:, 0], points[:, 1]),
        #                      method='cubic')
        #
        # interpolation
        rbfi = Rbf(data[:, 0], data[:, 1], values)
        sub_depths = rbfi(points[:, 0], points[:, 1])
        #
        # saving the distances to a file
        tmps = 'vert_dist_to_slab_{:s}.pkl'.format(self.label)
        out_filename = os.path.join(distance_folder, tmps)
        if not os.path.exists(out_filename):
            pickle.dump(surf_dist, open(out_filename, 'wb'))
        #
        # Let's find earthquakes close to the top of the slab
        idxa = np.nonzero((np.isfinite(surf_dist) & np.isfinite(sub_depths)
                           & np.isfinite(cat.data['depth'])) & (
                               (surf_dist < distance_buffer_below) &
                               (sub_depths > cat.data['depth']))
                          | ((surf_dist < distance_buffer_above)
                             & (sub_depths <= cat.data['depth'])))[0]
        idxa = []
        for srfd, subd, dept in zip(surf_dist, sub_depths, cat.data['depth']):
            if np.isfinite(srfd) & np.isfinite(subd) & np.isfinite(dept):
                if (float(srfd) <
                        min(distance_buffer_below, distance_buffer_above) *
                        0.90):
                    idxa.append(True)
                elif ((float(srfd) < distance_buffer_below) &
                      (float(subd) < float(dept))):
                    idxa.append(True)
                elif ((float(srfd) < distance_buffer_above) &
                      (float(subd) >= float(dept))):
                    idxa.append(True)
                else:
                    idxa.append(False)
            else:
                idxa.append(False)
        idxa = np.array(idxa)
        #
        # checking the size of lists
        assert len(idxa) == len(cat.data['longitude']) == len(idxs)
        #
        #
        self.surf_dist = surf_dist
        self.sub_depths = sub_depths
        self.tedges = tedges
        self.idxa = idxa
        self.treg = treg
        #
        #
        tl = np.zeros(len(idxa),
                      dtype={
                          'names':
                          ('lon', 'lat', 'dep', 'subd', 'srfd', 'idx'),
                          'formats': ('f8', 'f8', 'f8', 'f8', 'f8', 'i4')
                      })
        tl['lon'] = cat.data['longitude']
        tl['lat'] = cat.data['latitude']
        tl['dep'] = cat.data['depth']
        tl['subd'] = sub_depths
        tl['srfd'] = surf_dist
        tl['idx'] = idxa
        #
        # store log data
        if self.label not in flog.keys():
            grp.create_dataset('data', data=np.array(tl))
        #
        # updating the selection array
        for uuu, iii in enumerate(list(idxa)):
            aaa = idxs[uuu]
            assert catalogue.data['eventID'][aaa] == cat.data['eventID'][uuu]
            if iii:
                treg[aaa] = True
            else:
                treg[aaa] = False
        #
        # storing results in the .hdf5 file
        logging.info('Storing data in:\n{:s}'.format(treg_filename))
        f = h5py.File(treg_filename, "a")
        if len(remove_from):
            fmt = '    treg: {:d}'
            logging.info(fmt.format(len(treg)))
            iii = np.nonzero(treg)[0]
            for tkey in remove_from:
                logging.info('    Cleaning {:s}'.format(tkey))
                old = f[tkey][:]
                fmt = '     before: {:d}'
                logging.info(fmt.format(len(np.nonzero(old)[0])))
                del f[tkey]
                old[iii] = False
                f[tkey] = old
                fmt = '     after: {:d}'
                logging.info(fmt.format(len(np.nonzero(old)[0])))
        #
        # Removing the old classification and adding the new one
        if self.label in f.keys():
            del f[self.label]
        f[self.label] = treg
        #
        # closing files
        f.close()
        flog.close()
Example #12
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

    # 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
Example #13
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
Example #14
0
def create_sub_catalogue(alen, aaa, pck_fname, treg_fname, out_cata, out_path):
    """
    Creates .csv files with the subcatalogues

    :param alen:
        Number of earthquakes in the original catalogue
    :param aaa:
        List of the labels used to define the various tectonic regions
    :param pck_fname:
        Name of the file with the pickled catalogue
    :param treg_fname:
        Name of the .hdf5 file with the classification of the catalogue
    :param out_cata:
        Name of the .hdf5 file with the classification of the catalogue
    :param out_path:
        Name of the .hdf5 file with the classification of the catalogue
    :returns:
        A :class:`numpy.ndarray` vector of length N where N is the number of
        earthquakes in the original catalogue.
    """

    # The output vector
    tot_lab = np.zeros(alen)

    print(' ')
    fmt = '# earthquakes in the catalogue: {:d}'
    print(fmt.format(len(tot_lab)))

    # Loop over the tectonic regions
    for label in (aaa):

        # Output file name
        csv_filename = out_cata + "_TR_{:s}.csv".format(label)
        csv_filename = os.path.join(out_path, csv_filename)

        # Read the TR classification
        f = h5py.File(treg_fname, 'r')
        tr = f[label][:]
        f.close()

        if sum(tr) > 0:
            tmp_lab = tr * 1
            tot_lab = tot_lab + tmp_lab
            catalogue = pickle.load(open(pck_fname, 'rb'))
            for lab in ['month', 'day', 'hour', 'minute', 'second']:
                idx = np.isnan(catalogue.data[lab])
                if lab == 'day' or lab == 'month':
                    catalogue.data[lab][idx] = 1
                elif lab == 'second':
                    catalogue.data[lab][idx] = 0.0
                else:
                    catalogue.data[lab][idx] = 0
            selector = CatalogueSelector(catalogue, create_copy=False)
            catalogue = selector.select_catalogue(tr)
            catalogue.data['hour'] = catalogue.data['hour'].astype(int)
            catalogue.data['minute'] = catalogue.data['minute'].astype(int)

            print(' ')
            fmt = '# earthquakes in this TR      : {:d}'
            print(fmt.format(len(catalogue.data['longitude'])))

            # Sub-catalogue
            print(csv_filename)
            csvcat = CsvCatalogueWriter(csv_filename)

            # Write the purged catalogue
            csvcat.write_file(catalogue)
            print("Catalogue successfully written to %s" % csv_filename)

    return tot_lab