Coverage for /usr/local/lib/python3.11/dist-packages/grond/problems/double_dc/plot.py: 27%
62 statements
« prev ^ index » next coverage.py v6.5.0, created at 2025-04-03 09:31 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2025-04-03 09:31 +0000
1# https://pyrocko.org/grond - GPLv3
2#
3# The Grond Developers, 21st Century
4import math
5import logging
7from matplotlib import pyplot as plt
9from pyrocko.guts import Float, Tuple
10from pyrocko import gf
11from pyrocko.plot import mpl_init, beachball, mpl_color
13from grond import stats
14from grond.plot.collection import PlotItem
15from grond.plot.config import PlotConfig
17logger = logging.getLogger('grond.problem.double_dc.plot')
19guts_prefix = 'grond'
21km = 1e3
24class DoubleDCDecompositionPlot(PlotConfig):
25 '''
26 Double DC decomposition plot.
27 '''
28 name = 'dc_decomposition'
29 size_cm = Tuple.T(2, Float.T(), default=(15., 5.))
31 def make(self, environ):
32 cm = environ.get_plot_collection_manager()
33 history = environ.get_history(subset='harvest')
34 mpl_init(fontsize=self.font_size)
35 cm.create_group_mpl(
36 self,
37 self.draw_figures(history),
38 title=u'Double DC Decomposition',
39 section='solution',
40 feather_icon='sun',
41 description=u'''
42Double DC decomposition of the best and mean solution into its two contributing
43focal mechanisms.
44Shown are the ensemble best and the ensemble mean. The symbol size indicates
45the relative strength of the mechanisms. The inversion result is consistent
46and stable if ensemble mean and ensemble best have similar symbol size and
47patterns.
48''')
50 def draw_figures(self, history):
51 fontsize = self.font_size
53 fig = plt.figure(figsize=self.size_inch)
54 axes = fig.add_subplot(1, 1, 1, aspect=1.0)
56 fig.subplots_adjust(left=0., right=1., bottom=0., top=1.)
58 problem = history.problem
59 models = history.models
60 if models.size == 0:
61 logger.warn('Empty models vector.')
62 return []
64 mean_source = stats.get_mean_source(
65 problem, history.models)
66 best_source = history.get_best_source()
67 nlines_max = int(round(self.size_cm[1] / 5. * 4. - 1.0))
69 def get_deco(source):
70 if isinstance(source, gf.DoubleDCSource):
71 return [source] + source.split()
73 lines = []
74 lines.append(
75 ('Ensemble best', get_deco(best_source), mpl_color('aluminium5')))
76 lines.append(
77 ('Ensemble mean', get_deco(mean_source), mpl_color('aluminium5')))
79 mag_max = max(dc.magnitude for (_, line, _) in lines for dc in line)
81 for xpos, label in [
82 (0., 'Double DC'),
83 (2., 'DC 1'),
84 (4., 'DC 2')]:
86 axes.annotate(
87 label,
88 xy=(1 + xpos, nlines_max),
89 xycoords='data',
90 xytext=(0., 0.),
91 textcoords='offset points',
92 ha='center',
93 va='center',
94 color='black',
95 fontsize=fontsize)
97 for i, (label, deco, color_t) in enumerate(lines):
98 ypos = nlines_max - i - 1.0
99 [ddc, dc1, dc2] = deco
100 size0 = ddc.magnitude / mag_max
102 axes.annotate(
103 label,
104 xy=(-2., ypos),
105 xycoords='data',
106 xytext=(0., 0.),
107 textcoords='offset points',
108 ha='left',
109 va='center',
110 color='black',
111 fontsize=fontsize)
113 for xpos, dc_part, ratio, ops in [
114 (0., ddc, 1., '='),
115 (2., dc1, dc1.magnitude / mag_max, '+'),
116 (4., dc2, dc2.magnitude / mag_max, None)]:
118 if ratio > 1e-4:
119 try:
120 beachball.plot_beachball_mpl(
121 dc_part.pyrocko_moment_tensor(), axes,
122 position=(1. + xpos, ypos),
123 size=0.9 * size0 * math.sqrt(ratio),
124 size_units='data',
125 color_t=color_t,
126 linewidth=1.0)
127 except beachball.BeachballError as e:
128 logger.warn(str(e))
129 axes.annotate(
130 'ERROR',
131 xy=(1. + xpos, ypos),
132 ha='center',
133 va='center',
134 color='red',
135 fontsize=fontsize)
136 else:
137 axes.annotate(
138 'N/A',
139 xy=(1. + xpos, ypos),
140 ha='center',
141 va='center',
142 color='black',
143 fontsize=fontsize)
144 if ops is not None:
145 axes.annotate(
146 ops,
147 xy=(2. + xpos, ypos),
148 ha='center',
149 va='center',
150 color='black',
151 fontsize=fontsize)
152 axes.axison = False
153 axes.set_xlim(-2.25, 9.75)
154 axes.set_ylim(-0.5, nlines_max+0.5)
155 item = PlotItem(name='main')
156 return [[item, fig]]