checked all modules with flake8, restructured files in directories and changed module names

master
Simone Cesca 5 years ago
parent 3175e7077c
commit 4dbbfead2c

@ -1,16 +1,14 @@
#!/usr/local/bin/python3
import re, sys, os, shutil, glob, operator
import math, random, string
import datetime, time, calendar
import sys
import os
import shutil
from optparse import OptionParser
import numpy as num
#from numpy import mean,std,var,median
from pyrocko import moment_tensor, orthodrome, model, util
from pyrocko.guts import load, dump
from pyrocko import model
from pyrocko.client import catalog
from pyrocko.guts import load
from seiscloud import config
from seiscloud import cluster as sccluster
@ -25,8 +23,7 @@ Seismicity clustering
4. plot - Plot clustering results
'''
km=1000.
km = 1000.
def d2u(d):
@ -36,7 +33,6 @@ def d2u(d):
return d.replace('-', '_')
subcommand_descriptions = {
'example': 'create example configuration file',
'init': 'initialize a project',
@ -77,7 +73,6 @@ To get further help and a list of available options for any subcommand run:
''' % usage_tdata
def die(message, err=''):
if err:
sys.exit('%s: error: %s \n %s' % (program_name, message, err))
@ -85,14 +80,12 @@ def die(message, err=''):
sys.exit('%s: error: %s' % (program_name, message))
def help_and_die(parser, message):
parser.print_help(sys.stderr)
sys.stderr.write('\n')
die(message)
def cl_parse(command, args, setup=None, details=None):
'''
Parsing seiscloud call
@ -122,7 +115,6 @@ def cl_parse(command, args, setup=None, details=None):
return parser, options, args
def command_example(args):
'''
Execution of command example
@ -146,7 +138,6 @@ def command_example(args):
print('Created a fresh config file "%s"' % fn_config)
def command_init(args):
'''
Execution of command init
@ -160,7 +151,7 @@ def command_init(args):
parser, options, args = cl_parse('init', args, setup)
if len(args)!=1:
if len(args) != 1:
help_and_die(parser, 'missing argument')
else:
fn_config = args[0]
@ -172,17 +163,34 @@ def command_init(args):
config.check(conf)
if ((not options.force) and (os.path.isdir(conf.project_dir))):
die('project directory exists: %s; use force option' % conf.project_dir)
die('project dir exists: %s; use force option' % conf.project_dir)
else:
if os.path.isdir(conf.project_dir):
shutil.rmtree(conf.project_dir)
os.mkdir(conf.project_dir)
conf.dump(filename=os.path.join(conf.project_dir,'seiscloud.config'))
src,dst=conf.catalog_fn,os.path.join(conf.project_dir,'catalog.pf')
shutil.copyfile(src, dst)
conf.dump(filename=os.path.join(conf.project_dir, 'seiscloud.config'))
print('Project directory prepared "%s"' % conf.project_dir)
dst = os.path.join(conf.project_dir, 'catalog.pf')
if conf.catalog_origin == 'file':
src = conf.catalog_fn
shutil.copyfile(src, dst)
else:
if conf.catalog_origin == 'globalcmt':
orig_catalog = catalog.GlobalCMT()
else: # geofon
orig_catalog = catalog.Geofon()
events = orig_catalog.get_events(
time_range=(conf.tmin, conf.tmax),
magmin=conf.magmin,
latmin=conf.latmin,
latmax=conf.latmax,
lonmin=conf.lonmin,
lonmax=conf.lonmax)
selevents = [ev for ev in events if ev.magnitude <= conf.magmax]
model.dump_events(selevents, dst)
print('Project directory prepared "%s"' % conf.project_dir)
def command_matrix(args):
@ -206,7 +214,7 @@ def command_matrix(args):
parser, options, args = cl_parse('matrix', args, setup)
if len(args)!=1:
if len(args) != 1:
help_and_die(parser, 'missing argument')
else:
fn_config = args[0]
@ -220,56 +228,60 @@ def command_matrix(args):
if not os.path.isdir(conf.project_dir):
die('project directory missing: %s' % conf.project_dir)
simmat_temporal_fn=os.path.join(conf.project_dir,'simmat_temporal.npy')
simmat_temporal_fn = os.path.join(conf.project_dir, 'simmat_temporal.npy')
if ((not options.force) and (os.path.isfile(simmat_temporal_fn))):
die('similarity matrix exists: %s; use force option' % simmat_temporal_fn)
die('similarity matrix exists: %s; use force option'
% simmat_temporal_fn)
try:
allevents=model.load_events(conf.catalog_fn)
except:
die('catalog not readable: %s' % conf.catalog_fn)
if os.path.isfile(conf.catalog_fn):
allevents = model.load_events(conf.catalog_fn)
else:
die('catalog missing: %s' % conf.catalog_fn)
if conf.sw_simmat:
if not os.path.isfile(conf.sim_mat_fn):
die('similarity matrix missing: %s' % conf.sim_mat_fn)
if conf.sim_mat_type=='binary':
try:
simmat=load_similarity_matrix(conf.sim_mat_fn)
except:
if conf.sim_mat_type == 'binary':
if os.path.isfile(conf.sim_mat_fn):
simmat = sccluster.load_similarity_matrix(conf.sim_mat_fn)
else:
die('cannot read similarity matrix: %s' % conf.sim_mat_fn)
else:
die('ascii format for similarity matrix not yet implemented')
if len(allevents)!=len(simmat):
print (len(allevents),len(simmat))
die('clustering stopped, number of events differs from matrix size')
if len(allevents) != len(simmat):
print(len(allevents), len(simmat))
die('clustering stopped, number of events ' +
'differs from matrix size')
new_catalog_fn=os.path.join(conf.project_dir,'events_to_be_clustered.pf')
model.dump_events(allevents,new_catalog_fn)
new_catalog_fn = os.path.join(conf.project_dir,
'events_to_be_clustered.pf')
model.dump_events(allevents, new_catalog_fn)
else:
if conf.metric in config.acceptable_mt_based_metrics:
events=[ev for ev in allevents if ev.moment_tensor is not None]
events = [ev for ev in allevents if ev.moment_tensor is not None]
else:
events=[ev for ev in allevents]
new_catalog_fn=os.path.join(conf.project_dir,'events_to_be_clustered.pf')
model.dump_events(events,new_catalog_fn)
events = [ev for ev in allevents]
new_catalog_fn = os.path.join(conf.project_dir,
'events_to_be_clustered.pf')
model.dump_events(events, new_catalog_fn)
simmat=sccluster.compute_similarity_matrix(events, conf.metric)
simmat = sccluster.compute_similarity_matrix(events, conf.metric)
sccluster.save_similarity_matrix(simmat,simmat_temporal_fn)
sccluster.save_similarity_matrix(simmat, simmat_temporal_fn)
simmat_fig_fn=os.path.join(conf.project_dir,\
'simmat_temporal.'+conf.figure_format)
simmat_fig_fn = os.path.join(conf.project_dir,
'simmat_temporal.'+conf.figure_format)
if options.view and options.savefig:
scplot.view_and_savefig_similarity_matrix(simmat,simmat_fig_fn,
scplot.view_and_savefig_similarity_matrix(simmat, simmat_fig_fn,
'Sorted chronologically')
else:
if options.view:
scplot.view_similarity_matrix(simmat,'Sorted chronologically')
scplot.view_similarity_matrix(simmat, 'Sorted chronologically')
if options.savefig:
scplot.savefig_similarity_matrix(simmat,simmat_fig_fn,
scplot.savefig_similarity_matrix(simmat, simmat_fig_fn,
'Sorted chronologically')
print('Similarity matrix computed and stored as "%s"' % simmat_temporal_fn)
@ -277,7 +289,6 @@ def command_matrix(args):
print('Similarity matrix figure saved as "%s"' % simmat_fig_fn)
def command_cluster(args):
'''
Execution of command cluster
@ -299,7 +310,7 @@ def command_cluster(args):
parser, options, args = cl_parse('cluster', args, setup)
if len(args)!=1:
if len(args) != 1:
help_and_die(parser, 'missing argument')
else:
fn_config = args[0]
@ -313,7 +324,7 @@ def command_cluster(args):
if not os.path.isdir(conf.project_dir):
die('project directory missing: %s' % conf.project_dir)
resdir=os.path.join(conf.project_dir,'clustering_results')
resdir = os.path.join(conf.project_dir, 'clustering_results')
if not(options.force):
if (os.path.isdir(resdir)):
die('clustering result directory exists; use force option')
@ -322,51 +333,54 @@ def command_cluster(args):
shutil.rmtree(resdir)
os.mkdir(resdir)
simmat_temporal_fn=os.path.join(conf.project_dir,'simmat_temporal.npy')
simmat_temporal_fn = os.path.join(conf.project_dir, 'simmat_temporal.npy')
if not os.path.isfile(simmat_temporal_fn):
die('similarity matrix does not exists: %s; '+\
die('similarity matrix does not exists: %s; ' +
'use seiscloud matrix first' % simmat_temporal_fn)
new_catalog_fn=os.path.join(conf.project_dir,'events_to_be_clustered.pf')
new_catalog_fn = os.path.join(conf.project_dir,
'events_to_be_clustered.pf')
if not os.path.isfile(new_catalog_fn):
die('catalog of selected events does not exists: %s; '+\
die('catalog of selected events does not exists: %s; ' +
'use seiscloud matrix first' % new_catalog_fn)
simmat_temp=sccluster.load_similarity_matrix(simmat_temporal_fn)
events=model.load_events(new_catalog_fn)
simmat_temp = sccluster.load_similarity_matrix(simmat_temporal_fn)
events = model.load_events(new_catalog_fn)
eventsclusters = sccluster.dbscan(simmat_temp,
conf.dbscan_nmin, conf.dbscan_eps)
clusters = sccluster.get_clusters(events, eventsclusters)
sccluster.save_all(events,eventsclusters,clusters,conf,resdir)
simmat_clus=sccluster.get_simmat_clustered(events,eventsclusters,clusters,\
conf,resdir,simmat_temp)
sccluster.save_all(events, eventsclusters, clusters, conf, resdir)
simmat_clus = sccluster.get_simmat_clustered(events, eventsclusters,
clusters, conf, resdir,
simmat_temp)
simmat_clustered_fn=os.path.join(conf.project_dir,'simmat_clustered.npy')
sccluster.save_similarity_matrix(simmat_clus,simmat_clustered_fn)
simmat_clustered_fn = os.path.join(conf.project_dir,
'simmat_clustered.npy')
sccluster.save_similarity_matrix(simmat_clus, simmat_clustered_fn)
print('I run seiscloud for the project in "%s"' % conf.project_dir)
print(str(len(clusters)-1)+' cluster(s) found')
simmat_fig_fn=os.path.join(conf.project_dir,\
'simmat_clustered.'+conf.figure_format)
simmat_fig_fn = os.path.join(conf.project_dir,
'simmat_clustered.'+conf.figure_format)
if options.view and options.savefig:
scplot.view_and_savefig_similarity_matrix(simmat_clus,simmat_fig_fn,
scplot.view_and_savefig_similarity_matrix(simmat_clus, simmat_fig_fn,
'Sorted after clustering')
else:
if options.view:
scplot.view_similarity_matrix(simmat_clus,'Sorted after clustering')
scplot.view_similarity_matrix(simmat_clus,
'Sorted after clustering')
if options.savefig:
scplot.savefig_similarity_matrix(simmat_clus,simmat_fig_fn,
scplot.savefig_similarity_matrix(simmat_clus, simmat_fig_fn,
'Sorted after clustering')
print('Similarity matrix after clustering computed and stored as "%s"'
% simmat_clustered_fn)
% simmat_clustered_fn)
if options.savefig:
print('Similarity matrix figure saved as "%s"' % simmat_fig_fn)
def command_plot(args):
'''
Execution of command plot
@ -380,7 +394,7 @@ def command_plot(args):
parser, options, args = cl_parse('plot', args, setup)
if len(args)!=1:
if len(args) != 1:
help_and_die(parser, 'missing argument')
else:
fn_config = args[0]
@ -394,12 +408,12 @@ def command_plot(args):
if not os.path.isdir(conf.project_dir):
die('project directory missing: %s' % conf.project_dir)
resdir=os.path.join(conf.project_dir,'clustering_results')
resdir = os.path.join(conf.project_dir, 'clustering_results')
if not os.path.isdir(resdir):
die('clustering results missing: %s' % resdir)
plotdir=os.path.join(conf.project_dir,'clustering_plots')
resdir=os.path.join(conf.project_dir,'clustering_results')
plotdir = os.path.join(conf.project_dir, 'clustering_plots')
resdir = os.path.join(conf.project_dir, 'clustering_results')
if not(options.force):
if (os.path.isdir(plotdir)):
die('clustering plot directory exists; use force option')
@ -408,27 +422,30 @@ def command_plot(args):
shutil.rmtree(plotdir)
os.mkdir(plotdir)
simmat_temporal_fn=os.path.join(conf.project_dir,'simmat_temporal.npy')
simmat_clustered_fn=os.path.join(conf.project_dir,'simmat_clustered.npy')
simmat_temporal_fn = os.path.join(conf.project_dir, 'simmat_temporal.npy')
simmat_clustered_fn = os.path.join(conf.project_dir,
'simmat_clustered.npy')
if not os.path.isfile(simmat_temporal_fn):
die('similarity matrix does not exists: %s; '+\
die('similarity matrix does not exists: %s; ' +
'use seiscloud matrix first' % simmat_temporal_fn)
if not os.path.isfile(simmat_clustered_fn):
die('similarity matrix does not exists: %s; '+\
die('similarity matrix does not exists: %s; ' +
'use seiscloud matrix first' % simmat_clustered_fn)
new_catalog_fn=os.path.join(conf.project_dir,'events_to_be_clustered.pf')
new_catalog_fn = os.path.join(conf.project_dir,
'events_to_be_clustered.pf')
if not os.path.isfile(new_catalog_fn):
die('catalog of selected events does not exists: %s; '+\
'use seiscloud matrix and seiscloud cluster first' % new_catalog_fn)
die('catalog of selected events does not exists: %s; ' +
'use seiscloud matrix and seiscloud cluster first'
% new_catalog_fn)
events=model.load_events(new_catalog_fn)
events = model.load_events(new_catalog_fn)
eventsclusters = sccluster.load_obj(
os.path.join(resdir,'processed.eventsclusters'))
clusters = sccluster.load_obj(
os.path.join(resdir,'processed.clusters'))
os.path.join(resdir, 'processed.eventsclusters'))
clusters = sccluster.load_obj(
os.path.join(resdir, 'processed.clusters'))
scplot.plot_all(events,eventsclusters,clusters,conf,plotdir)
scplot.plot_all(events, eventsclusters, clusters, conf, plotdir)
print('Seiscloud plots prepared in "%s"' % plotdir)

@ -1,9 +1,12 @@
'''This module provides basic cluster processing for seismic events.'''
import collections, operator
import math, os, sys, pickle
import collections
import operator
import math
import os
import pickle
import numpy as num
from pyrocko import moment_tensor, orthodrome, model, io
from pyrocko import moment_tensor, orthodrome, model
epsilon = 1e-6
km = 1000.
@ -28,7 +31,6 @@ class ClusterError(Exception):
pass
def save_obj(obj, name):
'''
Save an object (clustering results)
@ -37,7 +39,6 @@ def save_obj(obj, name):
pickle.dump(obj, f, pickle.HIGHEST_PROTOCOL)
def load_obj(name):
'''
Load an object (clustering results)
@ -46,7 +47,6 @@ def load_obj(name):
return pickle.load(f)
def dbscan(simmat, nmin, eps):
'''
Apply DBSCAN algorithm, reading a similarity matrix and returning a list of
@ -130,7 +130,7 @@ def dbscan(simmat, nmin, eps):
# resorting data clusters (noise remains as -1)
clustersizes = []
for icl in range(n_clusters):
lencl=len ([ev for ev in eventsclusters if ev==icl])
lencl = len([ev for ev in eventsclusters if ev == icl])
clustersizes.append([icl, lencl])
# for icl in range(n_clusters):
# clustersizes.append([icl, 0])
@ -474,28 +474,26 @@ def compute_similarity_matrix(events, metric):
return simmat
def get_simmat_clustered(events,eventsclusters,clusters,conf,
resdir,simmat_temp):
def get_simmat_clustered(events, eventsclusters, clusters, conf,
resdir, simmat_temp):
'''
Compute and return a similarity matrix after clustering
'''
nev=len(events)
clevs=[]
for iev,ev in enumerate(events):
clevs.append([eventsclusters[iev],iev])
nev = len(events)
clevs = []
for iev, ev in enumerate(events):
clevs.append([eventsclusters[iev], iev])
clevs.sort(key=operator.itemgetter(0))
simmat2 = num.zeros((nev,nev))
for i,clevi in enumerate(clevs):
indi=clevi[1]
for j,clevj in enumerate(clevs):
indj=clevj[1]
simmat2[i, j] = simmat_temp[indi,indj]
simmat2 = num.zeros((nev, nev))
for i, clevi in enumerate(clevs):
indi = clevi[1]
for j, clevj in enumerate(clevs):
indj = clevj[1]
simmat2[i, j] = simmat_temp[indi, indj]
return simmat2
def load_similarity_matrix(fname):
'''
Load a binary similarity matrix from file
@ -505,35 +503,34 @@ def load_similarity_matrix(fname):
return simmat
def save_similarity_matrix(simmat,fname):
def save_similarity_matrix(simmat, fname):
'''
Save a binary similarity matrix from file
'''
num.save(fname,simmat)
num.save(fname, simmat)
def save_all(events,eventsclusters,clusters,conf,resdir):
def save_all(events, eventsclusters, clusters, conf, resdir):
'''
Save all results of the clustering analysis
'''
# save events of each cluster
for cluster_id in clusters:
wished_events=[]
fn=os.path.join(resdir,'cluster.'+str(cluster_id)+'.events.pf')
for iev,evcl in enumerate(eventsclusters):
if evcl==cluster_id:
wished_events = []
fn = os.path.join(resdir, 'cluster.'+str(cluster_id)+'.events.pf')
for iev, evcl in enumerate(eventsclusters):
if evcl == cluster_id:
wished_events.append(events[iev])
model.dump_events(wished_events,fn)
model.dump_events(wished_events, fn)
# save clusters
fn=os.path.join(resdir,'processed.clusters')
fn = os.path.join(resdir, 'processed.clusters')
save_obj(clusters, fn)
# save eventsclusters
fn=os.path.join(resdir,'processed.eventsclusters')
fn = os.path.join(resdir, 'processed.eventsclusters')
save_obj(eventsclusters, fn)
# save median of clusters

@ -1,93 +1,110 @@
from pyrocko.guts import Object, Float, Int, String, Bool, List, Tuple, Dict
import os
import sys
from pyrocko.guts import Object, Float, Int, String, Bool
acceptable_metrics=['kagan_angle','mt_l1norm','mt_l2norm','mt_cos',\
'mt_weighted_cos','principal_axis',\
'hypocentral','epicentral','temporal']
acceptable_metrics = ['kagan_angle', 'mt_l1norm', 'mt_l2norm', 'mt_cos',
'mt_weighted_cos', 'principal_axis',
'hypocentral', 'epicentral', 'temporal']
acceptable_mt_based_metrics=['kagan_angle','mt_l1norm','mt_l2norm','mt_cos',\
'mt_weighted_cos','principal_axis']
acceptable_mt_based_metrics = ['kagan_angle', 'mt_l1norm', 'mt_l2norm',
'mt_cos', 'mt_weighted_cos', 'principal_axis']
#acceptable_sortings=['size','north','east','down','dc','clvd','iso']
acceptable_sim_mat_types = ['ascii', 'binary']
acceptable_sim_mat_types=['ascii','binary']
acceptable_figure_formats = ['png', 'pdf']
acceptable_figure_formats=['png','pdf']
acceptable_catalog_origins = ['globalcmt', 'geofon', 'file']
class SeiscloudConfig(Object):
project_dir = String.T(
help='Project directory',default='./seiscloud_example_project')
catalog_fn = String.T(
help='Event file name',default='../examples/globalcmt.nchile.pf')
dbscan_eps = Float.T(
help='Epsilon parameter of DBSCAN',default=0.10)
dbscan_nmin = Int.T(
help='Nmin parameter of DBSCAN',default=20)
sw_simmat = Bool.T(
help='Switch to use a precalculated similarity matrix',default=False)
metric = String.T(
help='Metric definition',default='kagan_angle')
sim_mat_fn = String.T(
help='Name of the similarity file name',default='simmat.npy')
sim_mat_type = String.T(
help='Name of the similarity file name',default='binary')
weight_mnn = Float.T(
help='Weight of the Mnn component in the distance computation',default=1.0)
weight_mee = Float.T(
help='Weight of the Mee component in the distance computation',default=1.0)
weight_mdd = Float.T(
help='Weight of the Mdd component in the distance computation',default=1.0)
weight_mne = Float.T(
help='Weight of the Mne component in the distance computation',default=1.0)
weight_mnd = Float.T(
help='Weight of the Mnd component in the distance computation',default=1.0)
weight_med = Float.T(
help='Weight of the Med component in the distance computation',default=1.0)
tmin = String.T(
help='Minimum time',default='2000-01-01 00:00:00.000')
tmax = String.T(
help='Maximum time',default='2018-01-01 00:00:00.000')
time_window = Float.T(
help='Window length (in days) for temporal evolution of clusters',default=10.)
time_window = String.T(
help='Window length (in days) for temporal evolution of clusters',default=10.)
latmin = Float.T(
help='Minimum longitude (deg)',default=0.)
latmax = Float.T(
help='Maximum longitude (deg)',default=1.)
lonmin = Float.T(
help='Minimum longitude (deg)',default=0.)
lonmax = Float.T(
help='Maximum longitude (deg)',default=1.)
depthmin = Float.T(
help='Minimum depth (m)',default=0.)
depthmax = Float.T(
help='Maximum depth (m)',default=700000.)
magmin = Float.T(
help='Minimum magnitude',default=0.)
magmax = Float.T(
help='Maximum magnitude',default=10.)
euclidean_max = Float.T(
help='Maximum considered spatial distance',default=1000000.)
intertime_max = Float.T(
help='Maximum considered time based distance (s)',default=86400.)
figure_format = String.T(
help='Format of output figures (pdf|png)',default='png')
map_radius = Float.T(
help='Radius of map plots (m); if None, it is internally calculated',
project_dir = String.T(
help='Project directory',
default='./seiscloud_example_project')
catalog_origin = String.T(
help='Origin of seismic catalog (globalcmt, geofon, file)',
default='globalcmt')
catalog_fn = String.T(
help='Event file name',
default='none.pf')
dbscan_eps = Float.T(
help='Epsilon parameter of DBSCAN', default=0.10)
dbscan_nmin = Int.T(
help='Nmin parameter of DBSCAN', default=20)
sw_simmat = Bool.T(
help='Switch to use a precalculated similarity matrix',
default=False)
metric = String.T(
help='Metric definition', default='kagan_angle')
sim_mat_fn = String.T(
help='Name of the similarity file name',
default='simmat.npy')
sim_mat_type = String.T(
help='Name of the similarity file name', default='binary')
weight_mnn = Float.T(
help='Weight of Mnn component in the distance computation',
default=1.0)
weight_mee = Float.T(
help='Weight of Mee component in the distance computation',
default=1.0)
weight_mdd = Float.T(
help='Weight of Mdd component in the distance computation',
default=1.0)
weight_mne = Float.T(
help='Weight of Mne component in the distance computation',
default=1.0)
weight_mnd = Float.T(
help='Weight of Mnd component in the distance computation',
default=1.0)
weight_med = Float.T(
help='Weight of Med component in the distance computation',
default=1.0)
tmin = String.T(
help='Minimum time', default='2000-01-01 00:00:00.000')
tmax = String.T(
help='Maximum time', default='2018-01-01 00:00:00.000')
time_window = Float.T(
help='Window length (days) for time evolution of clusters',
default=10.)
time_window = String.T(
help='Window length (days) for time evolution of clusters',
default=10.)
latmin = Float.T(
help='Minimum longitude (deg)', default=-25.)
latmax = Float.T(
help='Maximum longitude (deg)', default=-18.)
lonmin = Float.T(
help='Minimum longitude (deg)', default=-72.)
lonmax = Float.T(
help='Maximum longitude (deg)', default=-67.)
depthmin = Float.T(
help='Minimum depth (m)', default=0.)
depthmax = Float.T(
help='Maximum depth (m)', default=700000.)
magmin = Float.T(
help='Minimum magnitude', default=0.)
magmax = Float.T(
help='Maximum magnitude', default=10.)
euclidean_max = Float.T(
help='Maximum considered spatial distance',
default=1000000.)
intertime_max = Float.T(
help='Maximum considered time based distance (s)',
default=86400.)
figure_format = String.T(
help='Format of output figures (pdf|png)',
default='png')
map_radius = Float.T(
help='Radius of map plots (m); if None, it is calculated',
default=100000.)
sw_findcenters = Bool.T(
help='Maximum considered spatial distance',default=False)
sw_filterevent = Bool.T(
help='Maximum considered spatial distance',default=False)
sw_cumulus = Bool.T(
help='Maximum considered spatial distance',default=False)
sw_findcenters = Bool.T(
help='Maximum considered spatial distance', default=False)
sw_filterevent = Bool.T(
help='Maximum considered spatial distance', default=False)
sw_cumulus = Bool.T(
help='Maximum considered spatial distance', default=False)
sw_include_edge = Bool.T(
help='Maximum considered spatial distance',default=False)
help='Maximum considered spatial distance', default=False)
def generate_default_config():
@ -95,11 +112,7 @@ def generate_default_config():
return config
def check(conf):
# if conf.cluster_sorting not in acceptable_sortings:
# print('cluster sorting not acceptable: %s' % conf.cluster_sorting)
# sys.exit()
if conf.metric not in acceptable_metrics:
print('metric not acceptable: %s' % conf.metric)
sys.exit()
@ -109,3 +122,6 @@ def check(conf):
if conf.figure_format not in acceptable_figure_formats:
print('figure format not acceptable: %s' % conf.figure_format)
sys.exit()
if conf.catalog_origin not in acceptable_catalog_origins:
print('catalog origin not acceptable: %s' % conf.catalog_origin)
sys.exit()

@ -1,68 +1,67 @@
'''This module provides basic cluster processing for seismic events.'''
import sys, os, datetime, math
import sys
import os
import datetime
import math
import matplotlib.pyplot as plt
import numpy as num
from pyrocko import util, model, gmtpy
from pyrocko import model, gmtpy
from pyrocko.automap import Map
from pyrocko import orthodrome as od
from pyrocko import moment_tensor as pmt
from matplotlib import collections as mc
from matplotlib import dates, colors
epsilon = 1e-6
km = 1000.
def CartesianToLambert(e,n,u):
def CartesianToLambert(e, n, u):
'''
Convert axis orientation to coordinate for axis plot
(using Lambert azimuthal equal-area projection)
'''
# Using Lambert azimuthal equal-area projection
x=(1/math.sqrt(2.))*e*math.sqrt(2/(1-u))
y=(1/math.sqrt(2.))*n*math.sqrt(2/(1-u))
return x,y
x = (1/math.sqrt(2.))*e*math.sqrt(2/(1-u))
y = (1/math.sqrt(2.))*n*math.sqrt(2/(1-u))
return x, y
def get_axis_coords(events):
'''
Get axis plot coordinates for all events
'''
xs,ys=[],[]
xs, ys = [], []
for ev in events:
pax=ev.moment_tensor.p_axis()
tax=ev.moment_tensor.t_axis()
bax=ev.moment_tensor.null_axis()
p=[pax[0,0],pax[0,1],pax[0,2]]
t=[tax[0,0],tax[0,1],tax[0,2]]
b=[bax[0,0],bax[0,1],bax[0,2]]
if p[2]<0:
p=[-p[0],-p[1],-p[2]]
if t[2]<0:
t=[-t[0],-t[1],-t[2]]
if b[2]<0:
b=[-b[0],-b[1],-b[2]]
pax = ev.moment_tensor.p_axis()
tax = ev.moment_tensor.t_axis()
bax = ev.moment_tensor.null_axis()
p = [pax[0, 0], pax[0, 1], pax[0, 2]]
t = [tax[0, 0], tax[0, 1], tax[0, 2]]
b = [bax[0, 0], bax[0, 1], bax[0, 2]]
px,py=CartesianToLambert(p[1],p[0],-p[2])
tx,ty=CartesianToLambert(t[1],t[0],-t[2])
bx,by=CartesianToLambert(b[1],b[0],-b[2])
if p[2] < 0:
p = [-p[0], -p[1], -p[2]]
if t[2] < 0:
t = [-t[0], -t[1], -t[2]]
if b[2] < 0:
b = [-b[0], -b[1], -b[2]]
xs.append([px,tx,bx])
ys.append([py,ty,by])
px, py = CartesianToLambert(p[1], p[0], -p[2])
tx, ty = CartesianToLambert(t[1], t[0], -t[2])
bx, by = CartesianToLambert(b[1], b[0], -b[2])
return xs,ys
xs.append([px, tx, bx])
ys.append([py, ty, by])
return xs, ys
def getCoordinatesHudsonPlot(mts):
'''
Get Hudson plot coordinates for all events
'''
us,vs=[],[]
us, vs = [], []
for mt in mts:
mt = pmt.values_to_matrix(mt)
eig_m = pmt.eigh_check(mt)[0]
@ -74,61 +73,63 @@ def getCoordinatesHudsonPlot(mts):
return us, vs
def get_triangle_coords(events):
'''
Get triangle plot coordinates for all events
'''
xs,ys,cs=[],[],[]
xs, ys, cs = [], [], []
for ev in events:
pax=ev.moment_tensor.p_axis()
tax=ev.moment_tensor.t_axis()
bax=ev.moment_tensor.null_axis()
p=[pax[0,0],pax[0,1],pax[0,2]]
t=[tax[0,0],tax[0,1],tax[0,2]]
b=[bax[0,0],bax[0,1],bax[0,2]]
pax = ev.moment_tensor.p_axis()
tax = ev.moment_tensor.t_axis()
bax = ev.moment_tensor.null_axis()
p = [pax[0, 0], pax[0, 1], pax[0, 2]]
t = [tax[0, 0], tax[0, 1], tax[0, 2]]
b = [bax[0, 0], bax[0, 1], bax[0, 2]]
# t,p,b=sds2tpb(ev.strike,ev.dip,ev.rake)
a3526=35.26*math.pi/180.
a3526 = 35.26*math.pi/180.
deltab=math.asin(abs(b[2]))
deltat=math.asin(abs(t[2]))
deltap=math.asin(abs(p[2]))
deltab = math.asin(abs(b[2]))
deltat = math.asin(abs(t[2]))
deltap = math.asin(abs(p[2]))
psi=math.atan(math.sin(deltat)/math.sin(deltap))-0.25*math.pi
den=math.sin(a3526)*math.sin(deltab)+math.cos(a3526)*math.cos(deltab)*math.cos(psi)
psi = math.atan(math.sin(deltat)/math.sin(deltap))-0.25*math.pi
den = math.sin(a3526)*math.sin(deltab) +\
math.cos(a3526)*math.cos(deltab)*math.cos(psi)
if abs(den)<=epsilon:
den=epsilon
if abs(den) <= epsilon:
den = epsilon
x=math.cos(deltab)*math.sin(psi)/den
y=(math.cos(a3526)*math.sin(deltab)-math.sin(a3526)*math.cos(deltab)*math.cos(psi))/den
s2p,s2t,s2b=(math.sin(deltap))**2,(math.sin(deltat))**2,(math.sin(deltab))**2
c=(s2t,s2b,s2p)
x = math.cos(deltab)*math.sin(psi)/den
y = (math.cos(a3526)*math.sin(deltab) -
math.sin(a3526)*math.cos(deltab)*math.cos(psi))/den
s2p = (math.sin(deltap))**2
s2t = (math.sin(deltat))**2
s2b = (math.sin(deltab))**2
c = (s2t, s2b, s2p)
xs.append(x)
ys.append(y)
cs.append(c)
return xs,ys,cs
return xs, ys, cs
def view_and_savefig_similarity_matrix(simmat,figname,title):
def view_and_savefig_similarity_matrix(simmat, figname, title):
'''
View and save a similarity matrix
'''
nev=len(simmat)
nev = len(simmat)
f = plt.figure(1,figsize=(12,10), facecolor='w', edgecolor='k')
f = plt.figure(1, figsize=(12, 10), facecolor='w', edgecolor='k')
grid = plt.GridSpec(10, 10, wspace=0.2, hspace=0.2)
plt.subplot(grid[0:9, 0:9])
plt.imshow(simmat,interpolation='none',cmap='GnBu_r')
plt.xlim(xmax = nev, xmin = 0)
plt.ylim(ymax = nev, ymin = 0)
plt.imshow(simmat, interpolation='none', cmap='GnBu_r')
plt.xlim(xmax=nev, xmin=0)
plt.ylim(ymax=nev, ymin=0)
plt.xlabel("Event number")
plt.ylabel("Event number")
@ -137,21 +138,20 @@ def view_and_savefig_similarity_matrix(simmat,figname,title):
plt.show()
def view_similarity_matrix(simmat,title):
def view_similarity_matrix(simmat, title):
'''
View (only) a similarity matrix
'''
nev=len(simmat)
nev = len(simmat)
f = plt.figure(1,figsize=(12,10), facecolor='w', edgecolor='k')
plt.figure(1, figsize=(12, 10), facecolor='w', edgecolor='k')
grid = plt.GridSpec(10, 10, wspace=0.2, hspace=0.2)
plt.subplot(grid[0:9, 0:9])
plt.imshow(simmat,interpolation='none',cmap='GnBu_r')
plt.xlim(xmax = nev, xmin = 0)
plt.ylim(ymax = nev, ymin = 0)
plt.imshow(simmat, interpolation='none', cmap='GnBu_r')
plt.xlim(xmax=nev, xmin=0)
plt.ylim(ymax=nev, ymin=0)
plt.xlabel("Event number")
plt.ylabel("Event number")
@ -159,21 +159,20 @@ def view_similarity_matrix(simmat,title):
plt.show()
def savefig_similarity_matrix(simmat,figname,title):
def savefig_similarity_matrix(simmat, figname, title):
'''
Save (only) a similarity matrix
'''
nev=len(simmat)
nev = len(simmat)
f = plt.figure(1,figsize=(12,10), facecolor='w', edgecolor='k')
f = plt.figure(1, figsize=(12, 10), facecolor='w', edgecolor='k')
grid = plt.GridSpec(10, 10, wspace=0.2, hspace=0.2)
plt.subplot(grid[0:9, 0:9])
plt.imshow(simmat,interpolation='none',cmap='GnBu_r')
plt.xlim(xmax = nev, xmin = 0)
plt.ylim(ymax = nev, ymin = 0)
plt.imshow(simmat, interpolation='none', cmap='GnBu_r')
plt.xlim(xmax=nev, xmin=0)
plt.ylim(ymax=nev, ymin=0)
plt.xlabel("Event number")
plt.ylabel("Event number")
@ -181,68 +180,64 @@ def savefig_similarity_matrix(simmat,figname,title):
f.savefig(figname)
def cluster_to_color(cluster_id):
'''
Given a cluster id provide the corresponding color
'''
mycolors=['black','red','blue','green','darkviolet','gold','darkorange',\
'dodgerblue','brown','lightseagreen','plum','lawngreen',\
'palevioletred','royalblue','limegreen','indigo']
my_def_color='gainsboro'
if cluster_id>(len(mycolors)-2):
color=def_color
mycolors = ['black', 'red', 'blue', 'green', 'darkviolet', 'gold',
'darkorange', 'dodgerblue', 'brown', 'lightseagreen', 'plum',
'lawngreen', 'palevioletred', 'royalblue', 'limegreen',
'indigo']
my_def_color = 'gainsboro'
if cluster_id > (len(mycolors)-2):
color = my_def_color
else:
color=mycolors[cluster_id+1]
color = mycolors[cluster_id+1]
return color
def color2rgb(col):
'''
Return a red/green/blue string for GMT for a given color name
'''
colarray = colors.to_rgb(col)
r,g,b=int(255*colarray[0]),int(255*colarray[1]),int(255*colarray[2])
rgb=str(r)+'/'+str(g)+'/'+str(b)
r, g, b = int(255*colarray[0]), int(255*colarray[1]), int(255*colarray[2])
rgb = str(r)+'/'+str(g)+'/'+str(b)
return rgb
def plot_spatial(events,eventsclusters,clusters,conf,plotdir):
def plot_spatial(events, eventsclusters, clusters, conf, plotdir):
'''
Plot map of seismicity clusters
'''
lats=[ev.lat for ev in events]
lons=[ev.lon for ev in events]
deps=[ev.depth for ev in events]
colors = [cluster_to_color(clid) for clid in eventsclusters]
lats = [ev.lat for ev in events]
lons = [ev.lon for ev in events]
# deps = [ev.depth for ev in events]
# colors = [cluster_to_color(clid) for clid in eventsclusters]
if conf.sw_filterevent:
latmin,latmax=cong.latmin,conf.latmax
lonmin,lonmax=cong.lonmin,conf.lonmax
depmin,depmax=cong.depthmin,conf.depthmax
if latmin>latmax:
print ('cases over lon +-180 still to be implemented')
latmin, latmax = conf.latmin, conf.latmax
lonmin, lonmax = conf.lonmin, conf.lonmax
# depmin, depmax = conf.depthmin, conf.depthmax
if latmin > latmax:
print('cases over lon +-180 still to be implemented')
sys.exit()
center=model.event(0.5*(latmin+latmax),0.5*(lonmin+lonmax))
center = model.event(0.5*(latmin+latmax), 0.5*(lonmin+lonmax))
else:
latmin=min([ev.lat for ev in events])-0.1
latmax=max([ev.lat for ev in events])+0.1
lonmin=min([ev.lon for ev in events])-0.1
lonmax=max([ev.lon for ev in events])+0.1
depmin=0.*km
depmax=1.05*max([ev.depth for ev in events])
center=od.Loc(0.5*(latmin+latmax),0.5*(lonmin+lonmax))
latmin, latmax = min(lats)-0.1, max(lats)+0.1
lonmin, lonmax = min(lons)-0.1, max(lons)+0.1
# depmin = 0.*km
# depmax = 1.05*max(deps)
center = od.Loc(0.5*(latmin+latmax), 0.5*(lonmin+lonmax))
# Map size
if conf.map_radius is not None:
safe_radius = conf.map_radius
else:
corners=[od.Loc(latmin,lonmin),od.Loc(latmin,lonmax)]
corners = [od.Loc(latmin, lonmin), od.Loc(latmin, lonmax)]
dist1 = od.distance_accurate50m(center, corners[0])
dist2 = od.distance_accurate50m(center, corners[1])
safe_radius = max(dist1,dist2)
safe_radius = max(dist1, dist2)
# Generate the basic map
m = Map(
@ -261,64 +256,62 @@ def plot_spatial(events,eventsclusters,clusters,conf,plotdir):
show_plates=False)
if conf.sw_filterevent:
rectlons=[lonmin,lonmin,lonmax,lonmax,lonmin]
rectlats=[latmin,latmax,latmax,latmin,latmin]
m.gmt.psxy(in_columns=(rectlons, rectlats), W='thin,0/0/0,dashed', *m.jxyr)
rectlons = [lonmin, lonmin, lonmax, lonmax, lonmin]
rectlats = [latmin, latmax, latmax, latmin, latmin]
m.gmt.psxy(in_columns=(rectlons, rectlats),
W='thin,0/0/0,dashed', *m.jxyr)
# Draw some larger cities covered by the map area
m.draw_cities()
# Events in clusters
for id_cluster in clusters:
col=cluster_to_color(id_cluster)
mylats,mylons=[],[]
for iev,evcl in enumerate(eventsclusters):
if evcl==id_cluster:
col = cluster_to_color(id_cluster)
mylats, mylons = [], []
for iev, evcl in enumerate(eventsclusters):
if evcl == id_cluster:
mylats.append(events[iev].lat)
mylons.append(events[iev].lon)
m.gmt.psxy(in_columns=(mylons, mylats), S='c7p',\
m.gmt.psxy(in_columns=(mylons, mylats), S='c7p',
G=color2rgb(col), *m.jxyr)
figname=os.path.join(plotdir,'plot_map.'+conf.figure_format)
figname = os.path.join(plotdir, 'plot_map.'+conf.figure_format)
m.save(figname)
# m.show()
def plot_spatial_with_dcs(events,eventsclusters,clusters,conf,plotdir):
def plot_spatial_with_dcs(events, eventsclusters, clusters, conf, plotdir):
'''
Plot map of seismicity clusters, with focal mechanisms
'''
lats=[ev.lat for ev in events]
lons=[ev.lon for ev in events]
deps=[ev.depth for ev in events]
colors = [cluster_to_color(clid) for clid in eventsclusters]
lats = [ev.lat for ev in events]
lons = [ev.lon for ev in events]
# deps = [ev.depth for ev in events]
# colors = [cluster_to_color(clid) for clid in eventsclusters]
if conf.sw_filterevent:
latmin,latmax=cong.latmin,conf.latmax
lonmin,lonmax=cong.lonmin,conf.lonmax
depmin,depmax=cong.depthmin,conf.depthmax
if latmin>latmax:
print ('cases over lon +-180 still to be implemented')
latmin, latmax = conf.latmin, conf.latmax
lonmin, lonmax = conf.lonmin, conf.lonmax
# depmin, depmax = conf.depthmin, conf.depthmax
if latmin > latmax:
print('cases over lon +-180 still to be implemented')
sys.exit()
center=model.event(0.5*(latmin+latmax),0.5*(lonmin+lonmax))
center = model.event(0.5*(latmin+latmax), 0.5*(lonmin+lonmax))
else:
latmin=min([ev.lat for ev in events])-0.1
latmax=max([ev.lat for ev in events])+0.1
lonmin=min([ev.lon for ev in events])-0.1
lonmax=max([ev.lon for ev in events])+0.1
depmin=0.*km
depmax=1.05*max([ev.depth for ev in events])
center=od.Loc(0.5*(latmin+latmax),0.5*(lonmin+lonmax))
latmin, latmax = min(lats)-0.1, max(lats)+0.1
lonmin, lonmax = min(lons)-0.1, max(lons)+0.1
# depmin = 0.*km
# depmax = 1.05*max(deps)
center = od.Loc(0.5*(latmin+latmax), 0.5*(lonmin+lonmax))
# Map size
if conf.map_radius is not None:
safe_radius = conf.map_radius
else:
corners=[od.Loc(latmin,lonmin),od.Loc(latmin,lonmax)]
corners = [od.Loc(latmin, lonmin), od.Loc(latmin, lonmax)]
dist1 = od.distance_accurate50m(center, corners[0])
dist2 = od.distance_accurate50m(center, corners[1])
safe_radius = max(dist1,dist2)
safe_radius = max(dist1, dist2)
# Generate the basic map
m = Map(
@ -337,9 +330,10 @@ def plot_spatial_with_dcs(events,eventsclusters,clusters,conf,plotdir):
show_plates=False)
if conf.sw_filterevent:
rectlons=[lonmin,lonmin,lonmax,lonmax,lonmin]
rectlats=[latmin,latmax,latmax,latmin,latmin]
m.gmt.psxy(in_columns=(rectlons, rectlats), W='thin,0/0/0,dashed', *m.jxyr)
rectlons = [lonmin, lonmin, lonmax, lonmax, lonmin]
rectlats = [latmin, latmax, latmax, latmin, latmin]
m.gmt.psxy(in_columns=(rectlons, rectlats),
W='thin,0/0/0,dashed', *m.jxyr)
# Draw some larger cities covered by the map area
m.draw_cities()
@ -349,11 +343,11 @@ def plot_spatial_with_dcs(events,eventsclusters,clusters,conf,plotdir):
beachball_symbol = 'd'
for id_cluster in clusters:
col=cluster_to_color(id_cluster)
g_col=color2rgb(col)
for iev,evcl in enumerate(eventsclusters):
if evcl==id_cluster:
ev=events[iev]
col = cluster_to_color(id_cluster)
g_col = color2rgb(col)
for iev, evcl in enumerate(eventsclusters):
if evcl == id_cluster:
ev = events[iev]
devi = ev.moment_tensor.deviatoric()
beachball_size = 3.*factor_symbl_size
mt = devi.m_up_south_east()
@ -362,16 +356,15 @@ def plot_spatial_with_dcs(events,eventsclusters,clusters,conf,plotdir):
m6 = pmt.to6(mt)
if m.gmt.is_gmt5():
kwargs = dict(
M=True,
S='%s%g' % (beachball_symbol[0],
(beachball_size) / gmtpy.cm))
kwargs = dict(M=True, S='%s%g' %
(beachball_symbol[0],
(beachball_size)/gmtpy.cm))
else:
kwargs = dict(
S='%s%g' % (beachball_symbol[0],
(beachball_size)*2 / gmtpy.cm))
kwargs = dict(S='%s%g' %
(beachball_symbol[0],
(beachball_size)*2 / gmtpy.cm))
data=(ev.lon, ev.lat, 10) + tuple(m6) + (1, 0, 0)
data = (ev.lon, ev.lat, 10) + tuple(m6) + (1, 0, 0)
m.gmt.psmeca(
in_rows=[data],
@ -381,222 +374,218 @@ def plot_spatial_with_dcs(events,eventsclusters,clusters,conf,plotdir):
*m.jxyr,
**kwargs)
figname=os.path.join(plotdir,'plot_map_with_dcs.'+conf.figure_format)
figname = os.path.join(plotdir, 'plot_map_with_dcs.'+conf.figure_format)
m.save(figname)
# m.show()
def plot_tm(events,eventsclusters,clusters,conf,plotdir):
def plot_tm(events, eventsclusters, clusters, conf, plotdir):
'''
Plot magnitude vs time for the eismicity clusters
'''
times=[ev.time for ev in events]
times = [ev.time for ev in events]
orig_dates = [datetime.datetime.fromtimestamp(ev.time) for ev in events]
mpl_dates=dates.date2num(orig_dates)
mags=[ev.magnitude for ev in events]
mpl_dates = dates.date2num(orig_dates)
mags = [ev.magnitude for ev in events]
colors = [cluster_to_color(clid) for clid in eventsclusters]
dates_format = dates.DateFormatter('%Y-%m-%d')
if conf.sw_filterevent:
tmin,tmax=cong.tmin,conf.tmax
magmin,magmax=cong.magmin,conf.magmax
tmin, tmax = conf.tmin, conf.tmax
magmin, magmax = conf.magmin, conf.magmax
else:
if (max(times)-min(times))/86400. > 720.:
dt=86400.
dates_loc=dates.YearLocator()
dt = 86400.
dates_loc = dates.YearLocator()
elif (max(times)-min(times))/86400. > 10.:
dt=86400.
dates_loc=dates.MonthLocator()
dt = 86400.
dates_loc = dates.MonthLocator()
elif (max(times)-min(times))/3600. > 10.:
dt=3600.
dates_loc=dates.DayLocator()
dt = 3600.
dates_loc = dates.DayLocator()
else:
dt=1.
dates_loc=dates.HourLocator()
dt = 1.
dates_loc = dates.HourLocator()
dates_format = dates.DateFormatter('%Y-%m-%d %h:%m:%s')
tmin,tmax=min(times)-dt,max(times)+dt
magmin,magmax=min(mags)-0.1,max(mags)+0.1
dmin=dates.date2num(datetime.datetime.fromtimestamp(tmin))
dmax=dates.date2num(datetime.datetime.fromtimestamp(tmax))
tmin, tmax = min(times)-dt, max(times)+dt