21
21
from matplotlib import patches
22
22
import matplotlib .patheffects as PathEffects
23
23
from matplotlib .ticker import ScalarFormatter as sf
24
+ from .config import config
24
25
from .savefig import savefig
25
26
from ._version import get_versions
26
27
logger = logging .getLogger (__name__ .rsplit ('.' , maxsplit = 1 )[- 1 ])
@@ -40,8 +41,20 @@ def _set_format(self, vmin=None, vmax=None):
40
41
phase_label_color = {'P' : 'black' , 'S' : 'black' }
41
42
42
43
43
- def _nplots (config , st , maxlines , ncols ):
44
- """Determine the number of lines and columns of the plot."""
44
+ def _nplots (st , maxlines , ncols ):
45
+ """
46
+ Determine the number of lines and columns of the plot.
47
+
48
+ :param st: Stream of traces.
49
+ :type st: :class:`obspy.core.stream.Stream`
50
+ :param maxlines: Maximum number of lines.
51
+ :type maxlines: int
52
+ :param ncols: Number of columns.
53
+ :type ncols: int
54
+
55
+ :return: Number of lines and columns.
56
+ :rtype: tuple of int
57
+ """
45
58
# Remove the channel letter to determine the number of plots
46
59
if config .plot_traces_ignored :
47
60
nplots = len ({tr .id [:- 1 ] for tr in st })
@@ -55,7 +68,19 @@ def _nplots(config, st, maxlines, ncols):
55
68
return nlines , ncols
56
69
57
70
58
- def _make_fig (config , nlines , ncols ):
71
+ def _make_fig (nlines , ncols ):
72
+ """
73
+ Create a figure with a number of subplots.
74
+
75
+ :param nlines: Number of lines.
76
+ :type nlines: int
77
+ :param ncols: Number of columns.
78
+ :type ncols: int
79
+
80
+ :return: Figure and axes.
81
+ :rtype: tuple of :class:`matplotlib.figure.Figure` and list of
82
+ :class:`matplotlib.axes.Axes`
83
+ """
59
84
figsize = (16 , 9 ) if nlines <= 3 else (16 , 18 )
60
85
# high dpi needed to rasterize png
61
86
# vector formats (pdf, svg) do not have rasters
@@ -127,7 +152,15 @@ def _make_fig(config, nlines, ncols):
127
152
BBOX = None
128
153
129
154
130
- def _savefig (config , figures , force_numbering = False ):
155
+ def _savefig (figures , force_numbering = False ):
156
+ """
157
+ Save figures to file.
158
+
159
+ :param figures: Figures to save.
160
+ :type figures: list of :class:`matplotlib.figure.Figure`
161
+ :param force_numbering: Force figure numbering.
162
+ :type force_numbering: bool
163
+ """
131
164
global BBOX # pylint: disable=global-statement
132
165
evid = config .event .event_id
133
166
figfile_base = os .path .join (config .options .outdir , f'{ evid } .traces.' )
@@ -165,7 +198,24 @@ def _savefig(config, figures, force_numbering=False):
165
198
166
199
167
200
def _plot_min_max (ax , x_vals , y_vals , linewidth , color , alpha , zorder ):
168
- """Quick and dirty plot using less points. Useful for vector plotting."""
201
+ """
202
+ Quick and dirty plot using less points. Useful for vector plotting.
203
+
204
+ :param ax: Axes object.
205
+ :type ax: :class:`matplotlib.axes.Axes`
206
+ :param x_vals: X values.
207
+ :type x_vals: :class:`numpy.ndarray`
208
+ :param y_vals: Y values.
209
+ :type y_vals: :class:`numpy.ndarray`
210
+ :param linewidth: Line width.
211
+ :type linewidth: float
212
+ :param color: Line color.
213
+ :type color: str
214
+ :param alpha: Line alpha.
215
+ :type alpha: float
216
+ :param zorder: Z-order.
217
+ :type zorder: int
218
+ """
169
219
ax_width_in_pixels = int (np .ceil (ax .bbox .width ))
170
220
nsamples = len (x_vals )
171
221
samples_per_pixel = int (np .ceil (nsamples / ax_width_in_pixels ))
@@ -190,7 +240,15 @@ def _plot_min_max(ax, x_vals, y_vals, linewidth, color, alpha, zorder):
190
240
191
241
192
242
def _freq_string (freq ):
193
- """Return a string representing the rounded frequency."""
243
+ """
244
+ Return a string representing the rounded frequency.
245
+
246
+ :param freq: Frequency.
247
+ :type freq: float
248
+
249
+ :return: Frequency string.
250
+ :rtype: str
251
+ """
194
252
# int or float notation for frequencies between 0.01 and 100
195
253
if 1e-2 <= freq <= 1e2 :
196
254
int_freq = int (round (freq ))
@@ -209,7 +267,25 @@ def _freq_string(freq):
209
267
)
210
268
211
269
212
- def _plot_trace (config , trace , ntraces , tmax , ax , trans , trans3 , path_effects ):
270
+ def _plot_trace (trace , ntraces , tmax , ax , trans , trans3 , path_effects ):
271
+ """
272
+ Plot a trace.
273
+
274
+ :param trace: Trace to plot.
275
+ :type trace: :class:`obspy.core.trace.Trace`
276
+ :param ntraces: Number of traces.
277
+ :type ntraces: int
278
+ :param tmax: Maximum value of the trace.
279
+ :type tmax: float
280
+ :param ax: Axes object.
281
+ :type ax: :class:`matplotlib.axes.Axes`
282
+ :param trans: Transformation for plotting phase labels.
283
+ :type trans: :class:`matplotlib.transforms.BboxTransformTo`
284
+ :param trans3: Transformation for plotting station info.
285
+ :type trans3: :class:`matplotlib.transforms.BboxTransformTo`
286
+ :param path_effects: Path effects for text.
287
+ :type path_effects: :class:`matplotlib
288
+ """
213
289
# Origin and height to draw vertical patches for noise and signal windows
214
290
rectangle_patch_origin = 0
215
291
rectangle_patch_height = 1
@@ -294,6 +370,16 @@ def _plot_trace(config, trace, ntraces, tmax, ax, trans, trans3, path_effects):
294
370
295
371
296
372
def _add_station_info_text (trace , ax , path_effects ):
373
+ """
374
+ Add station information text to the plot.
375
+
376
+ :param trace: Trace.
377
+ :type trace: :class:`obspy.core.trace.Trace`
378
+ :param ax: Axes object.
379
+ :type ax: :class:`matplotlib.axes.Axes`
380
+ :param path_effects: Path effects for text.
381
+ :type path_effects: :class:`matplotlib.patheffects`
382
+ """
297
383
with contextlib .suppress (AttributeError ):
298
384
if ax .has_station_info_text :
299
385
return
@@ -315,7 +401,16 @@ def _add_station_info_text(trace, ax, path_effects):
315
401
316
402
317
403
def _add_labels (axes , plotn , ncols ):
318
- """Add xlabels to the last row of plots."""
404
+ """
405
+ Add xlabels to the last row of plots.
406
+
407
+ :param axes: Axes objects.
408
+ :type axes: list of :class:`matplotlib.axes.Axes`
409
+ :param plotn: Number of plots.
410
+ :type plotn: int
411
+ :param ncols: Number of columns.
412
+ :type ncols: int
413
+ """
319
414
# A row has "ncols" plots: the last row is from `plotn-ncols` to `plotn`
320
415
n0 = max (plotn - ncols , 0 )
321
416
for ax in axes [n0 :plotn ]:
@@ -324,14 +419,25 @@ def _add_labels(axes, plotn, ncols):
324
419
325
420
326
421
def _set_ylim (axes ):
327
- """Set symmetric ylim."""
422
+ """
423
+ Set symmetric ylim.
424
+
425
+ :param axes: Axes objects.
426
+ :type axes: list of :class:`matplotlib
427
+ """
328
428
for ax in axes :
329
429
ylim = ax .get_ylim ()
330
430
ymax = np .max (np .abs (ylim ))
331
431
ax .set_ylim (- ymax , ymax )
332
432
333
433
334
- def _trim_traces (config , st ):
434
+ def _trim_traces (st ):
435
+ """
436
+ Trim traces to the time window of interest.
437
+
438
+ :param st: Stream of traces.
439
+ :type st: :class:`obspy.core.stream.Stream`
440
+ """
335
441
for trace in st :
336
442
t1 = trace .stats .arrivals ['N1' ][1 ]
337
443
t2 = trace .stats .arrivals ['S2' ][1 ] + 2 * config .win_length
@@ -342,11 +448,18 @@ def _trim_traces(config, st):
342
448
trace .stats .time_offset = trace .stats .starttime - min_starttime
343
449
344
450
345
- def plot_traces (config , st , ncols = None , block = True ):
451
+ def plot_traces (st , ncols = None , block = True ):
346
452
"""
347
453
Plot traces in the original instrument unit (velocity or acceleration).
348
454
349
455
Display to screen and/or save to file.
456
+
457
+ :param st: Stream of traces.
458
+ :type st: :class:`obspy.core.stream.Stream`
459
+ :param ncols: Number of columns in the plot (autoset if None).
460
+ :type ncols: int
461
+ :param block: If True, block execution until the plot window is closed.
462
+ :type block: bool
350
463
"""
351
464
# Check config, if we need to plot at all
352
465
if not config .plot_show and not config .plot_save :
@@ -358,8 +471,8 @@ def plot_traces(config, st, ncols=None, block=True):
358
471
ntr = len ({t .id [:- 1 ] for t in st })
359
472
ncols = 4 if ntr > 6 else 3
360
473
361
- nlines , ncols = _nplots (config , st , config .plot_traces_maxrows , ncols )
362
- fig , axes = _make_fig (config , nlines , ncols )
474
+ nlines , ncols = _nplots (st , config .plot_traces_maxrows , ncols )
475
+ fig , axes = _make_fig (nlines , ncols )
363
476
figures = [fig ]
364
477
# Path effect to contour text in white
365
478
path_effects = [PathEffects .withStroke (linewidth = 3 , foreground = 'white' )]
@@ -394,8 +507,8 @@ def plot_traces(config, st, ncols=None, block=True):
394
507
config .plot_save_format != 'pdf_multipage'
395
508
):
396
509
# save figure here to free up memory
397
- _savefig (config , figures , force_numbering = True )
398
- fig , axes = _make_fig (config , nlines , ncols )
510
+ _savefig (figures , force_numbering = True )
511
+ fig , axes = _make_fig (nlines , ncols )
399
512
figures .append (fig )
400
513
plotn = 1
401
514
ax = axes [plotn - 1 ]
@@ -419,13 +532,13 @@ def plot_traces(config, st, ncols=None, block=True):
419
532
transforms .blended_transform_factory (ax .transAxes , ax .transData )
420
533
trans3 = transforms .offset_copy (trans2 , fig = fig , x = 0 , y = 0.1 )
421
534
422
- _trim_traces (config , st_sel )
535
+ _trim_traces (st_sel )
423
536
max_values = [abs (tr .max ()) for tr in st_sel ]
424
537
ntraces = len (max_values )
425
538
tmax = max (max_values )
426
539
for trace in st_sel :
427
540
_plot_trace (
428
- config , trace , ntraces , tmax , ax , trans , trans3 , path_effects )
541
+ trace , ntraces , tmax , ax , trans , trans3 , path_effects )
429
542
430
543
_set_ylim (axes )
431
544
# Add labels for the last figure
@@ -437,4 +550,4 @@ def plot_traces(config, st, ncols=None, block=True):
437
550
if config .plot_show :
438
551
plt .show (block = block )
439
552
if config .plot_save :
440
- _savefig (config , figures )
553
+ _savefig (figures )
0 commit comments