pylot/pylot/tomography/fmtomo_tools/event_thinning.py
2025-04-10 13:58:01 +02:00

186 lines
5.8 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import glob, os, shutil
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from matplotlib.collections import PatchCollection
from obspy.geodetics import gps2dist_azimuth
#pwd = '/rscratch/minos13/marcel/fmtomo_alparray/v3.5/alparray_events_thinned/picks'
pwd = '/data/AlpArray_Data/fmtomo/v6/crust_incl_hf_sm_FIX_DTS_grad_sm30_dm10_EASI_test_Plomerova_NS_events/picks'
os.chdir(pwd)
infiles = glob.glob('*.ttf')
clat=46.
clon=11.
ddist = 5
dazim = 5
def make_grid(ddist, dazim):
distgrid = np.arange(35, 135, ddist)
bazimgrid = np.arange(0, 360, dazim)
grid = []
for bazim in np.deg2rad(bazimgrid):
for dist in distgrid:
grid.append(np.array([bazim, dist]))
return np.array(grid)
def make_axes():
fig = plt.figure(figsize=(16,9))
ax1 = fig.add_subplot(121, projection='polar')
ax2 = fig.add_subplot(122)
ax1.set_theta_direction(-1)
ax1.set_theta_zero_location('N')
return ax1, ax2
def load_events():
events = {}
for infile in infiles:
with open(infile, 'r') as fid:
eventid = infile.split('.ttf')[0]
npicks = int(fid.readline())
lat, lon, depth = [float(item) for item in fid.readline().split()]
dist, bazim, azim = gps2dist_azimuth(clat, clon, lat, lon, a=6.371e6, f=0)
bazim = np.deg2rad(bazim)
dist = dist / (np.pi * 6371) * 180 / 1e3
events[eventid] = dict(dist=dist, bazim=bazim, npicks=npicks)
return events
def get_events_in_grid():
events_in_grid = []
for index, gcorner in enumerate(grid):
bazim_l, dist_l = gcorner
bazim_u = bazim_l + np.deg2rad(dazim)
dist_u = dist_l + ddist
events_in_grid.append(dict(bazims=(bazim_l, bazim_u), dists=(dist_l, dist_u), events=[]))
for eventid, event in events.items():
if (dist_l <= event['dist'] < dist_u) and (bazim_l <= event['bazim'] <= bazim_u):
events_in_grid[index]['events'].append(eventid)
return events_in_grid
def filter_events():
filtered_events = {}
for eventdict in events_in_grid:
cur_events = eventdict['events']
if not cur_events: continue
eventid = get_best_event(cur_events)
filtered_events[eventid] = events[eventid]
return filtered_events
def get_best_event(cur_events):
''' return eventid with highest number of picks'''
select_events = {key: events[key] for key in cur_events}
npicks = {key: value['npicks'] for key, value in select_events.items()}
eventid = max(npicks, key=npicks.get)
return eventid
def plot_distribution(events_dict):
cmap_bnd = plt.get_cmap('Greys_r')
cmap_center = plt.get_cmap('viridis')
nevents = [len(grid_dict['events']) for grid_dict in events_dict]
npicks = []
for ev_dict in events_dict:
npick = 0
for eventid in ev_dict['events']:
npick += events[eventid]['npicks']
npicks.append(npick)
npicks = np.array(npicks)
ev_max = max(nevents)
np_max = max(npicks)
print('N picks total:', np.sum(npicks))
print('N picks max: ', np_max)
print('N events max: ', ev_max)
ax_polar, ax_hist = make_axes()
patches = []
for npick, ev_dict in zip(npicks, events_dict):
bazim_l, bazim_u = ev_dict.get('bazims')
dist_l, dist_u = ev_dict.get('dists')
n_ev = len(ev_dict.get('events'))
color_edge = cmap_bnd(n_ev / ev_max)
color_center = cmap_center(npick / np_max)
# color = cmap(np.random.rand())
rect = Rectangle((bazim_l, dist_l), np.deg2rad(dazim), ddist, edgecolor=color_edge)#, facecolor=color_center)
patches.append(rect)
collection = PatchCollection(patches, cmap=cmap_center)
collection.set_array(npicks)
ax_polar.add_collection(collection)
ax_polar.set_ylim((10, 135))
cbar = plt.colorbar(collection)
cbar.set_label('N picks')
# ax.scatter(grid[:, 0] + 0.5 * dazim, grid[:, 1] + 0.5 * ddist, c=nevents, s=50)
bazims = []
dists = []
for event in events.values():
bazims.append(event.get('bazim'))
dists.append(event.get('dist'))
ax_polar.scatter(bazims, dists, c='k', zorder=3, s=5, alpha=0.5)
ax_hist.hist(np.rad2deg(bazims), bins=np.arange(0, 360, dazim))
ax_hist.set_xlabel('Backazimuth (deg)')
ax_hist.set_ylabel('Number of events')
plt.title('Polar event distribution and histogram of backazimuths')
def export_filtered_events(fdir_save='picks_save'):
if not os.path.isdir(fdir_save):
os.mkdir(fdir_save)
for infile in infiles:
eventid = infile.split('.ttf')[0]
if not eventid in events:
for fname in glob.glob('{}.*'.format(eventid)):
shutil.move(fname, fdir_save)
print('Moved file {} to path {}'.format(fname, fdir_save))
def write_input_source_file(fname='input_source_file_P_new.in'):
with open(fname, 'w') as outfile:
outfile.write('{}\n'.format(len(events)))
for eventid in sorted(list(events.keys())):
outfile.write('1 1 {}.ttf\n'.format(eventid))
def filter_bazim(events, bazims_list):
events_filtered = {}
for eventid, event_dict in events.items():
for baz_min, baz_max in bazims_list:
if baz_min <= event_dict['bazim'] * 180. <= baz_max:
events_filtered[eventid] = event_dict
return events_filtered
filter_bazims = [(330, 360), (0, 30), (150, 210)]
events = load_events()
#plot_distribution(events)
events = filter_bazim(events, bazims_list=filter_bazims)
print()
#grid = make_grid(ddist, dazim)
#events_in_grid = get_events_in_grid()
#plot_distribution()
#events = filter_events()
#events_in_grid = get_events_in_grid()
#plot_distribution(events)
#plt.show()
export_filtered_events()
write_input_source_file()