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