1# http://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
5from __future__ import absolute_import
7from .qt_compat import qc, qw
9from .util import make_QPolygonF, LinValControl
10from .pile_viewer import Projection
12from pyrocko import beachball, moment_tensor as mtm
13from pyrocko import plot
16class BeachballView(qw.QWidget):
18 def __init__(self, *args):
19 qw.QWidget.__init__(self, *args)
20 mt = mtm.MomentTensor(m=mtm.symmat6(1., -1., 2., 0., -2., 1.))
21 self._mt = mt
22 self.set_moment_tensor(mt)
24 def set_moment_tensor(self, mt):
25 self._mt = mt
26 self.update()
28 def paintEvent(self, paint_ev):
29 '''
30 Called by QT whenever widget needs to be painted.
31 '''
33 painter = qw.QPainter(self)
34 painter.setRenderHint(qw.QPainter.Antialiasing)
35 self.drawit(painter)
37 def drawit(self, p):
38 '''
39 Draw beachball into painter.
40 '''
42 h = self.height()
43 w = self.width()
45 s = min(h, w)*0.9
47 xproj = Projection()
48 xproj.set_in_range(-1., 1.)
49 xproj.set_out_range((w-s)/2., w-(w-s)/2.)
51 yproj = Projection()
52 yproj.set_in_range(-1., 1.)
53 yproj.set_out_range(h-(h-s)/2., (h-s)/2.)
55 # m = mtm.symmat6(*(num.random.random(6)*2.-1.))
56 # mtm.MomentTensor(m=m)
58 mt = self._mt
60 mt_devi = mt.deviatoric()
61 eig = mt_devi.eigensystem()
63 group_to_color = {
64 'P': plot.graph_colors[0],
65 'T': plot.graph_colors[1]}
67 for (group, patches, patches_lower, patches_upper,
68 lines, lines_lower, lines_upper) in beachball.eig2gx(eig):
70 color = group_to_color[group]
71 brush = qw.QBrush(qw.QColor(*color))
72 p.setBrush(brush)
74 pen = qw.QPen(qw.QColor(*color))
75 pen.setWidth(1)
76 p.setPen(pen)
78 for poly in patches_lower:
79 px, py, pz = poly.T
80 points = make_QPolygonF(xproj(px), yproj(py))
81 p.drawPolygon(points)
83 color = (0, 0, 0)
84 pen = qw.QPen(qw.QColor(*color))
85 pen.setWidth(2)
86 p.setPen(pen)
88 for poly in lines_lower:
89 px, py, pz = poly.T
90 points = make_QPolygonF(xproj(px), yproj(py))
91 p.drawPolyline(points)
94class MomentTensorEditor(qw.QFrame):
96 moment_tensor_changed = qc.pyqtSignal(object)
98 def __init__(self, *args):
99 qw.QFrame.__init__(self, *args)
101 self._mt = mtm.MomentTensor(m=mtm.symmat6(1., -1., 2., 0., -2., 1.))
103 setupdata = [
104 (LinValControl, 'Strike 1', 0., 360., 0., 0),
105 (LinValControl, 'Dip 1', 0., 90., 0., 1),
106 (LinValControl, 'Slip-Rake 1', -180., 180., 0., 2),
107 (LinValControl, 'Strike 2', 0., 360., 0., 3),
108 (LinValControl, 'Dip 2', 0., 90., 0., 4),
109 (LinValControl, 'Slip-Rake 2', -180., 180., 0., 5)]
111 layout = qw.QGridLayout()
112 self.setLayout(layout)
114 val_controls = []
115 for irow, (typ, name, vmin, vmax, vcur, ind) in enumerate(setupdata):
116 val_control = typ()
117 val_control.setup(name, vmin, vmax, vcur, ind)
118 val_controls.append(val_control)
119 for icol, widget in enumerate(val_control.widgets()):
120 layout.addWidget(widget, irow, icol)
121 val_control.valchanged.connect(
122 self.valchange)
124 self.val_controls = val_controls
125 self.adjust_values()
127 def adjust_values(self):
129 ((strike1, dip1, rake1),
130 (strike2, dip2, rake2)) = self._mt.both_strike_dip_rake()
132 for val_control, value in zip(
133 self.val_controls, [
134 strike1, dip1, rake1, strike2, dip2, rake2]):
135 val_control.set_value(value)
137 def valchange(self, val, ind):
138 strike, dip, rake = [
139 val_control.get_value() for val_control in self.val_controls[:3]]
141 self._mt = mtm.MomentTensor(
142 strike=strike, dip=dip, rake=rake)
144 self.adjust_values()
146 self.moment_tensor_changed.emit(
147 self._mt)