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

185 statements  

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

1# https://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

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

5 

6import copy 

7import logging 

8try: 

9 from kite import Scene 

10except ImportError: 

11 Scene = None 

12 

13import numpy as num 

14 

15from pyrocko import geometry, cake 

16from pyrocko.guts import Bool, String, List 

17from pyrocko.gui.qt_compat import qw 

18from pyrocko.gui.vtk_util import TrimeshPipe, faces_to_cells 

19 

20from .. import common 

21 

22from .base import Element, ElementState, CPTHandler, CPTState 

23 

24logger = logging.getLogger('kite_scene') 

25guts_prefix = 'sparrow' 

26 

27km = 1e3 

28d2r = num.pi/180. 

29 

30 

31class SceneTileAdapter(object): 

32 

33 def __init__(self, scene): 

34 self._scene = scene 

35 

36 def x(self): 

37 # TODO how to handle E given in m 

38 frame = self._scene.frame 

39 x = num.zeros(frame.cols + 1) 

40 x[0] = frame.E[0] - 0.5 * frame.dE 

41 x[1:] = frame.E + 0.5 * frame.dE 

42 x += frame.llLon 

43 return x 

44 

45 def y(self): 

46 # TODO how to handle N given in m 

47 frame = self._scene.frame 

48 y = num.zeros(frame.rows + 1) 

49 y[0] = frame.N[0] - 0.5 * frame.dN 

50 y[1:] = frame.N + 0.5 * frame.dN 

51 y += frame.llLat 

52 return y 

53 

54 @property 

55 def data(self): 

56 disp = self._scene.displacement 

57 disp[num.isnan(disp)] = None 

58 return disp 

59 

60 

61class KiteMeshPipe(TrimeshPipe): 

62 def __init__(self, tile, cells_cache=None, **kwargs): 

63 lat_edge = tile.y() 

64 lon_edge = tile.x() 

65 data_center = tile.data 

66 

67 nlat = lat_edge.size 

68 nlon = lon_edge.size 

69 

70 assert nlat > 1 and nlon > 1 

71 assert data_center.shape == (nlat-1, nlon-1) 

72 

73 ele = num.zeros((nlat, nlon)) 

74 ele[:-1, :-1] = data_center * 100000. 

75 vertices, faces = geometry.topo_to_mesh( 

76 lat_edge, lon_edge, ele, cake.earthradius) 

77 

78 self._raw_vertices = vertices 

79 

80 if cells_cache is not None: 

81 if id(faces) not in cells_cache: 

82 cells_cache[id(faces)] = faces_to_cells(faces) 

83 

84 cells = cells_cache[id(faces)] 

85 else: 

86 cells = faces_to_cells(faces) 

87 

88 data_center = data_center.flatten() 

89 

90 TrimeshPipe.__init__( 

91 self, vertices, 

92 cells=cells, values=data_center, **kwargs) 

93 

94 

95class KiteSceneElement(ElementState): 

96 visible = Bool.T(default=True) 

97 filename = String.T() 

98 scene = None 

99 

100 

101class KiteState(ElementState): 

102 visible = Bool.T(default=True) 

103 scenes = List.T(KiteSceneElement.T(), default=[]) 

104 cpt = CPTState.T(default=CPTState.D(cpt_name='seismic_r')) 

105 

106 def create(self): 

107 element = KiteElement() 

108 return element 

109 

110 def add_scene(self, scene): 

111 self.scenes.append(scene) 

112 

113 def remove_scene(self, scene): 

114 if scene in self.scenes: 

115 self.scenes.remove(scene) 

116 

117 

118class KiteElement(Element): 

119 

120 def __init__(self): 

121 Element.__init__(self) 

122 self._controls = None 

123 self._meshes = {} 

124 self._cells = {} 

125 self.cpt_handler = CPTHandler() 

126 

127 def bind_state(self, state): 

128 Element.bind_state(self, state) 

129 self.talkie_connect(state, ['visible', 'scenes'], self.update) 

130 

131 self.cpt_handler.bind_state(state.cpt, self.update) 

132 

133 def unbind_state(self): 

134 self.cpt_handler.unbind_state() 

135 Element.unbind_state(self) 

136 

137 def get_name(self): 

138 return 'Kite InSAR Scenes' 

139 

140 def set_parent(self, parent): 

141 if Scene is None: 

142 qw.QMessageBox.warning( 

143 parent, 'Import Error', 

144 'Software package Kite is needed to display InSAR scenes!') 

145 return 

146 

147 self._parent = parent 

148 self._parent.add_panel( 

149 self.get_title_label(), 

150 self._get_controls(), 

151 visible=True, 

152 title_controls=[ 

153 self.get_title_control_remove(), 

154 self.get_title_control_visible()]) 

155 

156 self.update() 

157 

158 def unset_parent(self): 

159 self.unbind_state() 

160 if self._parent: 

161 for mesh in self._meshes: 

162 self._parent.remove_actor(mesh.actor) 

163 

164 self._meshes.clear() 

165 self._cells.clear() 

166 

167 if self._controls: 

168 self._parent.remove_panel(self._controls) 

169 self._controls = None 

170 

171 self._parent.update_view() 

172 self._parent = None 

173 

174 def _load_scene_from_fn(self, fn): 

175 try: 

176 scene = Scene.load(fn) 

177 except ImportError: 

178 qw.QMessageBox.warning( 

179 self._parent, 'Import Error', 

180 'Could not load Kite scene from %s' % fn) 

181 return 

182 

183 if scene.frame.spacing != 'degree': 

184 logger.warning( 

185 'Sparrow requires Scene spacing in degrees. ' 

186 'Skipped %s', fn) 

187 

188 return 

189 

190 return scene 

191 

192 def open_load_scene_dialog(self, *args): 

193 caption = 'Select one or more Kite scenes to open' 

194 

195 fns, _ = qw.QFileDialog.getOpenFileNames( 

196 self._parent, caption, 

197 filter='YAML file (*.yml *.yaml)', 

198 options=common.qfiledialog_options) 

199 

200 for fname in fns: 

201 scene = self._load_scene_from_fn(fname) 

202 

203 if scene is None: 

204 continue 

205 

206 logger.debug('Adding Kite scene %s', fname) 

207 

208 scene_element = KiteSceneElement(filename=fname) 

209 scene_element.scene = scene 

210 self._state.add_scene(scene_element) 

211 

212 self.update() 

213 

214 def clear_scenes(self, *args): 

215 logger.debug('Clearing all loaded Kite scenes') 

216 

217 for mesh in self._meshes.values(): 

218 self._parent.remove_actor(mesh.actor) 

219 

220 self._meshes.clear() 

221 self._state.scenes = [] 

222 

223 self.update() 

224 

225 def update(self, *args): 

226 state = self._state 

227 

228 for mesh in self._meshes.values(): 

229 self._parent.remove_actor(mesh.actor) 

230 

231 if self._state.visible: 

232 for scene_element in state.scenes: 

233 logger.debug('Drawing Kite scene') 

234 

235 if scene_element.scene is None: 

236 scene_element.scene = self._load_scene_from_fn( 

237 scene_element.filename) 

238 

239 scene = scene_element.scene 

240 

241 scene_tile = SceneTileAdapter(scene) 

242 

243 k = (scene_tile, state.cpt.cpt_name) 

244 

245 if k not in self._meshes: 

246 cpt = copy.deepcopy( 

247 self.cpt_handler._cpts[state.cpt.cpt_name]) 

248 

249 mesh = KiteMeshPipe( 

250 scene_tile, 

251 cells_cache=None, 

252 cpt=cpt, 

253 backface_culling=False) 

254 

255 values = scene_tile.data.flatten() 

256 self.cpt_handler._values = values 

257 self.cpt_handler.update_cpt() 

258 

259 mesh.set_shading('phong') 

260 mesh.set_lookuptable(self.cpt_handler._lookuptable) 

261 

262 self._meshes[k] = mesh 

263 else: 

264 mesh = self._meshes[k] 

265 self.cpt_handler.update_cpt() 

266 

267 if scene_element.visible: 

268 self._parent.add_actor(mesh.actor) 

269 

270 self._parent.update_view() 

271 

272 def _get_controls(self): 

273 if not self._controls: 

274 frame = qw.QFrame() 

275 layout = qw.QGridLayout() 

276 frame.setLayout(layout) 

277 

278 pb_load = qw.QPushButton('Add Scene') 

279 pb_load.clicked.connect(self.open_load_scene_dialog) 

280 layout.addWidget(pb_load, 0, 1) 

281 

282 pb_clear = qw.QPushButton('Clear Scenes') 

283 pb_clear.clicked.connect(self.clear_scenes) 

284 layout.addWidget(pb_clear, 0, 2) 

285 

286 self.cpt_handler.cpt_controls( 

287 self._parent, self._state.cpt, layout) 

288 

289 layout.addWidget(qw.QFrame(), 4, 0, 1, 3) 

290 

291 self._controls = frame 

292 

293 self._update_controls() 

294 

295 return self._controls 

296 

297 def _update_controls(self): 

298 self.cpt_handler._update_cpt_combobox() 

299 self.cpt_handler._update_cptscale_lineedit() 

300 

301 

302__all__ = [ 

303 'KiteState', 

304 'KiteElement' 

305]