示例#1
0
def graph_mag_count(catalog, dirname):
    """Graph event count grouped by magnitude and by date."""
    catalog.loc[:, 'convtime'] = [
        ' '.join(x.split('T')).split('.')[0] for x in catalog['time'].tolist()
    ]
    catalog.loc[:, 'convtime'] = catalog['convtime'].astype('datetime64[ns]')

    mindate, maxdate = catalog['convtime'].min(), catalog['convtime'].max()
    bincond = maxdate - mindate < pd.Timedelta(days=1460)
    barwidth = 31 if bincond else 365
    timedelt = pd.Timedelta(days=barwidth / 2.)

    minbin = qcu.round2bin(catalog['mag'].min() - 0.1, 1, 'down')
    maxbin = qcu.round2bin(catalog['mag'].max() + 0.1, 1, 'up')
    bins = np.arange(minbin, maxbin + 0.1, 1)

    catalog.loc[:, 'magbin'] = pd.cut(catalog['mag'], bins=bins, right=True)
    maggroups = catalog['magbin'].sort_values().unique()

    fig, axlist = plt.subplots(len(maggroups), sharex=True)
    fig.set_size_inches(10, 14, forward=True)
    for i, mbin in enumerate(maggroups):

        trimcat = catalog[catalog['magbin'] == mbin]

        if len(trimcat) == 0:
            continue

        datelist = [x.split('T')[0] for x in trimcat['time']]
        datedf = pd.DataFrame({'date': datelist})
        datedf['date'] = datedf['date'].astype('datetime64[ns]')

        datedf = datedf.groupby([datedf['date'].dt.year,
                 datedf['date'].dt.month]).count() if bincond\
                 else datedf.groupby([datedf['date'].dt.year]).count()

        evdates = datedf.index.tolist()
        counts = datedf.date.tolist()

        evdates = [
            date(x[0], x[1], 1) if bincond else date(x, 1, 1) for x in evdates
        ]

        axlist[i].bar(evdates,
                      counts,
                      alpha=1,
                      color='b',
                      width=barwidth,
                      edgecolor='k')
        axlist[i].set_ylabel('%d-%d' % (bins[i], bins[i + 1]), fontsize=10)
        plt.xlim(mindate - timedelt, maxdate - timedelt)
        plt.ylim(0, max(counts))
        axlist[i].get_yaxis().set_label_coords(-0.1, 0.5)

    plt.xlabel('Date', fontsize=14)
    for ax in axlist[:-1]:
        ax.xaxis.set_ticks_position('none')

    plt.savefig('%s_magtimecount.png' % dirname, dpi=300)
    plt.close()
示例#2
0
def make_hist(catalog,
              param,
              binsize,
              dirname,
              title='',
              xlabel='',
              countlabel=False,
              maxval=None):
    """Plot histogram grouped by some parameter."""
    paramlist = catalog[pd.notnull(catalog[param])][param].tolist()
    minparam, maxparam = min(paramlist), max(paramlist)
    paramdown = qcu.round2bin(minparam, binsize, 'down')
    paramup = qcu.round2bin(maxparam, binsize, 'up')
    numbins = int((paramup - paramdown) / binsize)
    labelbuff = float(paramup - paramdown) / numbins * 0.5

    diffs = [
        abs(paramlist[i + 1] - paramlist[i]) for i in range(len(paramlist))
        if i + 1 < len(paramlist)
    ]
    diffs = [round(x, 1) for x in diffs if x > 0]

    plt.figure(figsize=(10, 6))
    plt.title(title, fontsize=20)
    plt.xlabel(xlabel, fontsize=14)
    plt.ylabel('Count', fontsize=14)

    if param == 'ms':
        parambins = np.linspace(paramdown, paramup, numbins + 1)
        plt.xlim(paramdown, paramup)
    else:
        parambins = np.linspace(paramdown, paramup + binsize,
                                numbins + 2) - binsize / 2.
        plt.xlim(paramdown - binsize / 2., paramup + binsize / 2.)

    phist = plt.hist(paramlist, parambins, alpha=0.7, color='b', edgecolor='k')
    maxbarheight = max([phist[0][x] for x in range(numbins)] or [0])
    labely = maxbarheight / 50.

    plt.subplots_adjust(left=0.1, right=0.95, top=0.95, bottom=0.11)

    if maxval:
        plt.xlim(xmax=maxval)
    plt.ylim(0, maxbarheight * 1.1 + 0.1)

    # put count numbers above the bars if countlabel=True
    if countlabel:
        for i in range(numbins):
            plt.text(phist[1][i] + labelbuff,
                     phist[0][i] + labely,
                     '%0.f' % phist[0][i],
                     size=12,
                     ha='center')

    if maxval:
        plt.savefig('%s_zoom%shistogram.png' % (dirname, param), dpi=300)
    else:
        plt.savefig('%s_%shistogram.png' % (dirname, param), dpi=300)

    plt.close()
示例#3
0
def make_diff_hist(cat1,
                   cat2,
                   cat1mids,
                   cat2mids,
                   param,
                   binsize,
                   dirname,
                   title='',
                   xlabel=''):
    """Make histogram of parameter differences between matched detections."""
    if len(cat1mids) == 0:
        return

    paramdiffs = []

    for idx, eid in enumerate(cat1mids):
        c1mask = cat1['id'] == eid
        c2mask = cat2['id'] == cat2mids[idx]

        if param == 'distance':
            cat1lat = cat1[c1mask]['latitude'].values[0]
            cat1lon = cat1[c1mask]['longitude'].values[0]
            cat2lat = cat2[c2mask]['latitude'].values[0]
            cat2lon = cat2[c2mask]['longitude'].values[0]
            pardiff = gps2dist_azimuth(cat1lat, cat1lon, cat2lat,
                                       cat2lon)[0] / 1000.
            paramdiffs.append(pardiff)
        else:
            cat1param = cat1[c1mask][param].values[0]
            cat2param = cat2[c2mask][param].values[0]
            if np.isnan(cat1param) or np.isnan(cat2param):
                continue
            pardiff = cat1param - cat2param
            paramdiffs.append(pardiff)

    minpardiff, maxpardiff = min(paramdiffs), max(paramdiffs)
    pardiffdown = qcu.round2bin(minpardiff, binsize, 'down')
    pardiffup = qcu.round2bin(maxpardiff, binsize, 'up')
    numbins = int((pardiffup - pardiffdown) / binsize)
    pardiffbins = np.linspace(pardiffdown, pardiffup + binsize,
                              numbins + 2) - binsize / 2.

    plt.figure(figsize=(12, 6))
    plt.title(title, fontsize=20)
    plt.xlabel(xlabel, fontsize=14)
    plt.ylabel('Count', fontsize=14)

    plt.hist(paramdiffs, pardiffbins, alpha=1, color='b', edgecolor='k')

    plt.subplots_adjust(left=0.1, right=0.95, top=0.95, bottom=0.11)
    plt.tick_params(labelsize=12)
    plt.xlim(pardiffdown - binsize / 2., pardiffup + binsize / 2.)
    plt.ylim(0)

    plt.savefig('%s_%sdiffs.png' % (dirname, param), dpi=300)
    plt.close()
示例#4
0
def map_unique_events(cat, catname, mids):
    """Map unassociated events from a catalog."""
    if len(mids) == len(cat):
        return

    cat = cat[~cat['id'].isin(mids)].reset_index(drop=True)
    lllat, lllon, urlat, urlon, _, _, _, clon = qcu.get_map_bounds(cat)

    plt.figure(figsize=(12, 7))
    mplmap = plt.axes(projection=ccrs.PlateCarree(central_longitude=clon))
    mplmap.coastlines('50m')
    mplmap.scatter(cat['longitude'].tolist(),
                   cat['latitude'].tolist(),
                   color='r',
                   s=2,
                   zorder=4,
                   transform=ccrs.PlateCarree())
    mplmap.gridlines(crs=ccrs.PlateCarree(),
                     draw_labels=True,
                     linewidth=1,
                     color='gray',
                     alpha=0.5,
                     linestyle='--')
    mplmap.add_feature(
        cfeature.NaturalEarthFeature('cultural',
                                     'admin_1_states_provinces_lines',
                                     '50m',
                                     facecolor='none',
                                     edgecolor='k',
                                     zorder=9))
    mplmap.add_feature(cfeature.BORDERS)
    plt.title('%s unassociated events' % catname, fontsize=20, y=1.08)

    plt.savefig('%s_uniquedetecs.png' % catname, dpi=300)
    plt.close()
示例#5
0
def map_events(cat1, cat1name, cat2, cat2name, cat1mids, cat2mids, dirname):
    """Map matching events between catalogs."""
    if len(cat1mids) == 0:
        return

    lllat, lllon, urlat, urlon, _, _, _, clon = qcu.get_map_bounds(cat1, cat2)

    cat1lons, cat1lats, cat2lons, cat2lats = [], [], [], []
    for i, mid in enumerate(cat1mids):
        cat1lons.append(cat1[cat1['id'] == mid]['longitude'].get_values()[0])
        cat1lats.append(cat1[cat1['id'] == mid]['latitude'].get_values()[0])
        cat2lons.append(
            cat2[cat2['id'] == cat2mids[i]]['longitude'].get_values()[0])
        cat2lats.append(
            cat2[cat2['id'] == cat2mids[i]]['latitude'].get_values()[0])

    plt.figure(figsize=(12, 7))
    mplmap = plt.axes(projection=ccrs.PlateCarree(central_longitude=clon))
    mplmap.set_extent([lllon, urlon, lllat, urlat], ccrs.PlateCarree())
    mplmap.coastlines('50m')
    mplmap.gridlines(crs=ccrs.PlateCarree(),
                     draw_labels=True,
                     linewidth=1,
                     color='gray',
                     alpha=0.5,
                     linestyle='--')

    for i, lat in enumerate(cat1lats):
        mplmap.plot([cat1lons[i], cat2lons[i]], [lat, cat2lats[i]],
                    color='k',
                    transform=ccrs.PlateCarree())

    mplmap.scatter(cat1lons,
                   cat1lats,
                   color='b',
                   s=2,
                   zorder=4,
                   transform=ccrs.PlateCarree(),
                   label=cat1name)
    mplmap.scatter(cat2lons,
                   cat2lats,
                   color='r',
                   s=2,
                   zorder=4,
                   transform=ccrs.PlateCarree(),
                   label=cat2name)
    mplmap.add_feature(
        cfeature.NaturalEarthFeature('cultural',
                                     'admin_1_states_provinces_lines',
                                     '50m',
                                     facecolor='none',
                                     edgecolor='k',
                                     zorder=9))
    mplmap.add_feature(cfeature.BORDERS)
    plt.legend()

    plt.savefig('%s_mapmatcheddetecs.png' % dirname, dpi=300)
    plt.close()
示例#6
0
def make_time_hist(catalog, timelength, dirname, title=''):
    """Make histogram either by hour of the day or by date."""
    timelist = catalog['time']

    plt.figure(figsize=(10, 6))
    plt.title(title, fontsize=20)
    plt.ylabel('Count', fontsize=14)

    if timelength == 'hour':
        lons = np.linspace(-180, 180, 25).tolist()
        hours = np.linspace(-12, 12, 25).tolist()

        tlonlist = catalog.loc[:, ['longitude', 'time']]
        tlonlist.loc[:, 'rLon'] = qcu.round2lon(tlonlist['longitude'])

        tlonlist.loc[:, 'hour'] = [
            int(x.split('T')[1].split(':')[0]) for x in tlonlist['time']
        ]
        tlonlist.loc[:, 'rhour'] = [
            x.hour + hours[lons.index(x.rLon)] for x in tlonlist.itertuples()
        ]

        tlonlist.loc[:, 'rhour'] = [
            x + 24 if x < 0 else x - 24 if x > 23 else x
            for x in tlonlist['rhour']
        ]

        hourlist = tlonlist.rhour.tolist()
        hourbins = np.linspace(-0.5, 23.5, 25)

        plt.hist(hourlist, hourbins, alpha=1, color='b', edgecolor='k')
        plt.xlabel('Hour of the Day', fontsize=14)
        plt.xlim(-0.5, 23.5)

    elif timelength == 'day':
        daylist = [x.split('T')[0] for x in timelist]
        daydf = pd.DataFrame({'date': daylist})
        daydf['date'] = daydf['date'].astype('datetime64[ns]')
        daydf = daydf.groupby([
            daydf['date'].dt.year, daydf['date'].dt.month, daydf['date'].dt.day
        ]).count()

        eqdates = daydf.index.tolist()
        counts = daydf.date.tolist()

        eqdates = [date(x[0], x[1], x[2]) for x in eqdates]
        minday, maxday = min(eqdates), max(eqdates)

        plt.bar(eqdates, counts, alpha=1, color='b', width=1)
        plt.xlabel('Date', fontsize=14)
        plt.xlim(minday, maxday)

    plt.subplots_adjust(left=0.1, right=0.95, top=0.95, bottom=0.11)

    plt.savefig('%s_%shistogram.png' % (dirname, timelength), dpi=300)
    plt.close()
示例#7
0
def cat_dup_search(catalog, dirname):
    """Graph possible number of duplicate events given various distances
    and time differences.
    """
    epochtimes = [qcu.to_epoch(row.time) for row in catalog.itertuples()]
    tdifsec = np.asarray(abs(np.diff(epochtimes)))

    lat1 = np.asarray(catalog.latitude[:-1])
    lon1 = np.asarray(catalog.longitude[:-1])
    lat2 = np.asarray(catalog.latitude[1:])
    lon2 = np.asarray(catalog.longitude[1:])
    ddelkm = [
        gps2dist_azimuth(lat1[i], lon1[i], lat2[i], lon2[i])[0] / 1000.
        for i in range(len(lat1))
    ]

    diffdf = pd.DataFrame({'tdifsec': tdifsec, 'ddelkm': ddelkm})

    kmlimits = [1, 2, 4, 8, 16, 32, 64, 128, 256]
    tmax = 16
    dtime = 0.05
    timebins = np.arange(0, tmax + dtime / 2, dtime)

    numevents = np.empty([len(kmlimits), len(timebins) - 1])

    for jdx in range(len(kmlimits)):

        cat_subset = diffdf[diffdf.ddelkm <= kmlimits[jdx]]

        for idx in range(len(timebins) - 1):

            numevents[jdx][idx] = cat_subset[cat_subset.tdifsec.between(
                timebins[idx], timebins[idx + 1])].count()[0]

    totmatch = np.transpose(np.cumsum(np.transpose(numevents), axis=0))

    plt.figure(figsize=(10, 6))
    for idx in range(len(kmlimits)):
        times = timebins[1:]
        matches = totmatch[idx]
        lab = str(kmlimits[idx]) + ' km'
        plt.plot(times, matches, label=lab)

    plt.xlabel('Time (s)', fontsize=14)
    plt.ylabel('Possible duplicate events', fontsize=14)
    plt.xlim(0, tmax)
    plt.ylim(0, np.amax(totmatch) + 0.5)
    plt.legend(loc=2, numpoints=1)
    plt.title(('Cumulative number of events within X seconds\n'
               'and Z km (Z specified in legend)'),
              fontsize=20)

    plt.savefig('%s_catdupsearch.png' % dirname, dpi=300)
    plt.close()
示例#8
0
def make_az_dist(cat1,
                 cat1name,
                 cat2,
                 cat2name,
                 cat1mids,
                 cat2mids,
                 dirname,
                 distwindow=100,
                 numbins=16):
    """Make polar scatter/histogram of azimuth vs. distance."""
    if len(cat1mids) == 0:
        return

    azimuths, distances = qcu.get_azs_and_dists(cat1, cat2, cat1mids, cat2mids)

    width = 2 * pi / numbins
    razimuths = list(map(radians, azimuths))
    bins = np.linspace(0, 2 * pi, numbins + 1)
    azhist = np.histogram(razimuths, bins=bins)[0]
    hist = (float(distwindow) / max(azhist)) * azhist
    bins = (bins + width / 2)[:-1]

    plt.figure(figsize=(6, 6))
    ax1 = plt.subplot(111, projection='polar')
    ax1.scatter(razimuths, distances, color='b', s=10)
    bars = ax1.bar(bins, hist, width=width)
    ax1.set_theta_zero_location('N')
    ax1.set_rmax(distwindow)
    ax1.set_theta_direction(-1)
    ax1.set_rlabel_position(112.5)
    ax1.set_title('%s location relative to %s' % (cat1name, cat2name),
                  fontsize=20)

    for _, hbar in list(zip(hist, bars)):
        hbar.set_facecolor('b')
        hbar.set_alpha(0.2)

    plt.subplots_adjust(left=0.1, right=0.95, top=0.9, bottom=0.11)

    plt.savefig('%s_polarazimuth.png' % dirname, dpi=300)
    plt.close()
示例#9
0
def create_figures():
    """Generate and save all relevant figures and text files."""
    parser = argparse.ArgumentParser()

    parser.add_argument('catalog1',
                        nargs='?',
                        type=str,
                        help='pick first catalog to download data from; to \
                        download data from all catalogs, use "preferred"; if \
                        using -sf, give catalog name')
    parser.add_argument('catalog2',
                        nargs='?',
                        type=str,
                        help='pick second catalog to download data from; to \
                        download data from all catalogs, use "preferred"; if \
                        using -sf, give catalog name')
    parser.add_argument('startyear',
                        nargs='?',
                        type=int,
                        help='pick starting year; if using -sf, give first \
                        year in catalog')
    parser.add_argument('endyear',
                        nargs='?',
                        type=int,
                        help='pick end year (to get a single year of data, \
                        enter same year as startyear); if using -sf, give \
                        last year in catalog')

    parser.add_argument('-mr',
                        '--magrange',
                        nargs=2,
                        type=float,
                        default=[-5, 12],
                        help='give the magnitude range for downloading data \
                        (default range is from -5 to 12)')
    parser.add_argument('-sf',
                        '--specifyfiles',
                        nargs=2,
                        type=str,
                        help='specify two existing .csv files to use')
    parser.add_argument('-fd',
                        '--forcedownload',
                        action='store_true',
                        help='forces downloading of data even if .csv file \
                        exists')
    parser.add_argument('-nm',
                        '--nomatches',
                        action='store_false',
                        help='do not include list of matching events in HTML \
                        report')

    args = parser.parse_args()

    minmag, maxmag = args.magrange

    if args.specifyfiles is None:

        if not args.catalog1:
            sys.stdout.write('No first catalog specified. Exiting...\n')
            sys.exit()
        elif not args.catalog2:
            sys.stdout.write('No second catalog specified. Exiting...\n')
            sys.exit()
        elif not args.startyear:
            sys.stdout.write('No starting year specified. Exiting...\n')
            sys.exit()
        elif not args.endyear:
            sys.stdout.write('No ending year specified. Exiting...\n')
            sys.exit()

        cat1, cat2 = args.catalog1.lower(), args.catalog2.lower()
        startyear, endyear = map(int, [args.startyear, args.endyear])
        download = args.forcedownload

        dirname = '%s-%s%s-%s' % (cat1, cat2, startyear, endyear)

        if download:
            try:
                os.makedirs(dirname)
            except OSError as exception:
                if exception.errno != errno.EEXIST:
                    raise
            datadf1 = qcu.get_data(cat1,
                                   dirname,
                                   startyear=startyear,
                                   endyear=endyear,
                                   minmag=minmag,
                                   maxmag=maxmag)
            datadf2 = qcu.get_data(cat2,
                                   dirname,
                                   startyear=startyear,
                                   endyear=endyear,
                                   minmag=minmag,
                                   maxmag=maxmag)
        else:
            # Python 2
            try:
                try:
                    datadf1 = pd.read_csv('%s/%s%s-%s.csv' %
                                          (dirname, cat1, startyear, endyear))
                    datadf2 = pd.read_csv('%s/%s%s-%s.csv' %
                                          (dirname, cat2, startyear, endyear))
                except IOError:
                    try:
                        os.makedirs(dirname)
                    except OSError as exception:
                        if exception.errno != errno.EEXIST:
                            raise
                    datadf1 = qcu.get_data(cat1,
                                           dirname,
                                           startyear=startyear,
                                           endyear=endyear,
                                           minmag=minmag,
                                           maxmag=maxmag)
                    datadf2 = qcu.get_data(cat2,
                                           dirname,
                                           startyear=startyear,
                                           endyear=endyear,
                                           minmag=minmag,
                                           maxmag=maxmag)
            # Python 3
            except:
                try:
                    datadf1 = pd.read_csv('%s/%s%s-%s.csv' %
                                          (dirname, cat1, startyear, endyear))
                    datadf2 = pd.read_csv('%s/%s%s-%s.csv' %
                                          (dirname, cat2, startyear, endyear))
                except FileNotFoundError:
                    try:
                        os.makedirs(dirname)
                    except OSError as exception:
                        if exception.errno != errno.EEXIST:
                            raise
                    datadf1 = qcu.get_data(cat1,
                                           dirname,
                                           startyear=startyear,
                                           endyear=endyear,
                                           minmag=minmag,
                                           maxmag=maxmag)
                    datadf2 = qcu.get_data(cat2,
                                           dirname,
                                           startyear=startyear,
                                           endyear=endyear,
                                           minmag=minmag,
                                           maxmag=maxmag)

    else:
        from shutil import copy2

        sfcat1, sfcat2 = args.specifyfiles
        cat1, cat2 = args.catalog1, args.catalog2
        dirname = '%s-%s%s-%s' % (cat1, cat2, args.startyear, args.endyear)

        try:
            os.makedirs(dirname)
        except OSError as exception:
            if exception.errno != errno.EEXIST:
                raise

        datadf1, datadf2 = pd.read_csv(sfcat1), pd.read_csv(sfcat2)
        try:
            copy2(sfcat1, dirname)
            copy2(sfcat2, dirname)
        except shutil.SameFileError:
            pass

    if len(datadf1) == 0:
        sys.stdout.write(('%s catalog has no data available for that time '
                          'period. Quitting...\n') % cat1.upper())
        sys.exit()

    if len(datadf2) == 0:
        sys.stdout.write(('%s catalog has no data available for that time '
                          'period. Quitting...\n') % cat2.upper())
        sys.exit()

    cat1, cat2 = cat1.upper(), cat2.upper()

    os.chdir(dirname)
    basic_cat_sum(datadf1, cat1, dirname)
    basic_cat_sum(datadf2, cat2, dirname)

    datadf1.loc[:, 'convtime'] = [
        ' '.join(x.split('T')) for x in datadf1['time'].tolist()
    ]
    datadf1.loc[:, 'convtime'] = datadf1['convtime'].astype('datetime64[ns]')
    datadf1.loc[:, 'time'] = [qcu.to_epoch(x) for x in datadf1['time']]
    datadf2.loc[:, 'convtime'] = [
        ' '.join(x.split('T')) for x in datadf2['time'].tolist()
    ]
    datadf2.loc[:, 'convtime'] = datadf2['convtime'].astype('datetime64[ns]')
    datadf2.loc[:, 'time'] = [qcu.to_epoch(x) for x in datadf2['time']]
    datadf1, datadf2 = qcu.trim_times(datadf1, datadf2)

    cat1ids, cat2ids, newcat1, newcat2 = match_events(datadf1, datadf2,
                                                      dirname)

    if len(cat1ids) == 0:
        sys.stdout.write('*** No matching events found ***\n')

    comp_criteria(datadf1, cat1, cat1ids, datadf2, cat2, cat2ids, dirname)
    #find_closest(datadf1, cat1, cat1ids, datadf2, dirname)

    map_events(newcat1, cat1, newcat2, cat2, cat1ids, cat2ids, dirname)
    map_unique_events(datadf1, cat1, cat1ids)
    map_unique_events(datadf2, cat2, cat2ids)
    make_az_dist(newcat1, cat1, newcat2, cat2, cat1ids, cat2ids, dirname)
    compare_params(newcat1, cat1, newcat2, cat2, cat1ids, cat2ids, 'mag',
                   dirname)
    compare_params(newcat1, cat1, newcat2, cat2, cat1ids, cat2ids, 'depth',
                   dirname)
    make_diff_hist(newcat1,
                   newcat2,
                   cat1ids,
                   cat2ids,
                   'time',
                   0.5,
                   dirname,
                   xlabel='%s-%s time differences (sec)' %
                   (cat1.upper(), cat2.upper()))
    make_diff_hist(newcat1,
                   newcat2,
                   cat1ids,
                   cat2ids,
                   'mag',
                   0.1,
                   dirname,
                   xlabel='%s-%s magnitude differences' %
                   (cat1.upper(), cat2.upper()))
    make_diff_hist(newcat1,
                   newcat2,
                   cat1ids,
                   cat2ids,
                   'depth',
                   2,
                   dirname,
                   xlabel='%s-%s depth differences (km)' %
                   (cat1.upper(), cat2.upper()))
    make_diff_hist(newcat1,
                   newcat2,
                   cat1ids,
                   cat2ids,
                   'distance',
                   2,
                   dirname,
                   xlabel='%s-%s distances (km)' %
                   (cat1.upper(), cat2.upper()))

    return dirname, args.nomatches
示例#10
0
def list_duplicates(catalog,
                    dirname,
                    timewindow=2,
                    distwindow=15,
                    magwindow=None,
                    minmag=-5,
                    locfilter=None):
    """Make a list of possible duplicate events."""
    catalog.loc[:, 'convtime'] = [
        ' '.join(x.split('T')) for x in catalog['time'].tolist()
    ]
    catalog.loc[:, 'convtime'] = catalog['convtime'].astype('datetime64[ns]')
    catalog = catalog[catalog['mag'] >= minmag]
    if locfilter:
        catalog = catalog[catalog['place'].str.contains(locfilter, na=False)]
    cat = catalog[[
        'time', 'convtime', 'id', 'latitude', 'longitude', 'depth', 'mag'
    ]].copy()
    cat.loc[:, 'time'] = [qcu.to_epoch(x) for x in cat['time']]

    duplines1 = [('Possible duplicates using %ss time threshold and %skm '
                  'distance threshold\n') % (timewindow, distwindow),
                 '***********************\n'
                 'date time id latitude longitude depth magnitude '
                 '(distance) (Δ time) (Δ magnitude)\n']
    duplines2 = [('\n\nPossible duplicates using 16s time threshold and 100km '
                  'distance threshold\n'), '***********************\n'
                 'date time id latitude longitude depth magnitude '
                 '(distance) (Δ time) (Δ magnitude)\n']
    sep = '-----------------------\n'

    thresh1dupes, thresh2dupes = 0, 0
    for event in cat.itertuples():

        trimdf = cat[cat['convtime'].between(event.convtime,
                                             event.convtime +
                                             pd.Timedelta(seconds=16),
                                             inclusive=False)]

        if len(trimdf) != 0:
            for tevent in trimdf.itertuples():
                dist = gps2dist_azimuth(event.latitude, event.longitude,
                                        tevent.latitude,
                                        tevent.longitude)[0] / 1000.
                if dist < 100:
                    dtime = (event.convtime - tevent.convtime).total_seconds()
                    dmag = event.mag - tevent.mag
                    diffs = map('{:.2f}'.format, [dist, dtime, dmag])

                    dupline1 = ' '.join([str(x) for x in event[1:]]) + ' ' +\
                               ' '.join(diffs) + '\n'
                    dupline2 = ' '.join([str(x) for x in tevent[1:]]) + '\n'
                    duplines2.extend((sep, dupline1, dupline2))

                    thresh2dupes += 1

                    if (dist < distwindow) and (abs(dtime) < timewindow):
                        duplines1.extend((sep, dupline1, dupline2))
                        thresh1dupes += 1

            continue

    with open('%s_duplicates.txt' % dirname, 'w') as dupfile:
        for dupline in duplines1:
            dupfile.write(dupline)
        for dupline in duplines2:
            dupfile.write(dupline)

    return thresh1dupes, thresh2dupes
示例#11
0
def create_figures():
    """Generate and save all relevant figures and text files."""
    parser = argparse.ArgumentParser()

    parser.add_argument('catalog',
                        nargs='?',
                        type=str,
                        help='pick which catalog to download data from; to \
                        download data from all catalogs, use "preferred"')
    parser.add_argument('startyear',
                        nargs='?',
                        type=int,
                        help='pick starting year')
    parser.add_argument('endyear',
                        nargs='?',
                        type=int,
                        help='pick end year (to get a single year of data, \
                        enter same year as startyear)')

    parser.add_argument('-mr',
                        '--magrange',
                        type=float,
                        nargs=2,
                        default=[-5, 12],
                        help='give the magnitude range for downloading data \
                        (default range is from -5 to 12)')
    parser.add_argument('-tw',
                        '--timewindow',
                        type=float,
                        default=2,
                        help='change time window for finding duplicates \
                        (default is 2 seconds)')
    parser.add_argument('-dw',
                        '--distwindow',
                        type=float,
                        default=15,
                        help='change distance window for finding duplicates \
                        (default is 15 kilometers)')
    parser.add_argument('-sf',
                        '--specifyfile',
                        type=str,
                        help='specify existing .csv file to use')
    parser.add_argument('-fd',
                        '--forcedownload',
                        action='store_true',
                        help='forces downloading of data even if .csv file \
                        exists')

    args = parser.parse_args()

    minmag, maxmag = args.magrange

    if args.specifyfile is None:

        if not args.catalog:
            sys.stdout.write('No catalog specified. Exiting...\n')
            sys.exit()
        elif not args.startyear:
            sys.stdout.write('No starting year specified. Exiting...\n')
            sys.exit()
        elif not args.endyear:
            sys.stdout.write('No ending year specified. Exiting...\n')
            sys.exit()

        catalog = args.catalog.lower()
        startyear, endyear = map(int, [args.startyear, args.endyear])
        download = args.forcedownload

        dirname = '%s%s-%s' % (catalog, startyear, endyear) if catalog else\
                  'preferred%s-%s' % (startyear, endyear)

        if download:
            try:
                os.makedirs(dirname)
            except OSError as exception:
                if exception.errno != errno.EEXIST:
                    raise
            datadf = qcu.get_data(catalog,
                                  dirname,
                                  startyear=startyear,
                                  endyear=endyear,
                                  minmag=minmag,
                                  maxmag=maxmag)
        else:
            # Python 2
            try:
                try:
                    datadf = pd.read_csv('%s/%s.csv' % (dirname, dirname))
                except IOError:
                    try:
                        os.makedirs(dirname)
                    except OSError as exception:
                        if exception.errno != errno.EEXIST:
                            raise
                    datadf = qcu.get_data(catalog,
                                          dirname,
                                          startyear=startyear,
                                          endyear=endyear,
                                          minmag=minmag,
                                          maxmag=maxmag)
            # Python 3
            except:
                try:
                    datadf = pd.read_csv('%s/%s.csv' % (dirname, dirname))
                except FileNotFoundError:
                    try:
                        os.makedirs(dirname)
                    except OSError as exception:
                        if exception.errno != errno.EEXIST:
                            raise
                    datadf = qcu.get_data(catalog,
                                          dirname,
                                          startyear=startyear,
                                          endyear=endyear,
                                          minmag=minmag,
                                          maxmag=maxmag)

    else:
        from shutil import copy2
        dirname = '.'.join(args.specifyfile.split('.')[:-1])

        try:
            os.makedirs(dirname)
        except OSError as exception:
            if exception.errno != errno.EEXIST:
                raise

        datadf = pd.read_csv(args.specifyfile)
        copy2(args.specifyfile, dirname)

    if len(datadf) == 0:
        sys.stdout.write(('Catalog has no data available for that time period.'
                          ' Quitting...\n'))
        sys.exit()

    timewindow = args.timewindow
    distwindow = args.distwindow

    datadf = datadf.sort_values(by='time').reset_index(drop=True)
    datadf.loc[:, 'ms'] = datadf['time'].str[-4:-1].astype('float')

    os.chdir(dirname)
    dup1, dup2 = list_duplicates(datadf,
                                 dirname,
                                 timewindow=timewindow,
                                 distwindow=distwindow)
    basic_cat_sum(datadf, dirname, dup1, dup2, timewindow, distwindow)
    largest_ten(datadf, dirname)

    # generate figures
    map_detecs(datadf, dirname, title='Detection locations')
    map_detecs(datadf, dirname, mindep=50, title='Detections deeper than 50km')
    map_detec_nums(datadf, dirname, title='Detection density')
    make_hist(datadf,
              'mag',
              0.1,
              dirname,
              xlabel='Magnitude',
              title='Magnitude histogram')
    make_hist(datadf,
              'depth',
              1,
              dirname,
              xlabel='Depth (km)',
              title='Depth histogram')
    make_hist(datadf,
              'depth',
              0.5,
              dirname,
              maxval=20,
              xlabel='Depth (km)',
              title='Zoomed depth histogram')
    make_hist(datadf,
              'ms',
              20,
              dirname,
              xlabel='Milliseconds',
              title='Histogram of milliseconds')
    make_time_hist(datadf, 'hour', dirname, title='Events per Hour of the Day')
    make_time_hist(datadf, 'day', dirname, title='Events per Day')
    graph_time_sep(datadf, dirname)
    cat_mag_comp(datadf, dirname)
    graph_mag_time(datadf, dirname)
    cumul_moment_release(datadf, dirname)
    graph_event_types(datadf, dirname)
    cat_dup_search(datadf, dirname)
    med_mag(datadf, dirname)
    graph_mag_count(datadf, dirname)

    return dirname
示例#12
0
def cat_mag_comp(catalog, dirname, magbin=0.1):
    """Plot catalog magnitude completeness."""
    catalog = catalog[pd.notnull(catalog['mag'])]
    mags = np.array(catalog['mag'])
    mags = np.around(mags, 1)

    minmag, maxmag = min(min(mags), 0), max(mags)

    mag_centers = np.arange(minmag, maxmag + 2 * magbin, magbin)
    cdf = np.zeros(len(mag_centers))

    for idx in range(len(cdf)):
        cdf[idx] = np.count_nonzero(
            ~np.isnan(mags[mags >= mag_centers[idx] - 0.001]))

    mag_edges = np.arange(minmag - magbin / 2., maxmag + magbin, magbin)
    g_r, _ = np.histogram(mags, mag_edges)
    idx = list(g_r).index(max(g_r))

    mc_est = mag_centers[idx]

    try:
        mc_est, bvalue, avalue, lval, mc_bins, std_dev = qcu.WW2000(
            mc_est, mags, magbin)
    except:
        mc_est = mc_est + 0.3
        mc_bins = np.arange(0, maxmag + magbin / 2., magbin)
        bvalue = np.log10(np.exp(1)) / (np.average(mags[mags >= mc_est]) -
                                        (mc_est - magbin / 2.))
        avalue = np.log10(len(mags[mags >= mc_est])) + bvalue * mc_est
        log_l = avalue - bvalue * mc_bins
        lval = 10.**log_l
        std_dev = bvalue / sqrt(len(mags[mags >= mc_est]))

    plt.figure(figsize=(8, 6))
    plt.scatter(mag_centers[:len(g_r)],
                g_r,
                edgecolor='r',
                marker='o',
                facecolor='none',
                label='Incremental')
    plt.scatter(mag_centers, cdf, c='k', marker='+', label='Cumulative')
    plt.axvline(mc_est, c='r', linestyle='--', label='Mc = %2.1f' % mc_est)
    plt.plot(mc_bins,
             lval,
             c='k',
             linestyle='--',
             label='B = %1.3f%s%1.3f' % (bvalue, u'\u00B1', std_dev))

    ax1 = plt.gca()
    ax1.set_yscale('log')
    max_count = np.amax(cdf) + 100000
    ax1.set_xlim([minmag, maxmag])
    ax1.set_ylim([1, max_count])
    plt.title('Frequency-Magnitude Distribution', fontsize=18)
    plt.xlabel('Magnitude', fontsize=14)
    plt.ylabel('Log10 Count', fontsize=14)
    plt.legend(numpoints=1)

    plt.savefig('%s_catmagcomp.png' % dirname, dpi=300)
    plt.close()
示例#13
0
def map_detec_nums(catalog,
                   dirname,
                   title='',
                   numcolors=16,
                   rmin=77,
                   rmax=490,
                   minmag=-5,
                   pltevents=True):
    """Map detections and a grid of detection density. rmax=510 is white,
    rmin=0 is black.
    """
    # generate bounds for map
    mask = catalog['mag'] >= minmag

    lllat, lllon, urlat, urlon, gridsize, hgridsize, _, clon = \
        qcu.get_map_bounds(catalog[mask])

    catalog = qcu.add_centers(catalog, gridsize)
    groupedlatlons, _, cmax = qcu.group_lat_lons(catalog, minmag=minmag)

    # print message if there are no detections with magnitudes above minmag
    if cmax == 0:
        print("No detections over magnitude %s" % minmag)

    # create color gradient from light red to dark red
    colors = qcu.range2rgb(rmin, rmax, numcolors)

    # put each center into its corresponding color group
    colorgroups = list(np.linspace(0, cmax, numcolors))
    groupedlatlons.loc[:, 'group'] = np.digitize(groupedlatlons['count'],
                                                 colorgroups)

    # create map
    plt.figure(figsize=(12, 7))
    mplmap = plt.axes(projection=ccrs.PlateCarree(central_longitude=clon))
    mplmap.set_extent([lllon, urlon, lllat, urlat], ccrs.PlateCarree())
    mplmap.coastlines('50m')
    mplmap.add_feature(cfeature.BORDERS)
    mplmap.add_feature(
        cfeature.NaturalEarthFeature('cultural',
                                     'admin_1_states_provinces_lines',
                                     '50m',
                                     facecolor='none',
                                     edgecolor='k',
                                     zorder=9))
    plt.title(title, fontsize=20)
    plt.subplots_adjust(left=0.01, right=0.9, top=0.95, bottom=0.05)

    # create color map based on rmin and rmax
    cmap = LinearSegmentedColormap.from_list('CM', colors)._resample(numcolors)

    # make dummy plot for setting color bar
    colormesh = mplmap.pcolormesh(colors,
                                  colors,
                                  colors,
                                  cmap=cmap,
                                  alpha=1,
                                  vmin=0,
                                  vmax=cmax)

    # format color bar
    cbticks = [x for x in np.linspace(0, cmax, numcolors + 1)]
    cbar = plt.colorbar(colormesh, ticks=cbticks)
    cbar.ax.set_yticklabels([('%.0f' % x) for x in cbticks])
    cbar.set_label('# of detections', rotation=270, labelpad=15)

    # plot rectangles with color corresponding to number of detections
    for center, _, cgroup in groupedlatlons.itertuples():
        minlat, maxlat = center[0] - hgridsize, center[0] + hgridsize
        minlon, maxlon = center[1] - hgridsize, center[1] + hgridsize
        glats = [minlat, maxlat, maxlat, minlat]
        glons = [minlon, minlon, maxlon, maxlon]

        color = colors[cgroup - 1]

        qcu.draw_grid(glats, glons, color, alpha=0.8)

    # if provided, plot detection epicenters
    if pltevents and not catalog['mag'].isnull().all():
        magmask = catalog['mag'] >= minmag
        lons = list(catalog['longitude'][magmask])
        lats = list(catalog['latitude'][magmask])
        mplmap.scatter(lons, lats, c='k', s=7, marker='x', zorder=5)
    elif catalog['mag'].isnull().all():
        lons = list(catalog['longitude'])
        lats = list(catalog['latitude'])
        mplmap.scatter(lons, lats, c='k', s=7, marker='x', zorder=5)

    plt.savefig('%s_eqdensity.png' % dirname, dpi=300)
    plt.close()
示例#14
0
def map_detecs(catalog, dirname, minmag=-5, mindep=-50, title=''):
    """Make scatter plot of detections with magnitudes (if applicable)."""
    catalog = catalog[(catalog['mag'] >= minmag)
                      & (catalog['depth'] >= mindep)].copy()

    if len(catalog) == 0:
        print('\nCatalog contains no events deeper than %s.' % mindep)
        return

    # define map bounds
    lllat, lllon, urlat, urlon, _, _, _, clon = qcu.get_map_bounds(catalog)

    plt.figure(figsize=(12, 7))
    mplmap = plt.axes(projection=ccrs.PlateCarree(central_longitude=clon))
    mplmap.set_extent([lllon, urlon, lllat, urlat], ccrs.PlateCarree())
    mplmap.coastlines('50m', facecolor='none')

    # if catalog has magnitude data
    if not catalog['mag'].isnull().all():
        bins = [0, 5, 6, 7, 8, 15]
        binnames = ['< 5', '5-6', '6-7', '7-8', r'$\geq$8']
        binsizes = [10, 25, 50, 100, 400]
        bincolors = ['g', 'b', 'y', 'r', 'r']
        binmarks = ['o', 'o', 'o', 'o', '*']
        catalog.loc[:, 'maggroup'] = pd.cut(catalog['mag'],
                                            bins,
                                            labels=binnames)

        for i, label in enumerate(binnames):
            mgmask = catalog['maggroup'] == label
            rcat = catalog[mgmask]
            lons, lats = list(rcat['longitude']), list(rcat['latitude'])
            if len(lons) > 0:
                mplmap.scatter(lons,
                               lats,
                               s=binsizes[i],
                               marker=binmarks[i],
                               c=bincolors[i],
                               label=binnames[i],
                               alpha=0.8,
                               zorder=10,
                               transform=ccrs.PlateCarree())

        plt.legend(loc='lower left', title='Magnitude')

    # if catalog does not have magnitude data
    else:
        lons, lats = list(catalog['longitude']), list(catalog['latitude'])
        mplmap.scatter(lons, lats, s=15, marker='x', c='r', zorder=10)

    mplmap.add_feature(
        cfeature.NaturalEarthFeature('cultural',
                                     'admin_1_states_provinces_lines',
                                     '50m',
                                     facecolor='none',
                                     edgecolor='k',
                                     zorder=9))
    mplmap.add_feature(cfeature.BORDERS)

    plt.title(title, fontsize=20)
    plt.subplots_adjust(left=0.05, right=0.95, top=0.95, bottom=0.05)

    if mindep != -50:
        plt.savefig('%s_morethan%sdetecs.png' % (dirname, mindep), dpi=300)
    else:
        plt.savefig('%s_mapdetecs.png' % dirname, dpi=300)

    plt.close()