PhaseNet 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- PhaseNet-0.1.0.dist-info/LICENSE +674 -0
- PhaseNet-0.1.0.dist-info/METADATA +30 -0
- PhaseNet-0.1.0.dist-info/RECORD +12 -0
- PhaseNet-0.1.0.dist-info/WHEEL +6 -0
- PhaseNet-0.1.0.dist-info/top_level.txt +1 -0
- phasenet/__init__.py +1 -0
- phasenet/data_reader.py +520 -0
- phasenet/detect_peaks.py +175 -0
- phasenet/model.py +467 -0
- phasenet/predict.py +143 -0
- phasenet/train.py +297 -0
- phasenet/util.py +203 -0
phasenet/predict.py
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import tensorflow as tf
|
|
3
|
+
tf.compat.v1.disable_eager_execution()
|
|
4
|
+
tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)
|
|
5
|
+
import argparse, os, time, logging
|
|
6
|
+
from tqdm import tqdm
|
|
7
|
+
import pandas as pd
|
|
8
|
+
import threading
|
|
9
|
+
import multiprocessing
|
|
10
|
+
from functools import partial
|
|
11
|
+
import pickle
|
|
12
|
+
from model import UNet, ModelConfig
|
|
13
|
+
from data_reader import DataReader_pred, DataReader_mseed
|
|
14
|
+
from util import *
|
|
15
|
+
|
|
16
|
+
def read_args():
|
|
17
|
+
|
|
18
|
+
parser = argparse.ArgumentParser()
|
|
19
|
+
parser.add_argument("--model_dir", help="Checkpoint directory (default: None)")
|
|
20
|
+
parser.add_argument("--data_dir", default="./dataset/waveform_pred/", help="Input file directory")
|
|
21
|
+
parser.add_argument("--data_list", default="./dataset/waveform.csv", help="Input csv file")
|
|
22
|
+
parser.add_argument("--result_dir", default="./results", help="Output directory")
|
|
23
|
+
parser.add_argument("--batch_size", default=20, type=int, help="batch size")
|
|
24
|
+
parser.add_argument("--tp_prob", default=0.3, type=float, help="Probability threshold for P pick")
|
|
25
|
+
parser.add_argument("--ts_prob", default=0.3, type=float, help="Probability threshold for S pick")
|
|
26
|
+
parser.add_argument("--input_mseed", action="store_true", help="mseed format")
|
|
27
|
+
parser.add_argument("--stations", default="./dataset/waveform.csv", help="seismic station info")
|
|
28
|
+
parser.add_argument("--plot_figure", action="store_true", help="If plot figure for test")
|
|
29
|
+
parser.add_argument("--save_prob", action="store_true", help="If save result for test")
|
|
30
|
+
args = parser.parse_args()
|
|
31
|
+
return args
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def pred_fn(args, data_reader, figure_dir=None, result_dir=None, log_dir=None):
|
|
35
|
+
current_time = time.strftime("%y%m%d-%H%M%S")
|
|
36
|
+
if log_dir is None:
|
|
37
|
+
log_dir = os.path.join(args.log_dir, "pred", current_time)
|
|
38
|
+
logging.info("Pred log: %s" % log_dir)
|
|
39
|
+
logging.info("Dataset size: {}".format(data_reader.num_data))
|
|
40
|
+
if not os.path.exists(log_dir):
|
|
41
|
+
os.makedirs(log_dir)
|
|
42
|
+
if (args.plot_figure == True) and (figure_dir is None):
|
|
43
|
+
figure_dir = os.path.join(log_dir, 'figures')
|
|
44
|
+
if not os.path.exists(figure_dir):
|
|
45
|
+
os.makedirs(figure_dir)
|
|
46
|
+
if (args.save_prob == True) and (result_dir is None):
|
|
47
|
+
result_dir = os.path.join(log_dir, 'results')
|
|
48
|
+
if not os.path.exists(result_dir):
|
|
49
|
+
os.makedirs(result_dir)
|
|
50
|
+
|
|
51
|
+
with tf.compat.v1.name_scope('Input_Batch'):
|
|
52
|
+
dataset = data_reader.dataset().prefetch(10)
|
|
53
|
+
if args.input_mseed:
|
|
54
|
+
batch_size = 1
|
|
55
|
+
else:
|
|
56
|
+
batch_size = args.batch_size
|
|
57
|
+
dataset = dataset.batch(batch_size)
|
|
58
|
+
batch = tf.compat.v1.data.make_one_shot_iterator(dataset).get_next()
|
|
59
|
+
|
|
60
|
+
config = ModelConfig(X_shape=data_reader.X_shape)
|
|
61
|
+
with open(os.path.join(log_dir, 'config.log'), 'w') as fp:
|
|
62
|
+
fp.write('\n'.join("%s: %s" % item for item in vars(config).items()))
|
|
63
|
+
|
|
64
|
+
model = UNet(config=config, input_batch=batch, mode="pred")
|
|
65
|
+
sess_config = tf.compat.v1.ConfigProto()
|
|
66
|
+
sess_config.gpu_options.allow_growth = True
|
|
67
|
+
# sess_config.log_device_placement = False
|
|
68
|
+
|
|
69
|
+
with tf.compat.v1.Session(config=sess_config) as sess:
|
|
70
|
+
|
|
71
|
+
saver = tf.compat.v1.train.Saver(tf.compat.v1.global_variables(), max_to_keep=5)
|
|
72
|
+
init = tf.compat.v1.global_variables_initializer()
|
|
73
|
+
sess.run(init)
|
|
74
|
+
|
|
75
|
+
logging.info("restoring models...")
|
|
76
|
+
latest_check_point = tf.train.latest_checkpoint(args.model_dir)
|
|
77
|
+
saver.restore(sess, latest_check_point)
|
|
78
|
+
|
|
79
|
+
if args.plot_figure:
|
|
80
|
+
num_pool = multiprocessing.cpu_count()*2
|
|
81
|
+
elif args.save_prob:
|
|
82
|
+
num_pool = multiprocessing.cpu_count()
|
|
83
|
+
else:
|
|
84
|
+
num_pool = 2
|
|
85
|
+
pool = multiprocessing.Pool(num_pool)
|
|
86
|
+
|
|
87
|
+
fclog = open(os.path.join(log_dir, 'picks.csv'), 'w')
|
|
88
|
+
fclog.write("fname,itp,tp_prob,its,ts_prob\n")
|
|
89
|
+
picks = {}
|
|
90
|
+
|
|
91
|
+
for step in tqdm(range(0, data_reader.num_data, batch_size), desc="Pred"):
|
|
92
|
+
pred_batch, X_batch, fname_batch = sess.run([model.preds, batch[0], batch[1]],
|
|
93
|
+
feed_dict={model.drop_rate: 0,
|
|
94
|
+
model.is_training: False})
|
|
95
|
+
if args.input_mseed:
|
|
96
|
+
fname_batch = [(fname_batch.decode().split('/')[-1].rstrip(".mseed")+"."+data_reader.stations.iloc[i]["station"]).encode()
|
|
97
|
+
for i in range(len(pred_batch))]
|
|
98
|
+
picks_batch = pool.map(partial(postprocessing_thread,
|
|
99
|
+
pred = pred_batch,
|
|
100
|
+
X = X_batch,
|
|
101
|
+
fname = fname_batch,
|
|
102
|
+
result_dir = result_dir,
|
|
103
|
+
figure_dir = figure_dir,
|
|
104
|
+
args=args), range(len(pred_batch)))
|
|
105
|
+
|
|
106
|
+
for i in range(len(fname_batch)):
|
|
107
|
+
row = "{},[{}],[{}],[{}],[{}]".format(fname_batch[i].decode(), " ".join(map(str,picks_batch[i][0][0])), " ".join(map(str,picks_batch[i][0][1])),
|
|
108
|
+
" ".join(map(str,picks_batch[i][1][0])), " ".join(map(str,picks_batch[i][1][1])))
|
|
109
|
+
fclog.write(row+"\n")
|
|
110
|
+
picks[fname_batch[i].decode()]={"itp":picks_batch[i][0][0], "tp_prob":picks_batch[i][0][1], "its":picks_batch[i][1][0], "ts_prob":picks_batch[i][1][1]}
|
|
111
|
+
|
|
112
|
+
fclog.flush()
|
|
113
|
+
|
|
114
|
+
fclog.close()
|
|
115
|
+
with open(os.path.join(log_dir, 'picks.pkl'), 'wb') as fp:
|
|
116
|
+
pickle.dump(picks, fp)
|
|
117
|
+
print("Done")
|
|
118
|
+
|
|
119
|
+
return 0
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def main(args):
|
|
123
|
+
|
|
124
|
+
logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO)
|
|
125
|
+
|
|
126
|
+
with tf.compat.v1.name_scope('create_inputs'):
|
|
127
|
+
|
|
128
|
+
if args.input_mseed:
|
|
129
|
+
data_reader = DataReader_mseed(data_dir=args.data_dir,
|
|
130
|
+
data_list=args.data_list,
|
|
131
|
+
stations=args.stations)
|
|
132
|
+
else:
|
|
133
|
+
data_reader = DataReader_pred(data_dir=args.data_dir,
|
|
134
|
+
data_list=args.data_list)
|
|
135
|
+
|
|
136
|
+
pred_fn(args, data_reader, log_dir=args.result_dir)
|
|
137
|
+
|
|
138
|
+
return
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
if __name__ == '__main__':
|
|
142
|
+
args = read_args()
|
|
143
|
+
main(args)
|
phasenet/train.py
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import tensorflow as tf
|
|
3
|
+
tf.compat.v1.disable_eager_execution()
|
|
4
|
+
tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)
|
|
5
|
+
import argparse, os, time, logging
|
|
6
|
+
from tqdm import tqdm
|
|
7
|
+
import pandas as pd
|
|
8
|
+
import threading
|
|
9
|
+
import multiprocessing
|
|
10
|
+
from functools import partial
|
|
11
|
+
import pickle
|
|
12
|
+
from model import UNet, ModelConfig
|
|
13
|
+
from data_reader import DataReader, DataReader_test
|
|
14
|
+
from util import *
|
|
15
|
+
|
|
16
|
+
def read_args():
|
|
17
|
+
|
|
18
|
+
parser = argparse.ArgumentParser()
|
|
19
|
+
parser.add_argument("--mode", default="train", help="train/train_valid/test/debug")
|
|
20
|
+
parser.add_argument("--epochs", default=100, type=int, help="number of epochs (default: 10)")
|
|
21
|
+
parser.add_argument("--batch_size", default=20, type=int, help="batch size")
|
|
22
|
+
parser.add_argument("--learning_rate", default=0.01, type=float, help="learning rate")
|
|
23
|
+
parser.add_argument("--decay_step", default=-1, type=int, help="decay step")
|
|
24
|
+
parser.add_argument("--decay_rate", default=0.9, type=float, help="decay rate")
|
|
25
|
+
parser.add_argument("--momentum", default=0.9, type=float, help="momentum")
|
|
26
|
+
parser.add_argument("--filters_root", default=8, type=int, help="filters root")
|
|
27
|
+
parser.add_argument("--depth", default=5, type=int, help="depth")
|
|
28
|
+
parser.add_argument("--kernel_size", nargs="+", type=int, default=[7, 1], help="kernel size")
|
|
29
|
+
parser.add_argument("--pool_size", nargs="+", type=int, default=[4, 1], help="pool size")
|
|
30
|
+
parser.add_argument("--drop_rate", default=0, type=float, help="drop out rate")
|
|
31
|
+
parser.add_argument("--dilation_rate", nargs="+", type=int, default=[1, 1], help="dilation rate")
|
|
32
|
+
parser.add_argument("--loss_type", default="cross_entropy", help="loss type: cross_entropy, IOU, mean_squared")
|
|
33
|
+
parser.add_argument("--weight_decay", default=0, type=float, help="weight decay")
|
|
34
|
+
parser.add_argument("--optimizer", default="adam", help="optimizer: adam, momentum")
|
|
35
|
+
parser.add_argument("--summary", default=True, type=bool, help="summary")
|
|
36
|
+
parser.add_argument("--class_weights", nargs="+", default=[1, 1, 1], type=float, help="class weights")
|
|
37
|
+
parser.add_argument("--log_dir", default="log", help="Tensorboard log directory (default: log)")
|
|
38
|
+
parser.add_argument("--model_dir", default=None, help="Checkpoint directory (default: None)")
|
|
39
|
+
parser.add_argument("--num_plots", default=10, type=int, help="Plotting trainning results")
|
|
40
|
+
parser.add_argument("--tp_prob", default=0.3, type=float, help="Probability threshold for P pick")
|
|
41
|
+
parser.add_argument("--ts_prob", default=0.3, type=float, help="Probability threshold for S pick")
|
|
42
|
+
parser.add_argument("--train_dir", default="./dataset/waveform_train/", help="Input file directory")
|
|
43
|
+
parser.add_argument("--train_list", default="./dataset/waveform.csv", help="Input csv file")
|
|
44
|
+
parser.add_argument("--valid_dir", default=None, help="Input file directory")
|
|
45
|
+
parser.add_argument("--valid_list", default=None, help="Input csv file")
|
|
46
|
+
parser.add_argument("--test_dir", default=None, help="Input file directory")
|
|
47
|
+
parser.add_argument("--test_list", default=None, help="Input csv file")
|
|
48
|
+
parser.add_argument("--plot_figure", action="store_true", help="If plot figure for test")
|
|
49
|
+
parser.add_argument("--save_prob", action="store_true", help="If save result for test")
|
|
50
|
+
args = parser.parse_args()
|
|
51
|
+
return args
|
|
52
|
+
|
|
53
|
+
def train_fn(args, data_reader, data_reader_valid=None):
|
|
54
|
+
current_time = time.strftime("%y%m%d-%H%M%S")
|
|
55
|
+
log_dir = os.path.join(args.log_dir, current_time)
|
|
56
|
+
logging.info("Training log: {}".format(log_dir))
|
|
57
|
+
if not os.path.exists(log_dir):
|
|
58
|
+
os.makedirs(log_dir)
|
|
59
|
+
figure_dir = os.path.join(log_dir, 'figures')
|
|
60
|
+
if not os.path.exists(figure_dir):
|
|
61
|
+
os.makedirs(figure_dir)
|
|
62
|
+
|
|
63
|
+
with tf.compat.v1.name_scope('Input_Batch'):
|
|
64
|
+
batch = data_reader.dequeue(args.batch_size)
|
|
65
|
+
if data_reader_valid is not None:
|
|
66
|
+
batch_valid = data_reader_valid.dequeue(args.batch_size)
|
|
67
|
+
|
|
68
|
+
config = ModelConfig(X_shape=data_reader.X_shape, Y_shape=data_reader.Y_shape)
|
|
69
|
+
if args.decay_step == -1:
|
|
70
|
+
args.decay_step = data_reader.num_data // args.batch_size
|
|
71
|
+
config.update_args(args)
|
|
72
|
+
with open(os.path.join(log_dir, 'config.log'), 'w') as fp:
|
|
73
|
+
fp.write('\n'.join("%s: %s" % item for item in vars(config).items()))
|
|
74
|
+
|
|
75
|
+
model = UNet(config)
|
|
76
|
+
sess_config = tf.compat.v1.ConfigProto()
|
|
77
|
+
sess_config.gpu_options.allow_growth = True
|
|
78
|
+
# sess_config.log_device_placement = False
|
|
79
|
+
|
|
80
|
+
with tf.compat.v1.Session(config=sess_config) as sess:
|
|
81
|
+
|
|
82
|
+
summary_writer = tf.compat.v1.summary.FileWriter(log_dir, sess.graph)
|
|
83
|
+
saver = tf.compat.v1.train.Saver(tf.compat.v1.global_variables(), max_to_keep=5)
|
|
84
|
+
init = tf.compat.v1.global_variables_initializer()
|
|
85
|
+
sess.run(init)
|
|
86
|
+
|
|
87
|
+
if args.model_dir is not None:
|
|
88
|
+
logging.info("restoring models...")
|
|
89
|
+
latest_check_point = tf.train.latest_checkpoint(args.model_dir)
|
|
90
|
+
saver.restore(sess, latest_check_point)
|
|
91
|
+
|
|
92
|
+
threads = data_reader.start_threads(sess, n_threads=multiprocessing.cpu_count())
|
|
93
|
+
if data_reader_valid is not None:
|
|
94
|
+
threads_valid = data_reader_valid.start_threads(sess, n_threads=multiprocessing.cpu_count())
|
|
95
|
+
flog = open(os.path.join(log_dir, 'loss.log'), 'w')
|
|
96
|
+
total_step = 0
|
|
97
|
+
mean_loss = 0
|
|
98
|
+
if args.plot_figure:
|
|
99
|
+
num_pool = multiprocessing.cpu_count()*2
|
|
100
|
+
elif args.save_prob:
|
|
101
|
+
num_pool = multiprocessing.cpu_count()
|
|
102
|
+
else:
|
|
103
|
+
num_pool = 2
|
|
104
|
+
pool = multiprocessing.Pool(num_pool)
|
|
105
|
+
|
|
106
|
+
for epoch in range(args.epochs):
|
|
107
|
+
progressbar = tqdm(range(0, data_reader.num_data, args.batch_size), desc="{}: epoch {}".format(log_dir.split("/")[-1], epoch))
|
|
108
|
+
for step in progressbar:
|
|
109
|
+
X_batch, Y_batch = sess.run(batch)
|
|
110
|
+
loss_batch = model.train_on_batch(sess, X_batch, Y_batch, summary_writer, args.drop_rate)
|
|
111
|
+
if epoch < 1:
|
|
112
|
+
mean_loss = loss_batch
|
|
113
|
+
else:
|
|
114
|
+
total_step += 1
|
|
115
|
+
mean_loss += (loss_batch-mean_loss)/total_step
|
|
116
|
+
progressbar.set_description("{}: epoch {}, loss={:.6f}, mean={:.6f}".format(log_dir.split("/")[-1], epoch, loss_batch, mean_loss))
|
|
117
|
+
flog.write("epoch: {}, mean loss: {}\n".format(epoch, mean_loss))
|
|
118
|
+
|
|
119
|
+
if data_reader_valid is not None:
|
|
120
|
+
valid_step = 0
|
|
121
|
+
valid_loss = 0
|
|
122
|
+
progressbar = tqdm(range(0, data_reader_valid.num_data, args.batch_size), desc="Valid:")
|
|
123
|
+
for step in progressbar:
|
|
124
|
+
X_batch, Y_batch = sess.run(batch_valid)
|
|
125
|
+
loss_batch, preds_batch = model.valid_on_batch(sess, X_batch, Y_batch, summary_writer)
|
|
126
|
+
valid_step += 1
|
|
127
|
+
valid_loss += (loss_batch-valid_loss)/valid_step
|
|
128
|
+
progressbar.set_description("valid, loss={:.6f}, mean={:.6f}".format(loss_batch, valid_loss))
|
|
129
|
+
flog.write("Valid: mean loss: {}\n".format(valid_loss))
|
|
130
|
+
else:
|
|
131
|
+
loss_batch, preds_batch = model.valid_on_batch(sess, X_batch, Y_batch, summary_writer)
|
|
132
|
+
# loss_batch, pred_batch, logits_batch, X_batch, Y_batch = model.train_on_batch(sess, summary_writer, args.drop_rate, raw_data=True)
|
|
133
|
+
try: ## IO Error on cluster
|
|
134
|
+
flog.flush()
|
|
135
|
+
pool.map(partial(plot_result_thread,
|
|
136
|
+
pred = preds_batch,
|
|
137
|
+
X = X_batch,
|
|
138
|
+
Y = Y_batch,
|
|
139
|
+
fname = ["{:03d}_{:03d}".format(epoch, x).encode() for x in range(args.num_plots)],
|
|
140
|
+
figure_dir = figure_dir),
|
|
141
|
+
range(args.num_plots))
|
|
142
|
+
saver.save(sess, os.path.join(log_dir, "model_{}.ckpt".format(epoch)))
|
|
143
|
+
except:
|
|
144
|
+
pass
|
|
145
|
+
flog.close()
|
|
146
|
+
pool.close()
|
|
147
|
+
data_reader.coord.request_stop()
|
|
148
|
+
try:
|
|
149
|
+
data_reader.coord.join(threads, stop_grace_period_secs=10, ignore_live_threads=True)
|
|
150
|
+
if data_reader_valid is not None:
|
|
151
|
+
data_reader_valid.coord.join(threads_valid, stop_grace_period_secs=10, ignore_live_threads=True)
|
|
152
|
+
except:
|
|
153
|
+
pass
|
|
154
|
+
sess.run(data_reader.queue.close(cancel_pending_enqueues=True))
|
|
155
|
+
if data_reader_valid is not None:
|
|
156
|
+
sess.run(data_reader_valid.queue.close(cancel_pending_enqueues=True))
|
|
157
|
+
|
|
158
|
+
return 0
|
|
159
|
+
|
|
160
|
+
def test_fn(args, data_reader, figure_dir=None, result_dir=None):
|
|
161
|
+
current_time = time.strftime("%y%m%d-%H%M%S")
|
|
162
|
+
logging.info("{} log: {}".format(args.mode, current_time))
|
|
163
|
+
log_dir = os.path.join(args.log_dir, args.mode, current_time)
|
|
164
|
+
if not os.path.exists(log_dir):
|
|
165
|
+
os.makedirs(log_dir)
|
|
166
|
+
if (args.plot_figure == True ) and (figure_dir is None):
|
|
167
|
+
figure_dir = os.path.join(log_dir, 'figures')
|
|
168
|
+
if not os.path.exists(figure_dir):
|
|
169
|
+
os.makedirs(figure_dir)
|
|
170
|
+
if (args.save_prob == True) and (result_dir is None):
|
|
171
|
+
result_dir = os.path.join(log_dir, 'results')
|
|
172
|
+
if not os.path.exists(result_dir):
|
|
173
|
+
os.makedirs(result_dir)
|
|
174
|
+
|
|
175
|
+
with tf.compat.v1.name_scope('Input_Batch'):
|
|
176
|
+
batch = data_reader.dequeue(args.batch_size)
|
|
177
|
+
|
|
178
|
+
config = ModelConfig(X_shape=data_reader.X_shape, Y_shape=data_reader.Y_shape)
|
|
179
|
+
if args.decay_step == -1:
|
|
180
|
+
args.decay_step = data_reader.num_data // args.batch_size
|
|
181
|
+
config.update_args(args)
|
|
182
|
+
with open(os.path.join(log_dir, 'config.log'), 'w') as fp:
|
|
183
|
+
fp.write('\n'.join("%s: %s" % item for item in vars(config).items()))
|
|
184
|
+
|
|
185
|
+
model = UNet(config, input_batch=batch, mode='valid')
|
|
186
|
+
sess_config = tf.compat.v1.ConfigProto()
|
|
187
|
+
sess_config.gpu_options.allow_growth = True
|
|
188
|
+
# sess_config.log_device_placement = False
|
|
189
|
+
|
|
190
|
+
with tf.compat.v1.Session(config=sess_config) as sess:
|
|
191
|
+
|
|
192
|
+
summary_writer = tf.compat.v1.summary.FileWriter(log_dir, sess.graph)
|
|
193
|
+
saver = tf.compat.v1.train.Saver(tf.compat.v1.global_variables(), max_to_keep=5)
|
|
194
|
+
init = tf.compat.v1.global_variables_initializer()
|
|
195
|
+
sess.run(init)
|
|
196
|
+
|
|
197
|
+
logging.info("restoring models...")
|
|
198
|
+
latest_check_point = tf.train.latest_checkpoint(args.model_dir)
|
|
199
|
+
saver.restore(sess, latest_check_point)
|
|
200
|
+
|
|
201
|
+
threads = data_reader.start_threads(sess, n_threads=8)
|
|
202
|
+
flog = open(os.path.join(log_dir, 'loss.log'), 'w')
|
|
203
|
+
total_step = 0
|
|
204
|
+
mean_loss = 0
|
|
205
|
+
picks = []
|
|
206
|
+
itp = []
|
|
207
|
+
its = []
|
|
208
|
+
progressbar = tqdm(range(0, data_reader.num_data, args.batch_size), desc=args.mode)
|
|
209
|
+
if args.plot_figure:
|
|
210
|
+
num_pool = multiprocessing.cpu_count()*2
|
|
211
|
+
elif args.save_prob:
|
|
212
|
+
num_pool = multiprocessing.cpu_count()
|
|
213
|
+
else:
|
|
214
|
+
num_pool = 2
|
|
215
|
+
pool = multiprocessing.Pool(num_pool)
|
|
216
|
+
for step in progressbar:
|
|
217
|
+
|
|
218
|
+
if step + args.batch_size >= data_reader.num_data:
|
|
219
|
+
for t in threads:
|
|
220
|
+
t.join()
|
|
221
|
+
sess.run(data_reader.queue.close())
|
|
222
|
+
|
|
223
|
+
loss_batch, pred_batch, X_batch, Y_batch, \
|
|
224
|
+
fname_batch, itp_batch, its_batch = model.test_on_batch(sess, summary_writer)
|
|
225
|
+
total_step += 1
|
|
226
|
+
mean_loss += (loss_batch-mean_loss)/total_step
|
|
227
|
+
progressbar.set_description("{}, loss={:.6f}, mean loss={:6f}".format(args.mode, loss_batch, mean_loss))
|
|
228
|
+
|
|
229
|
+
itp_batch = clean_queue(itp_batch)
|
|
230
|
+
its_batch = clean_queue(its_batch)
|
|
231
|
+
picks_batch = pool.map(partial(postprocessing_thread,
|
|
232
|
+
pred = pred_batch,
|
|
233
|
+
X = X_batch,
|
|
234
|
+
Y = Y_batch,
|
|
235
|
+
itp = itp_batch,
|
|
236
|
+
its = its_batch,
|
|
237
|
+
fname = fname_batch,
|
|
238
|
+
result_dir = result_dir,
|
|
239
|
+
figure_dir = figure_dir),
|
|
240
|
+
range(len(pred_batch)))
|
|
241
|
+
picks.extend(picks_batch)
|
|
242
|
+
itp.extend(itp_batch)
|
|
243
|
+
its.extend(its_batch)
|
|
244
|
+
|
|
245
|
+
flog.write("mean loss: {}\n".format(mean_loss))
|
|
246
|
+
metrics_p, metrics_s = calculate_metrics(picks, itp, its, tol=0.1)
|
|
247
|
+
flog.write("P-phase: Precision={}, Recall={}, F1={}\n".format(metrics_p[0], metrics_p[1], metrics_p[2]))
|
|
248
|
+
flog.write("S-phase: Precision={}, Recall={}, F1={}\n".format(metrics_s[0], metrics_s[1], metrics_s[2]))
|
|
249
|
+
flog.close()
|
|
250
|
+
|
|
251
|
+
return 0
|
|
252
|
+
|
|
253
|
+
def main(args):
|
|
254
|
+
|
|
255
|
+
logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO)
|
|
256
|
+
coord = tf.train.Coordinator()
|
|
257
|
+
|
|
258
|
+
if (args.mode == "train") or (args.mode == "train_valid"):
|
|
259
|
+
with tf.compat.v1.name_scope('create_inputs'):
|
|
260
|
+
data_reader = DataReader(
|
|
261
|
+
data_dir=args.train_dir,
|
|
262
|
+
data_list=args.train_list,
|
|
263
|
+
mask_window=0.4,
|
|
264
|
+
queue_size=args.batch_size*3,
|
|
265
|
+
coord=coord)
|
|
266
|
+
if args.mode == "train_valid":
|
|
267
|
+
data_reader_valid = DataReader(
|
|
268
|
+
data_dir=args.valid_dir,
|
|
269
|
+
data_list=args.valid_list,
|
|
270
|
+
mask_window=0.4,
|
|
271
|
+
queue_size=args.batch_size*2,
|
|
272
|
+
coord=coord)
|
|
273
|
+
logging.info("Dataset size: train {}, valid {}".format(data_reader.num_data, data_reader_valid.num_data))
|
|
274
|
+
else:
|
|
275
|
+
data_reader_valid = None
|
|
276
|
+
logging.info("Dataset size: train {}".format(data_reader.num_data))
|
|
277
|
+
train_fn(args, data_reader, data_reader_valid)
|
|
278
|
+
|
|
279
|
+
elif args.mode == "test":
|
|
280
|
+
with tf.compat.v1.name_scope('create_inputs'):
|
|
281
|
+
data_reader = DataReader_test(
|
|
282
|
+
data_dir=args.test_dir,
|
|
283
|
+
data_list=args.test_list,
|
|
284
|
+
mask_window=0.4,
|
|
285
|
+
queue_size=args.batch_size*10,
|
|
286
|
+
coord=coord)
|
|
287
|
+
test_fn(args, data_reader)
|
|
288
|
+
|
|
289
|
+
else:
|
|
290
|
+
print("mode should be: train, train_valid, pred or debug")
|
|
291
|
+
|
|
292
|
+
return
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
if __name__ == '__main__':
|
|
296
|
+
args = read_args()
|
|
297
|
+
main(args)
|
phasenet/util.py
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
from __future__ import division
|
|
2
|
+
import matplotlib
|
|
3
|
+
matplotlib.use('agg')
|
|
4
|
+
import matplotlib.pyplot as plt
|
|
5
|
+
import numpy as np
|
|
6
|
+
import os
|
|
7
|
+
from data_reader import DataConfig
|
|
8
|
+
from detect_peaks import detect_peaks
|
|
9
|
+
import logging
|
|
10
|
+
|
|
11
|
+
def detect_peaks_thread(i, pred, fname=None, result_dir=None, args=None):
|
|
12
|
+
if args is None:
|
|
13
|
+
itp, prob_p = detect_peaks(pred[i,:,0,1], mph=0.5, mpd=0.5/DataConfig().dt, show=False)
|
|
14
|
+
its, prob_s = detect_peaks(pred[i,:,0,2], mph=0.5, mpd=0.5/DataConfig().dt, show=False)
|
|
15
|
+
else:
|
|
16
|
+
itp, prob_p = detect_peaks(pred[i,:,0,1], mph=args.tp_prob, mpd=0.5/DataConfig().dt, show=False)
|
|
17
|
+
its, prob_s = detect_peaks(pred[i,:,0,2], mph=args.ts_prob, mpd=0.5/DataConfig().dt, show=False)
|
|
18
|
+
if (fname is not None) and (result_dir is not None):
|
|
19
|
+
# np.savez(os.path.join(result_dir, fname[i].decode().split('/')[-1]), pred=pred[i], itp=itp, its=its, prob_p=prob_p, prob_s=prob_s)
|
|
20
|
+
try:
|
|
21
|
+
np.savez(os.path.join(result_dir, fname[i].decode()), pred=pred[i], itp=itp, its=its, prob_p=prob_p, prob_s=prob_s)
|
|
22
|
+
except FileNotFoundError:
|
|
23
|
+
#if not os.path.exists(os.path.dirname(os.path.join(result_dir, fname[i].decode()))):
|
|
24
|
+
os.makedirs(os.path.dirname(os.path.join(result_dir, fname[i].decode())), exist_ok=True)
|
|
25
|
+
np.savez(os.path.join(result_dir, fname[i].decode()), pred=pred[i], itp=itp, its=its, prob_p=prob_p, prob_s=prob_s)
|
|
26
|
+
return [(itp, prob_p), (its, prob_s)]
|
|
27
|
+
|
|
28
|
+
def plot_result_thread(i, pred, X, Y=None, itp=None, its=None,
|
|
29
|
+
itp_pred=None, its_pred=None, fname=None, figure_dir=None):
|
|
30
|
+
dt = DataConfig().dt
|
|
31
|
+
t = np.arange(0, pred.shape[1]) * dt
|
|
32
|
+
box = dict(boxstyle='round', facecolor='white', alpha=1)
|
|
33
|
+
text_loc = [0.05, 0.77]
|
|
34
|
+
|
|
35
|
+
plt.figure(i)
|
|
36
|
+
plt.clf()
|
|
37
|
+
# fig_size = plt.gcf().get_size_inches()
|
|
38
|
+
# plt.gcf().set_size_inches(fig_size*[1, 1.2])
|
|
39
|
+
plt.subplot(411)
|
|
40
|
+
plt.plot(t, X[i, :, 0, 0], 'k', label='E', linewidth=0.5)
|
|
41
|
+
plt.autoscale(enable=True, axis='x', tight=True)
|
|
42
|
+
tmp_min = np.min(X[i, :, 0, 0])
|
|
43
|
+
tmp_max = np.max(X[i, :, 0, 0])
|
|
44
|
+
if (itp is not None) and (its is not None):
|
|
45
|
+
for j in range(len(itp[i])):
|
|
46
|
+
if j == 0:
|
|
47
|
+
plt.plot([itp[i][j]*dt, itp[i][j]*dt], [tmp_min, tmp_max], 'b', label='P', linewidth=0.5)
|
|
48
|
+
else:
|
|
49
|
+
plt.plot([itp[i][j]*dt, itp[i][j]*dt], [tmp_min, tmp_max], 'b', linewidth=0.5)
|
|
50
|
+
for j in range(len(its[i])):
|
|
51
|
+
if j == 0:
|
|
52
|
+
plt.plot([its[i][j]*dt, its[i][j]*dt], [tmp_min, tmp_max], 'r', label='S', linewidth=0.5)
|
|
53
|
+
else:
|
|
54
|
+
plt.plot([its[i][j]*dt, its[i][j]*dt], [tmp_min, tmp_max], 'r', linewidth=0.5)
|
|
55
|
+
plt.ylabel('Amplitude')
|
|
56
|
+
plt.legend(loc='upper right', fontsize='small')
|
|
57
|
+
plt.gca().set_xticklabels([])
|
|
58
|
+
plt.text(text_loc[0], text_loc[1], '(i)', horizontalalignment='center',
|
|
59
|
+
transform=plt.gca().transAxes, fontsize="small", fontweight="normal", bbox=box)
|
|
60
|
+
plt.subplot(412)
|
|
61
|
+
plt.plot(t, X[i, :, 0, 1], 'k', label='N', linewidth=0.5)
|
|
62
|
+
plt.autoscale(enable=True, axis='x', tight=True)
|
|
63
|
+
tmp_min = np.min(X[i, :, 0, 1])
|
|
64
|
+
tmp_max = np.max(X[i, :, 0, 1])
|
|
65
|
+
if (itp is not None) and (its is not None):
|
|
66
|
+
for j in range(len(itp[i])):
|
|
67
|
+
plt.plot([itp[i][j]*dt, itp[i][j]*dt], [tmp_min, tmp_max], 'b', linewidth=0.5)
|
|
68
|
+
for j in range(len(its[i])):
|
|
69
|
+
plt.plot([its[i][j]*dt, its[i][j]*dt], [tmp_min, tmp_max], 'r', linewidth=0.5)
|
|
70
|
+
plt.ylabel('Amplitude')
|
|
71
|
+
plt.legend(loc='upper right', fontsize='small')
|
|
72
|
+
plt.gca().set_xticklabels([])
|
|
73
|
+
plt.text(text_loc[0], text_loc[1], '(ii)', horizontalalignment='center',
|
|
74
|
+
transform=plt.gca().transAxes, fontsize="small", fontweight="normal", bbox=box)
|
|
75
|
+
plt.subplot(413)
|
|
76
|
+
plt.plot(t, X[i, :, 0, 2], 'k', label='Z', linewidth=0.5)
|
|
77
|
+
plt.autoscale(enable=True, axis='x', tight=True)
|
|
78
|
+
tmp_min = np.min(X[i, :, 0, 2])
|
|
79
|
+
tmp_max = np.max(X[i, :, 0, 2])
|
|
80
|
+
if (itp is not None) and (its is not None):
|
|
81
|
+
for j in range(len(itp[i])):
|
|
82
|
+
plt.plot([itp[i][j]*dt, itp[i][j]*dt], [tmp_min, tmp_max], 'b', linewidth=0.5)
|
|
83
|
+
for j in range(len(its[i])):
|
|
84
|
+
plt.plot([its[i][j]*dt, its[i][j]*dt], [tmp_min, tmp_max], 'r', linewidth=0.5)
|
|
85
|
+
plt.ylabel('Amplitude')
|
|
86
|
+
plt.legend(loc='upper right', fontsize='small')
|
|
87
|
+
plt.gca().set_xticklabels([])
|
|
88
|
+
plt.text(text_loc[0], text_loc[1], '(iii)', horizontalalignment='center',
|
|
89
|
+
transform=plt.gca().transAxes, fontsize="small", fontweight="normal", bbox=box)
|
|
90
|
+
plt.subplot(414)
|
|
91
|
+
if Y is not None:
|
|
92
|
+
plt.plot(t, Y[i, :, 0, 1], 'b', label='P', linewidth=0.5)
|
|
93
|
+
plt.plot(t, Y[i, :, 0, 2], 'r', label='S', linewidth=0.5)
|
|
94
|
+
plt.plot(t, pred[i, :, 0, 1], '--g', label='$\hat{P}$', linewidth=0.5)
|
|
95
|
+
plt.plot(t, pred[i, :, 0, 2], '-.m', label='$\hat{S}$', linewidth=0.5)
|
|
96
|
+
plt.autoscale(enable=True, axis='x', tight=True)
|
|
97
|
+
if (itp_pred is not None) and (its_pred is not None):
|
|
98
|
+
for j in range(len(itp_pred)):
|
|
99
|
+
plt.plot([itp_pred[j]*dt, itp_pred[j]*dt], [-0.1, 1.1], '--g', linewidth=0.5)
|
|
100
|
+
for j in range(len(its_pred)):
|
|
101
|
+
plt.plot([its_pred[j]*dt, its_pred[j]*dt], [-0.1, 1.1], '-.m', linewidth=0.5)
|
|
102
|
+
plt.ylim([-0.05, 1.05])
|
|
103
|
+
plt.text(text_loc[0], text_loc[1], '(iv)', horizontalalignment='center',
|
|
104
|
+
transform=plt.gca().transAxes, fontsize="small", fontweight="normal", bbox=box)
|
|
105
|
+
plt.legend(loc='upper right', fontsize='small')
|
|
106
|
+
plt.xlabel('Time (s)')
|
|
107
|
+
plt.ylabel('Probability')
|
|
108
|
+
|
|
109
|
+
plt.tight_layout()
|
|
110
|
+
plt.gcf().align_labels()
|
|
111
|
+
|
|
112
|
+
try:
|
|
113
|
+
plt.savefig(os.path.join(figure_dir,
|
|
114
|
+
fname[i].decode().rstrip('.npz')+'.png'),
|
|
115
|
+
bbox_inches='tight')
|
|
116
|
+
except FileNotFoundError:
|
|
117
|
+
#if not os.path.exists(os.path.dirname(os.path.join(figure_dir, fname[i].decode()))):
|
|
118
|
+
os.makedirs(os.path.dirname(os.path.join(figure_dir, fname[i].decode())), exist_ok=True)
|
|
119
|
+
plt.savefig(os.path.join(figure_dir,
|
|
120
|
+
fname[i].decode().rstrip('.npz')+'.png'),
|
|
121
|
+
bbox_inches='tight')
|
|
122
|
+
#plt.savefig(os.path.join(figure_dir,
|
|
123
|
+
# fname[i].decode().split('/')[-1].rstrip('.npz')+'.png'),
|
|
124
|
+
# bbox_inches='tight')
|
|
125
|
+
# plt.savefig(os.path.join(figure_dir,
|
|
126
|
+
# fname[i].decode().split('/')[-1].rstrip('.npz')+'.pdf'),
|
|
127
|
+
# bbox_inches='tight')
|
|
128
|
+
plt.close(i)
|
|
129
|
+
return 0
|
|
130
|
+
|
|
131
|
+
def postprocessing_thread(i, pred, X, Y=None, itp=None, its=None, fname=None, result_dir=None, figure_dir=None, args=None):
|
|
132
|
+
(itp_pred, prob_p), (its_pred, prob_s) = detect_peaks_thread(i, pred, fname, result_dir, args)
|
|
133
|
+
if (fname is not None) and (figure_dir is not None):
|
|
134
|
+
plot_result_thread(i, pred, X, Y, itp, its, itp_pred, its_pred, fname, figure_dir)
|
|
135
|
+
return [(itp_pred, prob_p), (its_pred, prob_s)]
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def clean_queue(picks):
|
|
139
|
+
clean = []
|
|
140
|
+
for i in range(len(picks)):
|
|
141
|
+
tmp = []
|
|
142
|
+
for j in picks[i]:
|
|
143
|
+
if j != 0:
|
|
144
|
+
tmp.append(j)
|
|
145
|
+
clean.append(tmp)
|
|
146
|
+
return clean
|
|
147
|
+
|
|
148
|
+
def clean_queue_thread(picks):
|
|
149
|
+
tmp = []
|
|
150
|
+
for j in picks:
|
|
151
|
+
if j != 0:
|
|
152
|
+
tmp.append(j)
|
|
153
|
+
return tmp
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def metrics(TP, nP, nT):
|
|
157
|
+
'''
|
|
158
|
+
TP: true positive
|
|
159
|
+
nP: number of positive picks
|
|
160
|
+
nT: number of true picks
|
|
161
|
+
'''
|
|
162
|
+
precision = TP / nP
|
|
163
|
+
recall = TP / nT
|
|
164
|
+
F1 = 2* precision * recall / (precision + recall)
|
|
165
|
+
return [precision, recall, F1]
|
|
166
|
+
|
|
167
|
+
def correct_picks(picks, true_p, true_s, tol):
|
|
168
|
+
dt = DataConfig().dt
|
|
169
|
+
if len(true_p) != len(true_s):
|
|
170
|
+
print("The length of true P and S pickers are not the same")
|
|
171
|
+
num = len(true_p)
|
|
172
|
+
TP_p = 0; TP_s = 0; nP_p = 0; nP_s = 0; nT_p = 0; nT_s = 0
|
|
173
|
+
diff_p = []; diff_s = []
|
|
174
|
+
for i in range(num):
|
|
175
|
+
nT_p += len(true_p[i])
|
|
176
|
+
nT_s += len(true_s[i])
|
|
177
|
+
nP_p += len(picks[i][0][0])
|
|
178
|
+
nP_s += len(picks[i][1][0])
|
|
179
|
+
|
|
180
|
+
if len(true_p[i]) > 1 or len(true_s[i]) > 1:
|
|
181
|
+
print(i, picks[i], true_p[i], true_s[i])
|
|
182
|
+
tmp_p = np.array(picks[i][0][0]) - np.array(true_p[i])[:,np.newaxis]
|
|
183
|
+
tmp_s = np.array(picks[i][1][0]) - np.array(true_s[i])[:,np.newaxis]
|
|
184
|
+
TP_p += np.sum(np.abs(tmp_p) < tol/dt)
|
|
185
|
+
TP_s += np.sum(np.abs(tmp_s) < tol/dt)
|
|
186
|
+
diff_p.append(tmp_p[np.abs(tmp_p) < 0.5/dt])
|
|
187
|
+
diff_s.append(tmp_s[np.abs(tmp_s) < 0.5/dt])
|
|
188
|
+
|
|
189
|
+
return [TP_p, TP_s, nP_p, nP_s, nT_p, nT_s, diff_p, diff_s]
|
|
190
|
+
|
|
191
|
+
def calculate_metrics(picks, itp, its, tol=0.1):
|
|
192
|
+
TP_p, TP_s, nP_p, nP_s, nT_p, nT_s, diff_p, diff_s = correct_picks(picks, itp, its, tol)
|
|
193
|
+
precision_p, recall_p, f1_p = metrics(TP_p, nP_p, nT_p)
|
|
194
|
+
precision_s, recall_s, f1_s = metrics(TP_s, nP_s, nT_s)
|
|
195
|
+
|
|
196
|
+
logging.info("Total records: {}".format(len(picks)))
|
|
197
|
+
logging.info("P-phase:")
|
|
198
|
+
logging.info("True={}, Predict={}, TruePositive={}".format(nT_p, nP_p, TP_p))
|
|
199
|
+
logging.info("Precision={:.3f}, Recall={:.3f}, F1={:.3f}".format(precision_p, recall_p, f1_p))
|
|
200
|
+
logging.info("S-phase:")
|
|
201
|
+
logging.info("True={}, Predict={}, TruePositive={}".format(nT_s, nP_s, TP_s))
|
|
202
|
+
logging.info("Precision={:.3f}, Recall={:.3f}, F1={:.3f}".format(precision_s, recall_s, f1_s))
|
|
203
|
+
return [precision_p, recall_p, f1_p], [precision_s, recall_s, f1_s]
|