/
client.py
235 lines (210 loc) · 9.21 KB
/
client.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
# -*- coding: utf-8 -*-
"""
Earthworm Wave Server client for ObsPy.
:copyright:
The ObsPy Development Team (devs@obspy.org) & Victor Kress
:license:
GNU Lesser General Public License, Version 3
(https://www.gnu.org/copyleft/lesser.html)
.. seealso:: http://www.isti2.com/ew/PROGRAMMER/wsv_protocol.html
"""
from __future__ import (absolute_import, division, print_function,
unicode_literals)
from future.builtins import * # NOQA @UnusedWildImport
from fnmatch import fnmatch
from obspy import Stream, UTCDateTime
from .waveserver import get_menu, read_wave_server_v
class Client(object):
"""
A Earthworm Wave Server client.
:type host: str
:param host: Host name of the remote Earthworm Wave Server server.
:type port: int
:param port: Port of the remote Earthworm Wave Server server.
:type timeout: int, optional
:param timeout: Seconds before a connection timeout is raised (default is
``None``).
:type debug: bool, optional
:param debug: Enables verbose output of the connection handling (default is
``False``).
"""
def __init__(self, host, port, timeout=None, debug=False):
"""
Initializes a Earthworm Wave Server client.
See :class:`obspy.clients.earthworm.client.Client` for all parameters.
"""
self.host = host
self.port = port
self.timeout = timeout
self.debug = debug
def get_waveforms(self, network, station, location, channel, starttime,
endtime, cleanup=True):
"""
Retrieves waveform data from Earthworm Wave Server and returns an ObsPy
Stream object.
:type filename: str
:param filename: Name of the output file.
:type network: str
:param network: Network code, e.g. ``'UW'``.
:type station: str
:param station: Station code, e.g. ``'TUCA'``.
:type location: str
:param location: Location code, e.g. ``'--'``.
:type channel: str
:param channel: Channel code, e.g. ``'BHZ'``. Last character (i.e.
component) can be a wildcard ('?' or '*') to fetch `Z`, `N` and
`E` component.
:type starttime: :class:`~obspy.core.utcdatetime.UTCDateTime`
:param starttime: Start date and time.
:type endtime: :class:`~obspy.core.utcdatetime.UTCDateTime`
:param endtime: End date and time.
:return: ObsPy :class:`~obspy.core.stream.Stream` object.
:type cleanup: bool
:param cleanup: Specifies whether perfectly aligned traces should be
merged or not. See :meth:`obspy.core.stream.Stream.merge` for
``method=-1``.
.. rubric:: Example
>>> from obspy.clients.earthworm import Client
>>> client = Client("pubavo1.wr.usgs.gov", 16022)
>>> dt = UTCDateTime() - 2000 # now - 2000 seconds
>>> st = client.get_waveforms('AV', 'ACH', '', 'EHE', dt, dt + 10)
>>> st.plot() # doctest: +SKIP
>>> st = client.get_waveforms('AV', 'ACH', '', 'EH*', dt, dt + 10)
>>> st.plot() # doctest: +SKIP
.. plot::
from obspy.clients.earthworm import Client
from obspy import UTCDateTime
client = Client("pubavo1.wr.usgs.gov", 16022, timeout=5)
dt = UTCDateTime() - 2000 # now - 2000 seconds
st = client.get_waveforms('AV', 'ACH', '', 'EHE', dt, dt + 10)
st.plot()
st = client.get_waveforms('AV', 'ACH', '', 'EH*', dt, dt + 10)
st.plot()
"""
# replace wildcards in last char of channel and fetch all 3 components
if channel[-1] in "?*":
st = Stream()
for comp in ("Z", "N", "E"):
channel_new = channel[:-1] + comp
st += self.get_waveforms(network, station, location,
channel_new, starttime, endtime,
cleanup=cleanup)
return st
if location == '':
location = '--'
scnl = (station, channel, network, location)
# fetch waveform
tbl = read_wave_server_v(self.host, self.port, scnl, starttime,
endtime, timeout=self.timeout,
cleanup=cleanup)
# create new stream
st = Stream()
for tb in tbl:
st.append(tb.get_obspy_trace())
if cleanup:
st._cleanup()
st.trim(starttime, endtime)
return st
def save_waveforms(self, filename, network, station, location, channel,
starttime, endtime, format="MSEED", cleanup=True):
"""
Writes a retrieved waveform directly into a file.
:type filename: str
:param filename: Name of the output file.
:type network: str
:param network: Network code, e.g. ``'UW'``.
:type station: str
:param station: Station code, e.g. ``'TUCA'``.
:type location: str
:param location: Location code, e.g. ``''``.
:type channel: str
:param channel: Channel code, e.g. ``'BHZ'``. Last character (i.e.
component) can be a wildcard ('?' or '*') to fetch `Z`, `N` and
`E` component.
:type starttime: :class:`~obspy.core.utcdatetime.UTCDateTime`
:param starttime: Start date and time.
:type endtime: :class:`~obspy.core.utcdatetime.UTCDateTime`
:param endtime: End date and time.
:type format: str, optional
:param format: Output format. One of ``"MSEED"``, ``"GSE2"``,
``"SAC"``, ``"SACXY"``, ``"Q"``, ``"SH_ASC"``, ``"SEGY"``,
``"SU"``, ``"WAV"``. See the Supported Formats section in method
:meth:`~obspy.core.stream.Stream.write` for a full list of
supported formats. Defaults to ``'MSEED'``.
:type cleanup: bool
:param cleanup: Specifies whether perfectly aligned traces should be
merged or not. See :meth:`~obspy.core.stream.Stream.merge`,
`method` -1 or :meth:`~obspy.core.stream.Stream._cleanup`.
:return: None
.. rubric:: Example
>>> from obspy.clients.earthworm import Client
>>> client = Client("pubavo1.wr.usgs.gov", 16022)
>>> t = UTCDateTime() - 2000 # now - 2000 seconds
>>> client.save_waveforms('AV.ACH.--.EHE.mseed',
... 'AV', 'ACH', '', 'EHE',
... t, t + 10, format='MSEED') # doctest: +SKIP
"""
st = self.get_waveforms(network, station, location, channel, starttime,
endtime, cleanup=cleanup)
st.write(filename, format=format)
def get_availability(self, network="*", station="*", location="*",
channel="*"):
"""
Gets a list of data available on the server.
This method returns information about what time series data is
available on the server. The query can optionally be restricted to
specific network, station, channel and/or location criteria.
:type network: str
:param network: Network code, e.g. ``'UW'``, wildcards allowed.
:type station: str
:param station: Station code, e.g. ``'TUCA'``, wildcards allowed.
:type location: str
:param location: Location code, e.g. ``'--'``, wildcards allowed.
:type channel: str
:param channel: Channel code, e.g. ``'BHZ'``, wildcards allowed.
:rtype: list
:return: List of tuples with information on the available data. One
tuple consists of network, station, location, channel
(all strings), start time and end time
(both as :class:`~obspy.core.utcdatetime.UTCDateTime`).
.. rubric:: Example
>>> from obspy.clients.earthworm import Client
>>> client = Client("pubavo1.wr.usgs.gov", 16022, timeout=5)
>>> response = client.get_availability(
... network="AV", station="ACH", channel="EH*")
>>> print(response) # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
[('AV',
'ACH',
'--',
'EHE',
UTCDateTime(...),
UTCDateTime(...)),
('AV',
'ACH',
'--',
'EHN',
UTCDateTime(...),
UTCDateTime(...)),
('AV',
'ACH',
'--',
'EHZ',
UTCDateTime(...),
UTCDateTime(...))]
"""
# build up possibly wildcarded trace id pattern for query
if location == '':
location = '--'
pattern = ".".join((network, station, location, channel))
# get overview of all available data, winston wave servers can not
# restrict the query via network, station etc. so we do that manually
response = get_menu(self.host, self.port, timeout=self.timeout)
# reorder items and convert time info to UTCDateTime
response = [(x[3], x[1], x[4], x[2], UTCDateTime(x[5]),
UTCDateTime(x[6])) for x in response]
# restrict results according to user input
response = [x for x in response if fnmatch(".".join(x[:4]), pattern)]
return response
if __name__ == '__main__':
import doctest
doctest.testmod(exclude_empty=True)