Coverage for /usr/local/lib/python3.11/dist-packages/pyrocko/obspy_compat/base.py: 99%

95 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-10-06 15:01 +0000

1# https://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

4# ---|P------/S----------~Lg---------- 

5 

6''' 

7This module provides basic compatibility between ObsPy and Pyrocko. 

8 

9The functions defined here can be used to translate back and forth some of the 

10basic objects in Pyrocko and ObsPy. It also provides shortcuts to quickly look 

11at ObsPy waveforms with the Pyrocko's :doc:`Snuffler </apps/snuffler/index>` 

12application (:py:func:`snuffle`, :py:func:`fiddle`). 

13 

14With :func:`~pyrocko.obspy_compat.base.plant` several new methods are attached 

15to Pyrocko and ObsPy classes. 

16 

17**Example, visualize ObsPy stream object with Snuffler:** 

18 

19.. code-block:: python 

20 

21 import obspy 

22 from pyrocko import obspy_compat 

23 obspy_compat.plant() 

24 

25 stream = obspy.read() # returns some example data 

26 stream.snuffle() 

27 

28-- *With best wishes to the ObsPy Team from the Pyrocko Developers!* 

29 

30.. note:: 

31 

32 This is an experimental module, the interface may still be changed. 

33 Feedback and discussion welcome! 

34 

35''' 

36 

37 

38def to_pyrocko_trace(trace): 

39 ''' 

40 Convert ObsPy trace object to Pyrocko trace object. 

41 

42 :param trace: 

43 :py:class:`obspy.Trace <obspy.core.trace.Trace>` object 

44 :returns: 

45 :py:class:`pyrocko.trace.Trace` object 

46 ''' 

47 obspy_trace = trace 

48 from pyrocko import trace 

49 

50 return trace.Trace( 

51 str(obspy_trace.stats.network), 

52 str(obspy_trace.stats.station), 

53 str(obspy_trace.stats.location), 

54 str(obspy_trace.stats.channel), 

55 tmin=obspy_trace.stats.starttime.timestamp, 

56 tmax=obspy_trace.stats.endtime.timestamp, 

57 ydata=obspy_trace.data, 

58 deltat=obspy_trace.stats.delta) 

59 

60 

61def to_pyrocko_traces(stream): 

62 ''' 

63 Convert ObsPy stream object to list of Pyrocko trace objects. 

64 

65 :param stream: 

66 :py:class:`obspy.Stream <obspy.core.stream.Stream>` object 

67 :returns: 

68 list of :py:class:`pyrocko.trace.Trace` objects 

69 ''' 

70 

71 obspy_stream = stream 

72 

73 return [to_pyrocko_trace(obspy_trace) for obspy_trace in obspy_stream] 

74 

75 

76def to_pyrocko_events(catalog): 

77 ''' 

78 Convert ObsPy catalog object to list of Pyrocko event objects. 

79 

80 :param catalog: 

81 :py:class:`obspy.Catalog <obspy.core.event.Catalog>` object 

82 :returns: 

83 list of :py:class:`pyrocko.model.event.Event` objects or ``None`` if 

84 catalog is ``None`` 

85 ''' 

86 

87 obspy_catalog = catalog 

88 

89 if obspy_catalog is None: 

90 return None 

91 

92 from pyrocko import model 

93 

94 events = [] 

95 for obspy_event in obspy_catalog: 

96 for origin in obspy_event.origins: 

97 

98 events.append(model.Event( 

99 name='%s-%s' % (obspy_event.resource_id, origin.resource_id), 

100 time=origin.time.timestamp, 

101 lat=origin.latitude, 

102 lon=origin.longitude, 

103 depth=origin.depth, 

104 region=origin.region)) 

105 

106 return events 

107 

108 

109def to_pyrocko_stations(inventory): 

110 ''' 

111 Convert ObsPy inventory to list of Pyrocko traces. 

112 

113 :param inventory: 

114 :py:class:`obspy.Inventory <obspy.core.inventory.inventory.Inventory>` 

115 object 

116 :returns: 

117 list of :py:class:`pyrocko.model.station.Station` objects or ``None`` 

118 if inventory is ``None`` 

119 ''' 

120 

121 obspy_inventory = inventory 

122 

123 if obspy_inventory is None: 

124 return None 

125 

126 from pyrocko import model 

127 stations = [] 

128 for net in obspy_inventory.networks: 

129 for sta in net.stations: 

130 stations.append( 

131 model.Station( 

132 lat=sta.latitude, 

133 lon=sta.longitude, 

134 elevation=sta.elevation, 

135 network=net.code, 

136 station=sta.code, 

137 location='', 

138 channels=[ 

139 model.station.Channel( 

140 name=cha.code, 

141 azimuth=cha.azimuth, 

142 dip=cha.dip) for cha in sta.channels] 

143 )) 

144 

145 return stations 

146 

147 

148def to_obspy_stream(pile): 

149 ''' 

150 Convert Pyrocko pile to ObsPy stream. 

151 

152 :param pile: 

153 :py:class:`pyrocko.pile.Pile` object 

154 :returns: 

155 :py:class:`obspy.Stream <obspy.core.stream.Stream>` object 

156 ''' 

157 

158 pyrocko_pile = pile 

159 

160 import obspy 

161 stream = obspy.Stream() 

162 stream.extend([to_obspy_trace(tr) for tr in pyrocko_pile.iter_all()]) 

163 return stream 

164 

165 

166def to_obspy_trace(trace): 

167 ''' 

168 Convert Pyrocko trace to ObsPy trace. 

169 

170 :param trace: 

171 :py:class:`pyrocko.trace.Trace` 

172 ''' 

173 import obspy 

174 

175 pyrocko_trace = trace 

176 

177 obspy_trace = obspy.Trace( 

178 data=pyrocko_trace.ydata, 

179 header=obspy.core.trace.Stats( 

180 dict( 

181 npts=len(pyrocko_trace.ydata), 

182 network=pyrocko_trace.network, 

183 station=pyrocko_trace.station, 

184 location=pyrocko_trace.location, 

185 channel=pyrocko_trace.channel, 

186 delta=pyrocko_trace.deltat, 

187 starttime=pyrocko_trace.tmin, 

188 endtime=pyrocko_trace.tmax) 

189 )) 

190 

191 return obspy_trace 

192 

193 

194def snuffle(stream_or_trace, inventory=None, catalog=None, **kwargs): 

195 ''' 

196 Explore ObsPy data with Snuffler. 

197 

198 :param stream_or_trace: 

199 :py:class:`obspy.Stream <obspy.core.stream.Stream>` or 

200 :py:class:`obspy.Trace <obspy.core.trace.Trace>` object 

201 :param inventory: 

202 :py:class:`obspy.Inventory <obspy.core.inventory.inventory.Inventory>` 

203 object 

204 :param catalog: 

205 :py:class:`obspy.Catalog <obspy.core.event.Catalog>` object 

206 :param kwargs: 

207 extra arguments passed to :meth:`pyrocko.trace.Trace.snuffle`. 

208 

209 :returns: 

210 ``(return_tag, markers)``, where ``return_tag`` is the a string to flag 

211 how the Snuffler window has been closed and ``markers`` is a list of 

212 :py:class:`pyrocko.gui.snuffler.marker.Marker` objects. 

213 

214 This function displays an ObsPy stream object in Snuffler. It returns to 

215 the caller once the window has been closed. The ``return_tag`` returned by 

216 the function can be used as a primitive way to communicate a user decision 

217 to the calling script. By default it returns the key pressed to close the 

218 window (if any), either ``'q'`` or ``'x'``, but the value could be 

219 customized when the exit is triggered from within a Snuffling. 

220 

221 See also :py:func:`fiddle` for a variant of this function returning 

222 an interactively modified ObsPy stream object. 

223 ''' 

224 

225 from pyrocko import trace 

226 import obspy 

227 

228 obspy_inventory = inventory 

229 obspy_catalog = catalog 

230 

231 if isinstance(stream_or_trace, obspy.Trace): 

232 obspy_stream = obspy.core.stream.Stream(traces=[stream_or_trace]) 

233 else: 

234 obspy_stream = stream_or_trace 

235 

236 events = to_pyrocko_events(obspy_catalog) 

237 stations = to_pyrocko_stations(obspy_inventory) 

238 

239 return trace.snuffle( 

240 to_pyrocko_traces(obspy_stream), 

241 events=events, 

242 stations=stations, 

243 want_markers=True, 

244 **kwargs) 

245 

246 

247class ObsPyStreamSnufflingLoader(object): 

248 

249 def __init__(self, obspy_stream): 

250 self.obspy_stream = obspy_stream 

251 

252 def __call__(self, win): 

253 from .snuffling import ObsPyStreamSnuffling 

254 self.snuffling = ObsPyStreamSnuffling(obspy_stream=self.obspy_stream) 

255 self.snuffling.setup() 

256 win.pile_viewer.viewer.add_snuffling(self.snuffling, reloaded=True) 

257 

258 def get_snuffling(self): 

259 return self.snuffling 

260 

261 

262def fiddle(stream_or_trace, inventory=None, catalog=None, **kwargs): 

263 ''' 

264 Manipulate ObsPy stream object interactively. 

265 

266 :param stream_or_trace: 

267 :py:class:`obspy.Stream <obspy.core.stream.Stream>` or 

268 :py:class:`obspy.Trace <obspy.core.trace.Trace>` object 

269 :param inventory: 

270 :py:class:`obspy.Inventory <obspy.core.inventory.inventory.Inventory>` 

271 object 

272 :param catalog: 

273 :py:class:`obspy.Catalog <obspy.core.event.Catalog>` object 

274 :param kwargs: 

275 extra arguments passed to :meth:`pyrocko.trace.Trace.snuffle`. 

276 

277 :returns: :py:class:`obspy.Stream <obspy.core.stream.Stream>` object with 

278 changes applied interactively (or :py:class:`obspy.Trace 

279 <obspy.core.trace.Trace>` if called with a trace as first argument). 

280 

281 This function displays an ObsPy stream object in Snuffler like 

282 :py:func:`snuffle`, but additionally adds a Snuffling panel to apply some 

283 basic ObsPy signal processing to the contained traces. The applied changes 

284 are handed back to the caller as a modified copy of the stream object. 

285 

286 .. code:: 

287 

288 import obspy 

289 from pyrocko import obspy_compat 

290 

291 obspy_compat.plant() 

292 

293 stream = obspy.read() 

294 stream_filtered = stream.fiddle() # returns once window has been 

295 # closed 

296 ''' 

297 

298 from pyrocko import trace 

299 import obspy 

300 

301 obspy_inventory = inventory 

302 obspy_catalog = catalog 

303 

304 if isinstance(stream_or_trace, obspy.Trace): 

305 obspy_stream = obspy.core.stream.Stream(traces=[stream_or_trace]) 

306 else: 

307 obspy_stream = stream_or_trace 

308 

309 events = to_pyrocko_events(obspy_catalog) 

310 stations = to_pyrocko_stations(obspy_inventory) 

311 

312 snuffling_loader = ObsPyStreamSnufflingLoader(obspy_stream) 

313 launch_hook = kwargs.pop('launch_hook', []) 

314 if not isinstance(launch_hook, list): 

315 launch_hook = [launch_hook] 

316 launch_hook.append(snuffling_loader) 

317 

318 trace.snuffle( 

319 [], 

320 events=events, 

321 stations=stations, 

322 controls=False, 

323 launch_hook=launch_hook, 

324 **kwargs) 

325 

326 new_obspy_stream = snuffling_loader.get_snuffling().get_obspy_stream() 

327 

328 if isinstance(obspy_stream, obspy.Trace): 

329 return new_obspy_stream[0] 

330 else: 

331 return new_obspy_stream 

332 

333 

334def plant(): 

335 ''' 

336 Add conversion functions as methods to ObsPy and Pyrocko classes. 

337 

338 Methods added to ObsPy classes are: 

339 

340 +------------------------------------------------------+---------------------------------+ 

341 | class | methods | 

342 +======================================================+=================================+ 

343 | :py:class:`obspy.core.trace.Trace` | :py:func:`to_pyrocko_trace` | 

344 | +---------------------------------+ 

345 | | :py:func:`snuffle` | 

346 | +---------------------------------+ 

347 | | :py:func:`fiddle` | 

348 +------------------------------------------------------+---------------------------------+ 

349 | :py:class:`obspy.core.stream.Stream` | :py:func:`to_pyrocko_traces` | 

350 | +---------------------------------+ 

351 | | :py:func:`snuffle` | 

352 | +---------------------------------+ 

353 | | :py:func:`fiddle` | 

354 +------------------------------------------------------+---------------------------------+ 

355 | :py:class:`obspy.core.event.Catalog` | :py:func:`to_pyrocko_events` | 

356 +------------------------------------------------------+---------------------------------+ 

357 | :py:class:`obspy.core.inventory.inventory.Inventory` | :py:func:`to_pyrocko_stations` | 

358 +------------------------------------------------------+---------------------------------+ 

359 

360 Methods added to Pyrocko classes are: 

361 

362 +--------------------------------------+---------------------------------+ 

363 | class | methods | 

364 +======================================+=================================+ 

365 | :py:class:`pyrocko.trace.Trace` | :py:func:`to_obspy_trace` | 

366 +--------------------------------------+---------------------------------+ 

367 | :py:class:`pyrocko.pile.Pile` | :py:func:`to_obspy_stream` | 

368 +--------------------------------------+---------------------------------+ 

369 ''' # noqa 

370 

371 import obspy 

372 obspy.Trace.to_pyrocko_trace = to_pyrocko_trace 

373 obspy.Trace.snuffle = snuffle 

374 obspy.Trace.fiddle = fiddle 

375 

376 obspy.Stream.to_pyrocko_traces = to_pyrocko_traces 

377 obspy.Stream.snuffle = snuffle 

378 obspy.Stream.fiddle = fiddle 

379 

380 obspy.core.event.Catalog.to_pyrocko_events = to_pyrocko_events 

381 obspy.core.inventory.inventory.Inventory.to_pyrocko_stations =\ 

382 to_pyrocko_stations 

383 

384 import pyrocko.trace 

385 import pyrocko.pile 

386 pyrocko.trace.Trace.to_obspy_trace = to_obspy_trace 

387 pyrocko.pile.Pile.to_obspy_stream = to_obspy_stream 

388 

389 

390__all__ = [ 

391 'to_pyrocko_trace', 

392 'to_pyrocko_traces', 

393 'to_pyrocko_events', 

394 'to_pyrocko_stations', 

395 'to_obspy_stream', 

396 'to_obspy_trace', 

397 'snuffle', 

398 'fiddle', 

399 'plant']