-
Notifications
You must be signed in to change notification settings - Fork 528
/
test_scan.py
277 lines (245 loc) · 10.8 KB
/
test_scan.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# -*- coding: utf-8 -*-
"""
The obspy.imaging.scripts.scan / obspy-scan test suite.
"""
import os
import shutil
import warnings
from pathlib import Path
import matplotlib.pyplot as plt
import pytest
from obspy import read, UTCDateTime
from obspy.core.util.base import NamedTemporaryFile, get_example_file
from obspy.core.util.misc import TemporaryWorkingDirectory, CatchOutput
from obspy.imaging.scripts.scan import main as obspy_scan
from obspy.imaging.scripts.scan import scan, Scanner
class TestScan:
"""
Test cases for obspy-scan
"""
@pytest.fixture(scope='class')
def all_files(self, root):
"""return a list of all waveform files in the test suite."""
sac_files = ['LMOW.BHE.SAC', 'seism.sac', 'dis.G.SCZ.__.BHE_short',
'null_terminated.sac', 'test.sac', 'seism-longer.sac',
'test.sac.swap', 'seism-shorter.sac', 'testxy.sac']
gse2_files = ['STA2.testlines', 'STA2.testlines_out', 'acc.gse',
'loc_RJOB20050831023349.z',
'loc_RJOB20050831023349_first100_dos.z',
'loc_RNON20040609200559.z', 'loc_STAU20031119011659.z',
'sta2.gse2', 'twiceCHK2.gse2', 'y2000.gse']
all_files = [root / 'io' / 'sac' / 'tests' / 'data' / i
for i in sac_files]
all_files.extend([root / 'io' / 'gse2' / 'tests' / 'data' / i
for i in gse2_files])
return all_files
def test_scan_main_method(self, all_files, image_path):
"""
Run obspy-scan on selected tests/data directories
"""
# Copy files to a temp folder to avoid wildcard scans.
with TemporaryWorkingDirectory():
for filename in all_files:
shutil.copy(filename, os.curdir)
obspy_scan([os.curdir] + ['--output', str(image_path)])
def test_scan_dir_no_permission(self, all_files):
"""
Run obspy-scan on a directory without read permission.
Should just skip it and not raise an exception. see #3115
"""
# Copy files to a temp folder to avoid wildcard scans.
scanner = Scanner()
with TemporaryWorkingDirectory():
no_permission_dir = Path('no_permission_dir')
no_permission_dir.mkdir()
# copy one test file in
shutil.copy(all_files[0], no_permission_dir)
# take away read permissions
no_permission_dir.chmod(0o000)
# still sometimes even on Linux CI runners it seems that stripping
# read permission does not work and the scanner is able to process
# it, thus ending up with a higher counter than if properly making
# the directory not readable
try:
os.listdir(no_permission_dir)
# this is what we want, not being able to read the directory, thus
# the scanner only processing one item
except PermissionError:
pass
# this is unexpected, we weren't able to strip read permissions,
# and then in consequence this test is meaningless and we mark it
# as a skipped test
else:
pytest.skip(
"unable to remove read permission from a test file for "
"testing purposes")
scanner.parse(str(no_permission_dir))
# should not have been able to read test file but also not raised
# an error
assert scanner.counter == 1
assert not scanner.data
# now allow read permission and read again
no_permission_dir.chmod(0o777)
scanner.parse(str(no_permission_dir))
assert scanner.counter == 2
assert '.LMOW..BHE' in scanner.data
for child in no_permission_dir.iterdir():
child.unlink()
no_permission_dir.rmdir()
def test_scan_function_and_scanner_class(self, all_files, image_path):
"""
Test scan function and Scanner class (in one test to keep overhead of
copying files down)
"""
scanner = Scanner()
path1 = image_path.parent / 'scan1.png'
path2 = image_path.parent / 'scan2.png'
# Copy files to a temp folder to avoid wildcard scans.
with TemporaryWorkingDirectory():
for filename in all_files:
shutil.copy(filename, os.curdir)
scanner.parse(os.curdir)
scan(paths=os.curdir, plot=path1)
scanner.plot(path2)
def test_scan_plot_by_id_with_wildcard(self):
"""
Test selecting what to plot after scanning with wildcards in selected
SEED IDs
"""
files = [
"BW.UH1._.EHZ.D.2010.147.a.slist.gz",
"BW.UH1._.EHZ.D.2010.147.b.slist.gz",
"BW.UH1._.SHZ.D.2010.147.cut.slist.gz",
"BW.UH2._.SHZ.D.2010.147.cut.slist.gz",
"BW.UH3._.SHE.D.2010.147.cut.slist.gz",
"BW.UH3._.SHN.D.2010.147.cut.slist.gz",
"BW.UH3._.SHZ.D.2010.147.cut.slist.gz",
"BW.UH4._.EHZ.D.2010.147.cut.slist.gz",
"IUANMO.seed"]
scanner = Scanner()
for filename in files:
scanner.parse(get_example_file(filename))
expected = [
('*.UH[12]*',
['BW.UH2..SHZ\n100.0%',
'BW.UH1..SHZ\n100.0%',
'BW.UH1..EHZ\n10.7%']),
('*Z',
['IU.ANMO.00.LHZ\n100.0%',
'BW.UH4..EHZ\n100.0%',
'BW.UH3..SHZ\n100.0%',
'BW.UH2..SHZ\n100.0%',
'BW.UH1..SHZ\n100.0%',
'BW.UH1..EHZ\n10.7%'])]
for seed_id, expected_labels in expected:
fig, ax = plt.subplots()
fig = scanner.plot(fig=fig, show=False, seed_ids=[seed_id])
got = [label.get_text() for label in ax.get_yticklabels()]
assert got == expected_labels
plt.close(fig)
def test_scanner_manually_add_streams(self, all_files, image_path):
"""
Test Scanner class, manually adding streams of read data files
"""
scanner = Scanner()
# Copy files to a temp folder to avoid wildcard scans.
with TemporaryWorkingDirectory():
for filename in all_files:
shutil.copy(filename, os.curdir)
for file_ in os.listdir(os.curdir):
# some files used in the test cases actually can not
# be read with obspy..
if file_ in ('STA2.testlines_out', 'STA2.testlines',
'seism-shorter.sac', 'seism-longer.sac'):
continue
st = read(file_, headonly=True)
scanner.add_stream(st)
scanner.plot(str(image_path))
def test_scan_save_load_npz(self, all_files, image_path):
"""
Run obspy-scan on selected tests/data directories, saving/loading
to/from npz.
Tests both the command line script and the Scanner class.
"""
scanner = Scanner()
# Copy files to a temp folder to avoid wildcard scans.
with TemporaryWorkingDirectory():
for filename in all_files:
shutil.copy(filename, os.curdir)
# save via command line
obspy_scan([os.curdir, '--write', 'scan.npz'])
# save via Python
scanner.parse(os.curdir)
scanner.save_npz('scanner.npz')
scanner = Scanner()
path1 = image_path.parent / 'scan_load_npz_1.png'
path2 = image_path.parent / 'scan_load_npz_2.png'
# version string of '0.0.0+archive' raises UserWarning - ignore
with warnings.catch_warnings(record=True):
warnings.simplefilter('ignore', UserWarning)
# load via Python
scanner.load_npz('scanner.npz')
scanner.plot(path1)
# load via command line
obspy_scan(['--load', 'scan.npz', '--output', str(path2)])
def test_scan_times(self, all_files, image_path):
"""
Checks for timing related options
"""
# Copy files to a temp folder to avoid wildcard scans.
with TemporaryWorkingDirectory():
for filename in all_files:
shutil.copy(filename, os.curdir)
obspy_scan([os.curdir] + ['--output', str(image_path)] +
['--start-time', '2004-01-01'] +
['--end-time', '2004-12-31'] +
['--event-time', '2004-03-14T15:09:26'] +
['--event-time', '2004-02-07T18:28:18'])
def test_multiple_sampling_rates(self, image_path):
"""
Check for multiple sampling rates
"""
lines = [
"TIMESERIES XX_TEST__BHZ_R, 200 samples, 200 sps, "
"2008-01-15T00:00:00.000000, SLIST, INTEGER, Counts",
"TIMESERIES XX_TEST__BHZ_R, 50 samples, 50 sps, "
"2008-01-15T00:00:00.900000, SLIST, INTEGER, Counts",
"TIMESERIES XX_TEST__BHZ_R, 200 samples, 200 sps, "
"2008-01-15T00:00:02.000000, SLIST, INTEGER, Counts",
]
files = []
expected = [
"XX.TEST..BHZ 2008-01-15T00:00:01.000000Z "
"2008-01-15T00:00:00.899995Z -0.100",
"XX.TEST..BHZ 2008-01-15T00:00:01.899999Z "
"2008-01-15T00:00:02.000000Z 0.100"
]
with NamedTemporaryFile() as f1, NamedTemporaryFile() as f2, \
NamedTemporaryFile() as f3:
for i, fp in enumerate([f1, f2, f3]):
fp.write(("%s\n" % lines[i]).encode('ascii',
'strict'))
fp.flush()
fp.seek(0)
files.append(fp.name)
# make image comparison instance and set manual rms (see #2089)
with CatchOutput() as out:
cmds = ['--output', str(image_path), '--print-gaps']
obspy_scan(files + cmds)
# read output and compare with expected
# only check if datetime objects are close, not exact
output = out.stdout.splitlines()
for ex_line, out_line in zip(expected, output):
ex_split = ex_line.split(' ')
out_split = out_line.split(' ')
for ex_str, out_str in zip(ex_split, out_split):
try:
utc1 = UTCDateTime(ex_str)
utc2 = UTCDateTime(out_str)
except (ValueError, TypeError):
# if str is not a datetime it should be equal
assert ex_str == out_str
else:
# datetimes just need to be close
t1, t2 = utc1.timestamp, utc2.timestamp
assert abs(t1 - t2) < .001