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 2023-10-26 16:25 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2023-10-26 16:25 +0000
1import logging
2from collections import defaultdict
4import numpy as num
6from matplotlib import pyplot as plt
7from mpl_toolkits.axes_grid1 import ImageGrid
9from pyrocko import gf, orthodrome as od, plot, model, trace
10from grond import dataset
11from grond.meta import store_t
13km = 1000.
15logger = logging.getLogger('grond.qc')
18def darken(c):
19 return (c[0]*0.5, c[1]*0.5, c[2]*0.5)
22def plot_color_line(axes, x, y, t, color, tmin, tmax):
23 from matplotlib.colors import LinearSegmentedColormap
24 from matplotlib.collections import LineCollection
26 cmap = LinearSegmentedColormap.from_list(
27 'noname', [color, (1., 1., 1.)], 100)
29 points = num.array([x, y], dtype=float).T.reshape(-1, 1, 2)
30 segments = num.concatenate([points[:-1], points[1:]], axis=1)
31 lc = LineCollection(segments, cmap=cmap, norm=plt.Normalize(tmin, tmax))
32 lc.set_array(t)
33 axes.add_collection(lc, autolim=True)
36def polarization(
37 ds, store, timing, fmin, fmax, ffactor,
38 time_factor_pre=2.,
39 time_factor_post=2.,
40 distance_min=None,
41 distance_max=None,
42 depth_min=None,
43 depth_max=None,
44 size_factor=0.05,
45 nsl_to_time=None,
46 output_filename=None,
47 output_format=None,
48 output_dpi=None):
50 event = ds.get_event()
51 stations = ds.get_stations()
53 source = gf.Source.from_pyrocko_event(event)
55 trs = []
56 for station in stations:
58 nsl = station.nsl()
60 dist = source.distance_to(station)
62 if distance_min is not None and dist < distance_min:
63 continue
65 if distance_max is not None and distance_max < dist:
66 continue
68 if depth_min is not None and station.depth < depth_min:
69 continue
71 if depth_max is not None and depth_max < station.depth:
72 continue
74 if nsl_to_time is None:
75 tp = event.time + store_t(store, timing, source, station)
77 else:
78 if nsl not in nsl_to_time:
79 continue
81 tp = nsl_to_time[nsl]
83 for component in 'ZNE':
85 tmin = tp - time_factor_pre / fmin
86 tmax = tp + time_factor_post / fmin
88 nslc = nsl + (component,)
90 freqlimits = [
91 fmin / ffactor,
92 fmin,
93 fmax,
94 fmax * ffactor]
96 tfade = 1.0 / (fmin / ffactor)
98 try:
99 trs_projected, trs_restituted, trs_raw, _ = \
100 ds.get_waveform(
101 nslc,
102 tmin=tmin,
103 tmax=tmax,
104 tfade=tfade,
105 freqlimits=freqlimits,
106 debug=True)
108 for tr in trs_projected:
109 tr.shift(-tp)
111 trs.extend(trs_projected)
113 except dataset.NotFound as e:
114 logger.warning(str(e))
115 continue
117 trace.snuffle(trs, stations=stations)
119 plot_polarizations(
120 stations, trs,
121 event=event,
122 size_factor=size_factor,
123 output_filename=output_filename,
124 output_format=output_format,
125 output_dpi=output_dpi)
128def plot_polarizations(
129 stations, trs,
130 event=None,
131 size_factor=0.05,
132 fontsize=10.,
133 output_filename=None,
134 output_format=None,
135 output_dpi=None):
137 if event is None:
138 slats = num.array([s.lat for s in stations], dtype=float)
139 slons = num.array([s.lon for s in stations], dtype=float)
140 clat, clon = od.geographic_midpoint(slats, slons)
141 event = od.Loc(clat, clon)
143 nsl_c_to_trs = defaultdict(dict)
144 for tr in trs:
145 nsl_c_to_trs[tr.nslc_id[:3]][tr.nslc_id[3]] = tr
147 nsl_to_station = dict(
148 (s.nsl(), s) for s in stations)
150 plot.mpl_init(fontsize=fontsize)
151 fig = plt.figure(figsize=plot.mpl_papersize('a4', 'landscape'))
152 plot.mpl_margins(fig, w=7., h=6., units=fontsize)
154 grid = ImageGrid(
155 fig, 111, nrows_ncols=(2, 2),
156 axes_pad=0.5,
157 add_all=True,
158 label_mode='L',
159 aspect=True)
161 axes_en = grid[0]
162 axes_en.set_ylabel('Northing [km]')
164 axes_dn = grid[1]
165 axes_dn.locator_params(axis='x', nbins=4)
166 axes_dn.set_xlabel('Depth [km]')
168 axes_ed = grid[2]
169 axes_ed.locator_params(axis='y', nbins=4)
170 axes_ed.set_ylabel('Depth [km]')
171 axes_ed.set_xlabel('Easting [km]')
173 if isinstance(event, model.Event):
174 axes_en.plot(0., 0., '*')
175 axes_dn.plot(event.depth/km, 0., '*')
176 axes_ed.plot(0., event.depth/km, '*')
178 grid[3].set_axis_off()
180 locations = []
181 for nsl in sorted(nsl_c_to_trs.keys()):
182 station = nsl_to_station[nsl]
183 n, e = od.latlon_to_ne(
184 event.lat, event.lon, station.lat, station.lon)
186 locations.append((n, e))
188 ns, es = num.array(locations, dtype=float).T
190 n_min = num.min(ns)
191 n_max = num.max(ns)
192 e_min = num.min(es)
193 e_max = num.max(es)
195 factor = max((n_max - n_min) * size_factor, (e_max - e_min) * size_factor)
197 fontsize_annot = fontsize * 0.7
199 data = {}
200 for insl, nsl in enumerate(sorted(nsl_c_to_trs.keys())):
202 color = plot.mpl_graph_color(insl)
204 try:
205 tr_e = nsl_c_to_trs[nsl]['E']
206 tr_n = nsl_c_to_trs[nsl]['N']
207 tr_z = nsl_c_to_trs[nsl]['Z']
209 except KeyError:
210 continue
212 station = nsl_to_station[nsl]
214 n, e = od.latlon_to_ne(
215 event.lat, event.lon, station.lat, station.lon)
217 d = station.depth
219 axes_en.annotate(
220 '.'.join(x for x in nsl if x),
221 xy=(e/km, n/km),
222 xycoords='data',
223 xytext=(fontsize_annot/3., fontsize_annot/3.),
224 textcoords='offset points',
225 verticalalignment='bottom',
226 horizontalalignment='left',
227 rotation=0.,
228 size=fontsize_annot)
230 axes_en.plot(e/km, n/km, '^', mfc=color, mec=darken(color))
231 axes_dn.plot(d/km, n/km, '^', mfc=color, mec=darken(color))
232 axes_ed.plot(e/km, d/km, '^', mfc=color, mec=darken(color))
234 arr_e = tr_e.ydata
235 arr_n = tr_n.ydata
236 arr_z = tr_z.ydata
237 arr_t = tr_z.get_xdata()
239 data[nsl] = (arr_e, arr_n, arr_z, arr_t, n, e, d, color)
241 amaxs = []
242 amax_hors = []
243 for nsl in sorted(data.keys()):
244 arr_e, arr_n, arr_z, arr_t, n, e, d, color = data[nsl]
245 amaxs.append(
246 num.max(num.abs(num.sqrt(arr_e**2 + arr_n**2 + arr_z**2))))
247 amax_hors.append(
248 num.max(num.abs(num.sqrt(arr_e**2 + arr_n**2))))
250 amax = num.median(amaxs)
251 amax_hor = num.median(amax_hors)
253 for nsl in sorted(data.keys()):
254 arr_e, arr_n, arr_z, arr_t, n, e, d, color = data[nsl]
255 tmin = arr_t.min()
256 tmax = arr_t.max()
257 plot_color_line(
258 axes_en,
259 (e + arr_e/amax_hor * factor)/km, (n + arr_n/amax_hor * factor)/km,
260 arr_t, color, tmin, tmax)
261 plot_color_line(
262 axes_dn,
263 (d - arr_z/amax * factor)/km, (n + arr_n/amax * factor)/km,
264 arr_t, color, tmin, tmax)
265 plot_color_line(
266 axes_ed,
267 (e + arr_e/amax * factor)/km, (d - arr_z/amax * factor)/km,
268 arr_t, color, tmin, tmax)
270 axes_ed.invert_yaxis()
272 for axes in (axes_dn, axes_ed, axes_en):
273 axes.autoscale_view(tight=True)
275 if output_filename is None:
276 plt.show()
277 else:
278 fig.savefig(output_filename, format=output_format, dpi=output_dpi)