Coverage for /usr/local/lib/python3.11/dist-packages/grond/qc.py: 0%
140 statements
« prev ^ index » next coverage.py v6.5.0, created at 2024-11-27 15:15 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2024-11-27 15:15 +0000
1# https://pyrocko.org/grond - GPLv3
2#
3# The Grond Developers, 21st Century
4import logging
5from collections import defaultdict
7import numpy as num
9from matplotlib import pyplot as plt
10from mpl_toolkits.axes_grid1 import ImageGrid
12from pyrocko import gf, orthodrome as od, plot, model, trace
13from grond import dataset
14from grond.meta import store_t
16km = 1000.
18logger = logging.getLogger('grond.qc')
21def darken(c):
22 return (c[0]*0.5, c[1]*0.5, c[2]*0.5)
25def plot_color_line(axes, x, y, t, color, tmin, tmax):
26 from matplotlib.colors import LinearSegmentedColormap
27 from matplotlib.collections import LineCollection
29 cmap = LinearSegmentedColormap.from_list(
30 'noname', [color, (1., 1., 1.)], 100)
32 points = num.array([x, y], dtype=float).T.reshape(-1, 1, 2)
33 segments = num.concatenate([points[:-1], points[1:]], axis=1)
34 lc = LineCollection(segments, cmap=cmap, norm=plt.Normalize(tmin, tmax))
35 lc.set_array(t)
36 axes.add_collection(lc, autolim=True)
39def polarization(
40 ds, store, timing, fmin, fmax, ffactor,
41 time_factor_pre=2.,
42 time_factor_post=2.,
43 distance_min=None,
44 distance_max=None,
45 depth_min=None,
46 depth_max=None,
47 size_factor=0.05,
48 nsl_to_time=None,
49 output_filename=None,
50 output_format=None,
51 output_dpi=None):
53 event = ds.get_event()
54 stations = ds.get_stations()
56 source = gf.Source.from_pyrocko_event(event)
58 trs = []
59 for station in stations:
61 nsl = station.nsl()
63 dist = source.distance_to(station)
65 if distance_min is not None and dist < distance_min:
66 continue
68 if distance_max is not None and distance_max < dist:
69 continue
71 if depth_min is not None and station.depth < depth_min:
72 continue
74 if depth_max is not None and depth_max < station.depth:
75 continue
77 if nsl_to_time is None:
78 tp = event.time + store_t(store, timing, source, station)
80 else:
81 if nsl not in nsl_to_time:
82 continue
84 tp = nsl_to_time[nsl]
86 for component in 'ZNE':
88 tmin = tp - time_factor_pre / fmin
89 tmax = tp + time_factor_post / fmin
91 nslc = nsl + (component,)
93 freqlimits = [
94 fmin / ffactor,
95 fmin,
96 fmax,
97 fmax * ffactor]
99 tfade = 1.0 / (fmin / ffactor)
101 try:
102 trs_projected, trs_restituted, trs_raw, _ = \
103 ds.get_waveform(
104 nslc,
105 tmin=tmin,
106 tmax=tmax,
107 tfade=tfade,
108 freqlimits=freqlimits,
109 debug=True)
111 for tr in trs_projected:
112 tr.shift(-tp)
114 trs.extend(trs_projected)
116 except dataset.NotFound as e:
117 logger.warning(str(e))
118 continue
120 trace.snuffle(trs, stations=stations)
122 plot_polarizations(
123 stations, trs,
124 event=event,
125 size_factor=size_factor,
126 output_filename=output_filename,
127 output_format=output_format,
128 output_dpi=output_dpi)
131def plot_polarizations(
132 stations, trs,
133 event=None,
134 size_factor=0.05,
135 fontsize=10.,
136 output_filename=None,
137 output_format=None,
138 output_dpi=None):
140 if event is None:
141 slats = num.array([s.lat for s in stations], dtype=float)
142 slons = num.array([s.lon for s in stations], dtype=float)
143 clat, clon = od.geographic_midpoint(slats, slons)
144 event = od.Loc(clat, clon)
146 nsl_c_to_trs = defaultdict(dict)
147 for tr in trs:
148 nsl_c_to_trs[tr.nslc_id[:3]][tr.nslc_id[3]] = tr
150 nsl_to_station = dict(
151 (s.nsl(), s) for s in stations)
153 plot.mpl_init(fontsize=fontsize)
154 fig = plt.figure(figsize=plot.mpl_papersize('a4', 'landscape'))
155 plot.mpl_margins(fig, w=7., h=6., units=fontsize)
157 grid = ImageGrid(
158 fig, 111, nrows_ncols=(2, 2),
159 axes_pad=0.5,
160 add_all=True,
161 label_mode='L',
162 aspect=True)
164 axes_en = grid[0]
165 axes_en.set_ylabel('Northing [km]')
167 axes_dn = grid[1]
168 axes_dn.locator_params(axis='x', nbins=4)
169 axes_dn.set_xlabel('Depth [km]')
171 axes_ed = grid[2]
172 axes_ed.locator_params(axis='y', nbins=4)
173 axes_ed.set_ylabel('Depth [km]')
174 axes_ed.set_xlabel('Easting [km]')
176 if isinstance(event, model.Event):
177 axes_en.plot(0., 0., '*')
178 axes_dn.plot(event.depth/km, 0., '*')
179 axes_ed.plot(0., event.depth/km, '*')
181 grid[3].set_axis_off()
183 locations = []
184 for nsl in sorted(nsl_c_to_trs.keys()):
185 station = nsl_to_station[nsl]
186 n, e = od.latlon_to_ne(
187 event.lat, event.lon, station.lat, station.lon)
189 locations.append((n, e))
191 ns, es = num.array(locations, dtype=float).T
193 n_min = num.min(ns)
194 n_max = num.max(ns)
195 e_min = num.min(es)
196 e_max = num.max(es)
198 factor = max((n_max - n_min) * size_factor, (e_max - e_min) * size_factor)
200 fontsize_annot = fontsize * 0.7
202 data = {}
203 for insl, nsl in enumerate(sorted(nsl_c_to_trs.keys())):
205 color = plot.mpl_graph_color(insl)
207 try:
208 tr_e = nsl_c_to_trs[nsl]['E']
209 tr_n = nsl_c_to_trs[nsl]['N']
210 tr_z = nsl_c_to_trs[nsl]['Z']
212 except KeyError:
213 continue
215 station = nsl_to_station[nsl]
217 n, e = od.latlon_to_ne(
218 event.lat, event.lon, station.lat, station.lon)
220 d = station.depth
222 axes_en.annotate(
223 '.'.join(x for x in nsl if x),
224 xy=(e/km, n/km),
225 xycoords='data',
226 xytext=(fontsize_annot/3., fontsize_annot/3.),
227 textcoords='offset points',
228 verticalalignment='bottom',
229 horizontalalignment='left',
230 rotation=0.,
231 size=fontsize_annot)
233 axes_en.plot(e/km, n/km, '^', mfc=color, mec=darken(color))
234 axes_dn.plot(d/km, n/km, '^', mfc=color, mec=darken(color))
235 axes_ed.plot(e/km, d/km, '^', mfc=color, mec=darken(color))
237 arr_e = tr_e.ydata
238 arr_n = tr_n.ydata
239 arr_z = tr_z.ydata
240 arr_t = tr_z.get_xdata()
242 data[nsl] = (arr_e, arr_n, arr_z, arr_t, n, e, d, color)
244 amaxs = []
245 amax_hors = []
246 for nsl in sorted(data.keys()):
247 arr_e, arr_n, arr_z, arr_t, n, e, d, color = data[nsl]
248 amaxs.append(
249 num.max(num.abs(num.sqrt(arr_e**2 + arr_n**2 + arr_z**2))))
250 amax_hors.append(
251 num.max(num.abs(num.sqrt(arr_e**2 + arr_n**2))))
253 amax = num.median(amaxs)
254 amax_hor = num.median(amax_hors)
256 for nsl in sorted(data.keys()):
257 arr_e, arr_n, arr_z, arr_t, n, e, d, color = data[nsl]
258 tmin = arr_t.min()
259 tmax = arr_t.max()
260 plot_color_line(
261 axes_en,
262 (e + arr_e/amax_hor * factor)/km, (n + arr_n/amax_hor * factor)/km,
263 arr_t, color, tmin, tmax)
264 plot_color_line(
265 axes_dn,
266 (d - arr_z/amax * factor)/km, (n + arr_n/amax * factor)/km,
267 arr_t, color, tmin, tmax)
268 plot_color_line(
269 axes_ed,
270 (e + arr_e/amax * factor)/km, (d - arr_z/amax * factor)/km,
271 arr_t, color, tmin, tmax)
273 axes_ed.invert_yaxis()
275 for axes in (axes_dn, axes_ed, axes_en):
276 axes.autoscale_view(tight=True)
278 if output_filename is None:
279 plt.show()
280 else:
281 fig.savefig(output_filename, format=output_format, dpi=output_dpi)