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 2024-03-07 11:54 +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''' 

31 

32 

33def to_pyrocko_trace(trace): 

34 ''' 

35 Convert ObsPy trace object to Pyrocko trace object. 

36 

37 :param trace: 

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

39 :returns: 

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

41 ''' 

42 obspy_trace = trace 

43 from pyrocko import trace 

44 

45 return trace.Trace( 

46 str(obspy_trace.stats.network), 

47 str(obspy_trace.stats.station), 

48 str(obspy_trace.stats.location), 

49 str(obspy_trace.stats.channel), 

50 tmin=obspy_trace.stats.starttime.timestamp, 

51 tmax=obspy_trace.stats.endtime.timestamp, 

52 ydata=obspy_trace.data, 

53 deltat=obspy_trace.stats.delta) 

54 

55 

56def to_pyrocko_traces(stream): 

57 ''' 

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

59 

60 :param stream: 

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

62 :returns: 

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

64 ''' 

65 

66 obspy_stream = stream 

67 

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

69 

70 

71def to_pyrocko_events(catalog): 

72 ''' 

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

74 

75 :param catalog: 

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

77 :returns: 

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

79 catalog is ``None`` 

80 ''' 

81 

82 obspy_catalog = catalog 

83 

84 if obspy_catalog is None: 

85 return None 

86 

87 from pyrocko import model 

88 

89 events = [] 

90 for obspy_event in obspy_catalog: 

91 for origin in obspy_event.origins: 

92 

93 events.append(model.Event( 

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

95 time=origin.time.timestamp, 

96 lat=origin.latitude, 

97 lon=origin.longitude, 

98 depth=origin.depth, 

99 region=origin.region)) 

100 

101 return events 

102 

103 

104def to_pyrocko_stations(inventory): 

105 ''' 

106 Convert ObsPy inventory to list of Pyrocko traces. 

107 

108 :param inventory: 

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

110 object 

111 :returns: 

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

113 if inventory is ``None`` 

114 ''' 

115 

116 obspy_inventory = inventory 

117 

118 if obspy_inventory is None: 

119 return None 

120 

121 from pyrocko import model 

122 stations = [] 

123 for net in obspy_inventory.networks: 

124 for sta in net.stations: 

125 stations.append( 

126 model.Station( 

127 lat=sta.latitude, 

128 lon=sta.longitude, 

129 elevation=sta.elevation, 

130 network=net.code, 

131 station=sta.code, 

132 location='', 

133 channels=[ 

134 model.station.Channel( 

135 name=cha.code, 

136 azimuth=cha.azimuth, 

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

138 )) 

139 

140 return stations 

141 

142 

143def to_obspy_stream(pile): 

144 ''' 

145 Convert Pyrocko pile to ObsPy stream. 

146 

147 :param pile: 

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

149 :returns: 

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

151 ''' 

152 

153 pyrocko_pile = pile 

154 

155 import obspy 

156 stream = obspy.Stream() 

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

158 return stream 

159 

160 

161def to_obspy_trace(trace): 

162 ''' 

163 Convert Pyrocko trace to ObsPy trace. 

164 

165 :param trace: 

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

167 ''' 

168 import obspy 

169 

170 pyrocko_trace = trace 

171 

172 obspy_trace = obspy.Trace( 

173 data=pyrocko_trace.ydata, 

174 header=obspy.core.trace.Stats( 

175 dict( 

176 npts=len(pyrocko_trace.ydata), 

177 network=pyrocko_trace.network, 

178 station=pyrocko_trace.station, 

179 location=pyrocko_trace.location, 

180 channel=pyrocko_trace.channel, 

181 delta=pyrocko_trace.deltat, 

182 starttime=pyrocko_trace.tmin, 

183 endtime=pyrocko_trace.tmax) 

184 )) 

185 

186 return obspy_trace 

187 

188 

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

190 ''' 

191 Explore ObsPy data with Snuffler. 

192 

193 :param stream_or_trace: 

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

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

196 :param inventory: 

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

198 object 

199 :param catalog: 

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

201 :param kwargs: 

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

203 

204 :returns: 

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

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

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

208 

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

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

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

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

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

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

215 

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

217 an interactively modified ObsPy stream object. 

218 ''' 

219 

220 from pyrocko import trace 

221 import obspy 

222 

223 obspy_inventory = inventory 

224 obspy_catalog = catalog 

225 

226 if isinstance(stream_or_trace, obspy.Trace): 

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

228 else: 

229 obspy_stream = stream_or_trace 

230 

231 events = to_pyrocko_events(obspy_catalog) 

232 stations = to_pyrocko_stations(obspy_inventory) 

233 

234 return trace.snuffle( 

235 to_pyrocko_traces(obspy_stream), 

236 events=events, 

237 stations=stations, 

238 want_markers=True, 

239 **kwargs) 

240 

241 

242class ObsPyStreamSnufflingLoader(object): 

243 

244 def __init__(self, obspy_stream): 

245 self.obspy_stream = obspy_stream 

246 

247 def __call__(self, win): 

248 from .snuffling import ObsPyStreamSnuffling 

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

250 self.snuffling.setup() 

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

252 

253 def get_snuffling(self): 

254 return self.snuffling 

255 

256 

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

258 ''' 

259 Manipulate ObsPy stream object interactively. 

260 

261 :param stream_or_trace: 

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

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

264 :param inventory: 

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

266 object 

267 :param catalog: 

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

269 :param kwargs: 

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

271 

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

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

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

275 

276 This function displays an ObsPy stream object in Snuffler like 

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

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

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

280 

281 .. code:: 

282 

283 import obspy 

284 from pyrocko import obspy_compat 

285 

286 obspy_compat.plant() 

287 

288 stream = obspy.read() 

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

290 # closed 

291 ''' 

292 

293 from pyrocko import trace 

294 import obspy 

295 

296 obspy_inventory = inventory 

297 obspy_catalog = catalog 

298 

299 if isinstance(stream_or_trace, obspy.Trace): 

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

301 else: 

302 obspy_stream = stream_or_trace 

303 

304 events = to_pyrocko_events(obspy_catalog) 

305 stations = to_pyrocko_stations(obspy_inventory) 

306 

307 snuffling_loader = ObsPyStreamSnufflingLoader(obspy_stream) 

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

309 if not isinstance(launch_hook, list): 

310 launch_hook = [launch_hook] 

311 launch_hook.append(snuffling_loader) 

312 

313 trace.snuffle( 

314 [], 

315 events=events, 

316 stations=stations, 

317 controls=False, 

318 launch_hook=launch_hook, 

319 **kwargs) 

320 

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

322 

323 if isinstance(obspy_stream, obspy.Trace): 

324 return new_obspy_stream[0] 

325 else: 

326 return new_obspy_stream 

327 

328 

329def plant(): 

330 ''' 

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

332 

333 Methods added to ObsPy classes are: 

334 

335 +------------------------------------------------------+---------------------------------+ 

336 | class | methods | 

337 +======================================================+=================================+ 

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

339 | +---------------------------------+ 

340 | | :py:func:`snuffle` | 

341 | +---------------------------------+ 

342 | | :py:func:`fiddle` | 

343 +------------------------------------------------------+---------------------------------+ 

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

345 | +---------------------------------+ 

346 | | :py:func:`snuffle` | 

347 | +---------------------------------+ 

348 | | :py:func:`fiddle` | 

349 +------------------------------------------------------+---------------------------------+ 

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

351 +------------------------------------------------------+---------------------------------+ 

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

353 +------------------------------------------------------+---------------------------------+ 

354 

355 Methods added to Pyrocko classes are: 

356 

357 +--------------------------------------+---------------------------------+ 

358 | class | methods | 

359 +======================================+=================================+ 

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

361 +--------------------------------------+---------------------------------+ 

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

363 +--------------------------------------+---------------------------------+ 

364 ''' # noqa 

365 

366 import obspy 

367 obspy.Trace.to_pyrocko_trace = to_pyrocko_trace 

368 obspy.Trace.snuffle = snuffle 

369 obspy.Trace.fiddle = fiddle 

370 

371 obspy.Stream.to_pyrocko_traces = to_pyrocko_traces 

372 obspy.Stream.snuffle = snuffle 

373 obspy.Stream.fiddle = fiddle 

374 

375 obspy.core.event.Catalog.to_pyrocko_events = to_pyrocko_events 

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

377 to_pyrocko_stations 

378 

379 import pyrocko.trace 

380 import pyrocko.pile 

381 pyrocko.trace.Trace.to_obspy_trace = to_obspy_trace 

382 pyrocko.pile.Pile.to_obspy_stream = to_obspy_stream 

383 

384 

385__all__ = [ 

386 'to_pyrocko_trace', 

387 'to_pyrocko_traces', 

388 'to_pyrocko_events', 

389 'to_pyrocko_stations', 

390 'to_obspy_stream', 

391 'to_obspy_trace', 

392 'snuffle', 

393 'fiddle', 

394 'plant']