Coverage for /usr/local/lib/python3.11/dist-packages/pyrocko/gui/sparrow/elements/grid.py: 99%

131 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-10-06 06:59 +0000

1# https://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

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

5 

6import numpy as num 

7 

8import vtk 

9 

10from pyrocko import util, plot 

11from pyrocko.guts import Bool, Float 

12from pyrocko.gui.qt_compat import qw 

13from pyrocko.color import Color 

14 

15 

16from pyrocko.gui import vtk_util 

17from .base import Element, ElementState 

18from .. import common 

19from pyrocko.geometry import r2d, d2r 

20 

21km = 1000. 

22 

23guts_prefix = 'sparrow' 

24 

25 

26def nice_value_circle(step): 

27 step = plot.nice_value(step) 

28 if step > 30.: 

29 return 30. 

30 

31 return step 

32 

33 

34def ticks(vmin, vmax, vstep): 

35 vmin = num.floor(vmin / vstep) * vstep 

36 vmax = num.ceil(vmax / vstep) * vstep 

37 n = int(round((vmax - vmin) / vstep)) 

38 return vmin + num.arange(n+1) * vstep 

39 

40 

41class LatLonGrid(object): 

42 def __init__(self, r, step_major, step_minor, lat, lon, delta, depth): 

43 

44 lat_min, lat_max, lon_min, lon_max, lon_closed = common.cover_region( 

45 lat, lon, delta, step_major, avoid_poles=True) 

46 

47 if delta < 30.: 

48 step_major_lon = nice_value_circle(step_major/num.cos(lat*d2r)) 

49 else: 

50 step_major_lon = step_major 

51 

52 lat_majors = ticks(lat_min, lat_max, step_major) 

53 lon_majors = ticks(lon_min, lon_max, step_major_lon) 

54 

55 lat_minors = util.arange2(lat_min, lat_max, step_minor) 

56 

57 if lon_closed: 

58 lon_minors = util.arange2(-180., 180., step_minor) 

59 else: 

60 lon_minors = util.arange2(lon_min, lon_max, step_minor) 

61 

62 lines = [] 

63 for lat_major in lat_majors: 

64 points = num.zeros((lon_minors.size, 2)) 

65 points[:, 0] = lat_major 

66 points[:, 1] = lon_minors 

67 lines.append(points) 

68 

69 for lon_major in lon_majors: 

70 points = num.zeros((lat_minors.size, 2)) 

71 points[:, 0] = lat_minors 

72 points[:, 1] = lon_major 

73 lines.append(points) 

74 

75 polyline_grid = vtk_util.make_multi_polyline( 

76 lines_latlon=lines, depth=depth) 

77 

78 mapper = vtk.vtkDataSetMapper() 

79 vtk_util.vtk_set_input(mapper, polyline_grid) 

80 

81 actor = vtk.vtkActor() 

82 actor.SetMapper(mapper) 

83 

84 prop = actor.GetProperty() 

85 self.prop = prop 

86 

87 prop.SetOpacity(0.15) 

88 

89 self._color = None 

90 self.set_color(Color('white')) 

91 

92 self.actor = actor 

93 

94 def set_color(self, color): 

95 if self._color is None or self._color != color: 

96 self.prop.SetDiffuseColor(color.rgb) 

97 self._color = color 

98 

99 

100class GridState(ElementState): 

101 visible = Bool.T(default=True) 

102 color = Color.T(default=Color.D('white')) 

103 depth = Float.T(default=-1.0*km) 

104 

105 def create(self): 

106 element = GridElement() 

107 return element 

108 

109 

110class GridElement(Element): 

111 

112 def __init__(self): 

113 Element.__init__(self) 

114 self._controls = None 

115 self._grid = None 

116 self._stepsizes = self.get_stepsizes(10.) 

117 

118 def get_name(self): 

119 return 'Grid' 

120 

121 def bind_state(self, state): 

122 Element.bind_state(self, state) 

123 self.talkie_connect(state, ['visible', 'color', 'depth'], self.update) 

124 

125 def set_parent(self, parent): 

126 Element.set_parent(self, parent) 

127 self._parent.add_panel( 

128 self.get_title_label(), 

129 self._get_controls(), 

130 visible=True, 

131 title_controls=[ 

132 self.get_title_control_remove(), 

133 self.get_title_control_visible()]) 

134 

135 self.talkie_connect( 

136 self._parent.state, 

137 ['distance', 'lat', 'lon'], 

138 self.update) 

139 

140 self.update() 

141 

142 def unset_parent(self): 

143 self.unbind_state() 

144 if self._parent: 

145 if self._grid: 

146 self._parent.remove_actor(self._grid.actor) 

147 self._grid = None 

148 

149 if self._controls: 

150 self._parent.remove_panel(self._controls) 

151 self._controls = None 

152 

153 self._parent.update_view() 

154 self._parent = None 

155 

156 def get_stepsizes(self, distance): 

157 factor = 10. 

158 step_major = nice_value_circle(min(10.0, factor * distance)) 

159 step_minor = min(1.0, step_major) 

160 return step_major, step_minor 

161 

162 def update(self, *args): 

163 state = self._state 

164 pstate = self._parent.state 

165 

166 stepsizes = self.get_stepsizes(pstate.distance) 

167 if self._grid: 

168 self._parent.remove_actor(self._grid.actor) 

169 self._grid = None 

170 

171 if state.visible and not self._grid: 

172 delta = pstate.distance * r2d * 0.5 

173 self._grid = LatLonGrid( 

174 1.0, stepsizes[0], stepsizes[1], pstate.lat, pstate.lon, delta, 

175 state.depth) 

176 self._parent.add_actor(self._grid.actor) 

177 

178 if self._grid: 

179 self._grid.set_color(state.color) 

180 

181 self._parent.update_view() 

182 

183 def _get_controls(self): 

184 if not self._controls: 

185 from ..state import state_bind_combobox_color, \ 

186 state_bind_lineedit 

187 

188 frame = qw.QFrame() 

189 layout = qw.QGridLayout() 

190 frame.setLayout(layout) 

191 

192 # color 

193 

194 layout.addWidget(qw.QLabel('Color'), 0, 0) 

195 

196 cb = common.strings_to_combobox( 

197 ['black', 'white']) 

198 

199 layout.addWidget(cb, 0, 1) 

200 state_bind_combobox_color(self, self._state, 'color', cb) 

201 

202 layout.addWidget(qw.QLabel('Depth [km]'), 1, 0) 

203 le = qw.QLineEdit() 

204 layout.addWidget(le, 1, 1) 

205 state_bind_lineedit( 

206 self, self._state, 'depth', le, 

207 from_string=lambda s: float(s)*1000., 

208 to_string=lambda v: str(v/1000.)) 

209 

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

211 

212 self._controls = frame 

213 

214 return self._controls 

215 

216 

217__all__ = [ 

218 'GridElement', 

219 'GridState']