1# https://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6import numpy as num
8from pyrocko.guts import Bool, Float
9from pyrocko.gui.qt_compat import qw, qc
11from pyrocko.dataset.active_faults import ActiveFaults
12from pyrocko.gui import vtk_util
13from pyrocko import plot
14import vtk
16from .base import Element, ElementState
18guts_prefix = 'sparrow'
20km = 1e3
23def color(x):
24 return num.array(plot.to01(plot.color(x)), dtype=num.float64)
27fault_color_themes = {
28 'light': {
29 'Normal': color('skyblue1'),
30 'Reverse': color('scarletred1'),
31 'SS': color('chameleon1'),
32 'Sinistral': color('plum1'),
33 'Dextral': color('plum1'),
34 None: color('chocolate1')},
35 'dark': {
36 'Normal': color('skyblue3'),
37 'Reverse': color('scarletred3'),
38 'SS': color('chameleon3'),
39 'Sinistral': color('plum3'),
40 'Dextral': color('plum3'),
41 None: color('chocolate3')},
42 'uniform_light': {
43 None: color('chocolate1')},
44 'uniform_dark': {
45 None: color('chocolate3')}}
48class ActiveFaultsState(ElementState):
49 visible = Bool.T(default=True)
50 line_width = Float.T(default=1.0)
51 color_by_slip_type = Bool.T(default=False)
53 def create(self):
54 element = ActiveFaultsElement()
55 element.bind_state(self)
56 return element
59class FaultlinesPipe(object):
60 def __init__(self, faults):
62 self._opacity = 1.0
63 self._line_width = 1.0
64 self._faults = faults
66 slip_types = sorted(set(f.slip_type for f in faults.active_faults))
67 self._slip_types = slip_types
69 self._actors = {}
70 for slip_type in slip_types:
71 mapper = vtk.vtkDataSetMapper()
73 lines = [
74 f.get_surface_line()
75 for f in faults.active_faults
76 if f.slip_type == slip_type]
78 grid = vtk_util.make_multi_polyline(
79 lines_latlon=lines, depth=-100.)
81 vtk_util.vtk_set_input(mapper, grid)
83 actor = vtk.vtkActor()
84 actor.SetMapper(mapper)
86 self._actors[slip_type] = actor
88 self._theme = ''
89 self.set_color_theme('uniform_light')
91 def set_color_theme(self, theme):
93 if self._theme != theme:
95 colors = fault_color_themes[theme]
96 default_color = colors[None]
98 for slip_type in self._slip_types:
99 actor = self._actors[slip_type]
100 prop = actor.GetProperty()
101 prop.SetDiffuseColor(*colors.get(slip_type, default_color))
103 self._theme = theme
105 def set_opacity(self, opacity):
106 opacity = float(opacity)
107 if self._opacity != opacity:
108 for actor in self._actors.values():
109 actor.GetProperty().SetOpacity(opacity)
111 self._opacity = opacity
113 def set_line_width(self, width):
114 width = float(width)
115 if self._line_width != width:
116 for actor in self._actors.values():
117 actor.GetProperty().SetLineWidth(width)
119 self._line_width = width
121 def get_actors(self):
122 return [self._actors[slip_type] for slip_type in self._slip_types]
125class ActiveFaultsElement(Element):
127 def __init__(self):
128 Element.__init__(self)
129 self._pipe = None
130 self._controls = None
131 self._active_faults = None
133 def bind_state(self, state):
134 Element.bind_state(self, state)
135 self.register_state_listener3(self.update, state, 'visible')
136 self.register_state_listener3(self.update, state, 'line_width')
137 self.register_state_listener3(self.update, state, 'color_by_slip_type')
139 def get_name(self):
140 return 'Active Faults'
142 def set_parent(self, parent):
143 Element.set_parent(self, parent)
144 if not self._active_faults:
145 self._active_faults = ActiveFaults()
147 self._parent.add_panel(
148 self.get_name(),
149 self._get_controls(),
150 visible=True,
151 title_controls=[
152 self.get_title_control_remove(),
153 self.get_title_control_visible()])
155 self.update()
157 def unset_parent(self):
158 self.unbind_state()
159 if self._parent:
160 if self._pipe:
161 for actor in self._pipe.get_actors():
162 self._parent.remove_actor(actor)
164 self._pipe = None
166 if self._controls:
167 self._parent.remove_panel(self._controls)
168 self._controls = None
170 self._parent.update_view()
171 self._parent = None
173 def update(self, *args):
175 state = self._state
176 if state.visible:
177 if not self._pipe:
178 self._pipe = FaultlinesPipe(self._active_faults)
180 if state.color_by_slip_type:
181 self._pipe.set_color_theme('light')
182 else:
183 self._pipe.set_color_theme('uniform_light')
185 self._pipe.set_line_width(state.line_width)
187 if state.visible:
188 for actor in self._pipe.get_actors():
189 self._parent.add_actor(actor)
191 else:
192 for actor in self._pipe.get_actors():
193 self._parent.remove_actor(actor)
195 self._parent.update_view()
197 def _get_controls(self):
198 if self._controls is None:
199 from ..state import state_bind_checkbox, state_bind_slider
201 frame = qw.QFrame()
202 layout = qw.QGridLayout()
203 layout.setAlignment(qc.Qt.AlignTop)
204 frame.setLayout(layout)
206 layout.addWidget(qw.QLabel('Line width'), 0, 0)
208 slider = qw.QSlider(qc.Qt.Horizontal)
209 slider.setSizePolicy(
210 qw.QSizePolicy(
211 qw.QSizePolicy.Expanding, qw.QSizePolicy.Fixed))
212 slider.setMinimum(0)
213 slider.setMaximum(10)
214 slider.setSingleStep(1)
215 slider.setPageStep(1)
216 layout.addWidget(slider, 0, 1)
217 state_bind_slider(self, self._state, 'line_width', slider)
219 cb_color_slip_type = qw.QCheckBox('Color by slip type')
221 layout.addWidget(cb_color_slip_type, 1, 0)
222 state_bind_checkbox(self, self._state, 'color_by_slip_type',
223 cb_color_slip_type)
225 layout.addWidget(qw.QFrame(), 2, 0, 1, 2)
227 self._controls = frame
229 return self._controls
232__all__ = [
233 'ActiveFaultsElement',
234 'ActiveFaultsState'
235]