1# https://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6from __future__ import absolute_import, print_function, division
8import numpy as num
10from pyrocko.guts import Bool, Float
11from pyrocko.gui.qt_compat import qw, qc
13from pyrocko.dataset.active_faults import ActiveFaults
14from pyrocko.gui import vtk_util
15from pyrocko import plot
16import vtk
18from .base import Element, ElementState
20guts_prefix = 'sparrow'
22km = 1e3
25def color(x):
26 return num.array(plot.to01(plot.color(x)), dtype=num.float64)
29fault_color_themes = {
30 'light': {
31 'Normal': color('skyblue1'),
32 'Reverse': color('scarletred1'),
33 'SS': color('chameleon1'),
34 'Sinistral': color('plum1'),
35 'Dextral': color('plum1'),
36 None: color('chocolate1')},
37 'dark': {
38 'Normal': color('skyblue3'),
39 'Reverse': color('scarletred3'),
40 'SS': color('chameleon3'),
41 'Sinistral': color('plum3'),
42 'Dextral': color('plum3'),
43 None: color('chocolate3')},
44 'uniform_light': {
45 None: color('chocolate1')},
46 'uniform_dark': {
47 None: color('chocolate3')}}
50class ActiveFaultsState(ElementState):
51 visible = Bool.T(default=True)
52 line_width = Float.T(default=1.0)
53 color_by_slip_type = Bool.T(default=False)
55 def create(self):
56 element = ActiveFaultsElement()
57 element.bind_state(self)
58 return element
61class FaultlinesPipe(object):
62 def __init__(self, faults):
64 self._opacity = 1.0
65 self._line_width = 1.0
66 self._faults = faults
68 slip_types = sorted(set(f.slip_type for f in faults.active_faults))
69 self._slip_types = slip_types
71 self._actors = {}
72 for slip_type in slip_types:
73 mapper = vtk.vtkDataSetMapper()
75 lines = [
76 f.get_surface_line()
77 for f in faults.active_faults
78 if f.slip_type == slip_type]
80 grid = vtk_util.make_multi_polyline(
81 lines_latlon=lines, depth=-100.)
83 vtk_util.vtk_set_input(mapper, grid)
85 actor = vtk.vtkActor()
86 actor.SetMapper(mapper)
88 self._actors[slip_type] = actor
90 self._theme = ''
91 self.set_color_theme('uniform_light')
93 def set_color_theme(self, theme):
95 if self._theme != theme:
97 colors = fault_color_themes[theme]
98 default_color = colors[None]
100 for slip_type in self._slip_types:
101 actor = self._actors[slip_type]
102 prop = actor.GetProperty()
103 prop.SetDiffuseColor(*colors.get(slip_type, default_color))
105 self._theme = theme
107 def set_opacity(self, opacity):
108 opacity = float(opacity)
109 if self._opacity != opacity:
110 for actor in self._actors.values():
111 actor.GetProperty().SetOpacity(opacity)
113 self._opacity = opacity
115 def set_line_width(self, width):
116 width = float(width)
117 if self._line_width != width:
118 for actor in self._actors.values():
119 actor.GetProperty().SetLineWidth(width)
121 self._line_width = width
123 def get_actors(self):
124 return [self._actors[slip_type] for slip_type in self._slip_types]
127class ActiveFaultsElement(Element):
129 def __init__(self):
130 Element.__init__(self)
131 self._pipe = None
132 self._controls = None
133 self._active_faults = None
135 def bind_state(self, state):
136 Element.bind_state(self, state)
137 self.register_state_listener3(self.update, state, 'visible')
138 self.register_state_listener3(self.update, state, 'line_width')
139 self.register_state_listener3(self.update, state, 'color_by_slip_type')
141 def get_name(self):
142 return 'Active Faults'
144 def set_parent(self, parent):
145 Element.set_parent(self, parent)
146 if not self._active_faults:
147 self._active_faults = ActiveFaults()
149 self._parent.add_panel(
150 self.get_name(),
151 self._get_controls(),
152 visible=True,
153 title_controls=[
154 self.get_title_control_remove(),
155 self.get_title_control_visible()])
157 self.update()
159 def unset_parent(self):
160 self.unbind_state()
161 if self._parent:
162 if self._pipe:
163 for actor in self._pipe.get_actors():
164 self._parent.remove_actor(actor)
166 self._pipe = None
168 if self._controls:
169 self._parent.remove_panel(self._controls)
170 self._controls = None
172 self._parent.update_view()
173 self._parent = None
175 def update(self, *args):
177 state = self._state
178 if state.visible:
179 if not self._pipe:
180 self._pipe = FaultlinesPipe(self._active_faults)
182 if state.color_by_slip_type:
183 self._pipe.set_color_theme('light')
184 else:
185 self._pipe.set_color_theme('uniform_light')
187 self._pipe.set_line_width(state.line_width)
189 if state.visible:
190 for actor in self._pipe.get_actors():
191 self._parent.add_actor(actor)
193 else:
194 for actor in self._pipe.get_actors():
195 self._parent.remove_actor(actor)
197 self._parent.update_view()
199 def _get_controls(self):
200 if self._controls is None:
201 from ..state import state_bind_checkbox, state_bind_slider
203 frame = qw.QFrame()
204 layout = qw.QGridLayout()
205 layout.setAlignment(qc.Qt.AlignTop)
206 frame.setLayout(layout)
208 layout.addWidget(qw.QLabel('Line width'), 0, 0)
210 slider = qw.QSlider(qc.Qt.Horizontal)
211 slider.setSizePolicy(
212 qw.QSizePolicy(
213 qw.QSizePolicy.Expanding, qw.QSizePolicy.Fixed))
214 slider.setMinimum(0)
215 slider.setMaximum(10)
216 slider.setSingleStep(1)
217 slider.setPageStep(1)
218 layout.addWidget(slider, 0, 1)
219 state_bind_slider(self, self._state, 'line_width', slider)
221 cb_color_slip_type = qw.QCheckBox('Color by slip type')
223 layout.addWidget(cb_color_slip_type, 1, 0)
224 state_bind_checkbox(self, self._state, 'color_by_slip_type',
225 cb_color_slip_type)
227 layout.addWidget(qw.QFrame(), 2, 0, 1, 2)
229 self._controls = frame
231 return self._controls
234__all__ = [
235 'ActiveFaultsElement',
236 'ActiveFaultsState'
237]