1# https://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

4# ---|P------/S----------~Lg---------- 

5 

6from __future__ import absolute_import, print_function, division 

7 

8import numpy as num 

9 

10from pyrocko.guts import Bool, Float 

11from pyrocko.gui.qt_compat import qw, qc 

12 

13from pyrocko.dataset.active_faults import ActiveFaults 

14from pyrocko.gui import vtk_util 

15from pyrocko import plot 

16import vtk 

17 

18from .base import Element, ElementState 

19 

20guts_prefix = 'sparrow' 

21 

22km = 1e3 

23 

24 

25def color(x): 

26 return num.array(plot.to01(plot.color(x)), dtype=num.float64) 

27 

28 

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')}} 

48 

49 

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) 

54 

55 def create(self): 

56 element = ActiveFaultsElement() 

57 element.bind_state(self) 

58 return element 

59 

60 

61class FaultlinesPipe(object): 

62 def __init__(self, faults): 

63 

64 self._opacity = 1.0 

65 self._line_width = 1.0 

66 self._faults = faults 

67 

68 slip_types = sorted(set(f.slip_type for f in faults.active_faults)) 

69 self._slip_types = slip_types 

70 

71 self._actors = {} 

72 for slip_type in slip_types: 

73 mapper = vtk.vtkDataSetMapper() 

74 

75 lines = [ 

76 f.get_surface_line() 

77 for f in faults.active_faults 

78 if f.slip_type == slip_type] 

79 

80 grid = vtk_util.make_multi_polyline( 

81 lines_latlon=lines, depth=-100.) 

82 

83 vtk_util.vtk_set_input(mapper, grid) 

84 

85 actor = vtk.vtkActor() 

86 actor.SetMapper(mapper) 

87 

88 self._actors[slip_type] = actor 

89 

90 self._theme = '' 

91 self.set_color_theme('uniform_light') 

92 

93 def set_color_theme(self, theme): 

94 

95 if self._theme != theme: 

96 

97 colors = fault_color_themes[theme] 

98 default_color = colors[None] 

99 

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)) 

104 

105 self._theme = theme 

106 

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) 

112 

113 self._opacity = opacity 

114 

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) 

120 

121 self._line_width = width 

122 

123 def get_actors(self): 

124 return [self._actors[slip_type] for slip_type in self._slip_types] 

125 

126 

127class ActiveFaultsElement(Element): 

128 

129 def __init__(self): 

130 Element.__init__(self) 

131 self._pipe = None 

132 self._controls = None 

133 self._active_faults = None 

134 

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') 

140 

141 def get_name(self): 

142 return 'Active Faults' 

143 

144 def set_parent(self, parent): 

145 Element.set_parent(self, parent) 

146 if not self._active_faults: 

147 self._active_faults = ActiveFaults() 

148 

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()]) 

156 

157 self.update() 

158 

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) 

165 

166 self._pipe = None 

167 

168 if self._controls: 

169 self._parent.remove_panel(self._controls) 

170 self._controls = None 

171 

172 self._parent.update_view() 

173 self._parent = None 

174 

175 def update(self, *args): 

176 

177 state = self._state 

178 if state.visible: 

179 if not self._pipe: 

180 self._pipe = FaultlinesPipe(self._active_faults) 

181 

182 if state.color_by_slip_type: 

183 self._pipe.set_color_theme('light') 

184 else: 

185 self._pipe.set_color_theme('uniform_light') 

186 

187 self._pipe.set_line_width(state.line_width) 

188 

189 if state.visible: 

190 for actor in self._pipe.get_actors(): 

191 self._parent.add_actor(actor) 

192 

193 else: 

194 for actor in self._pipe.get_actors(): 

195 self._parent.remove_actor(actor) 

196 

197 self._parent.update_view() 

198 

199 def _get_controls(self): 

200 if self._controls is None: 

201 from ..state import state_bind_checkbox, state_bind_slider 

202 

203 frame = qw.QFrame() 

204 layout = qw.QGridLayout() 

205 layout.setAlignment(qc.Qt.AlignTop) 

206 frame.setLayout(layout) 

207 

208 layout.addWidget(qw.QLabel('Line width'), 0, 0) 

209 

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) 

220 

221 cb_color_slip_type = qw.QCheckBox('Color by slip type') 

222 

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) 

226 

227 layout.addWidget(qw.QFrame(), 2, 0, 1, 2) 

228 

229 self._controls = frame 

230 

231 return self._controls 

232 

233 

234__all__ = [ 

235 'ActiveFaultsElement', 

236 'ActiveFaultsState' 

237]