1# https://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6from pyrocko.plot import automap
7from pyrocko.dataset.topo import tile
8from pyrocko.guts import String
9from pyrocko.dataset import topo
10from pyrocko.gui.qt_compat import qw, qc
12from pyrocko.gui.vtk_util import cpt_to_vtk_lookuptable
14from .base import Element
15from .topo import TopoMeshPipe, TopoCPTChoice, TopoState
17from .. import common
19guts_prefix = 'sparrow'
22class CustomTopoState(TopoState):
23 path = String.T(optional=True)
25 def create(self):
26 element = CustomTopoElement()
27 return element
30class CustomTopoElement(Element):
32 def __init__(self):
33 Element.__init__(self)
34 self._parent = None
35 self._controls = None
36 self._visible = False
37 self._mesh = None
38 self._lookuptables = {}
39 self._path_loaded = None
41 def get_name(self):
42 return 'Custom Topography'
44 def bind_state(self, state):
45 Element.bind_state(self, state)
46 self.register_state_listener3(self.update, state, 'visible')
47 self.register_state_listener3(self.update, state, 'exaggeration')
48 self.register_state_listener3(self.update, state, 'opacity')
49 self.register_state_listener3(self.update, state, 'smooth')
50 self.register_state_listener3(self.update, state, 'cpt')
51 self.register_state_listener3(self.update, state, 'path')
53 def set_parent(self, parent):
54 self._parent = parent
56 self._parent.add_panel(
57 self.get_name(),
58 self._get_controls(),
59 visible=True,
60 title_controls=[
61 self.get_title_control_remove(),
62 self.get_title_control_visible()])
64 self.update()
66 def unset_parent(self):
67 self.unbind_state()
68 if self._parent:
69 if self._mesh is not None:
70 self._parent.remove_actor(self._mesh.actor)
72 self._mesh = None
74 if self._controls:
75 self._parent.remove_panel(self._controls)
76 self._controls = None
78 self._parent.update_view()
79 self._parent = None
81 def update_cpt(self, cpt_name):
82 if cpt_name not in self._lookuptables:
83 if cpt_name == 'light':
84 topo_cpt_wet = 'light_sea'
85 topo_cpt_dry = 'light_land'
87 elif cpt_name == 'uniform':
88 topo_cpt_wet = 'light_sea_uniform'
89 topo_cpt_dry = 'light_land_uniform'
91 cpt_wet = automap.read_cpt(topo.cpt(topo_cpt_wet))
92 cpt_dry = automap.read_cpt(topo.cpt(topo_cpt_dry))
93 cpt_combi = automap.cpt_merge_wet_dry(cpt_wet, cpt_dry)
95 lut_combi = cpt_to_vtk_lookuptable(cpt_combi)
96 lut_combi.SetNanColor(0.0, 0.0, 0.0, 0.0)
98 self._lookuptables[cpt_name] = lut_combi
100 def update(self, *args):
101 visible = self._state.visible
103 self.update_cpt(self._state.cpt)
105 if visible:
106 if self._path_loaded is None and self._state.path is not None or \
107 self._state.path != self._path_loaded:
109 if self._mesh:
110 self._parent.remove_actor(self._mesh.actor)
111 self._mesh = None
113 t = tile.Tile.from_grd(self._state.path)
114 self._path_loaded = self._state.path
115 self._mesh = TopoMeshPipe(
116 t,
117 mask_ocean=False,
118 smooth=self._state.smooth,
119 lut=self._lookuptables[self._state.cpt])
121 self._parent.add_actor(self._mesh.actor)
123 if not visible and self._mesh:
124 self._parent.remove_actor(self._mesh.actor)
126 if self._mesh:
127 if visible:
128 self._parent.add_actor(self._mesh.actor)
130 self._mesh.set_exaggeration(self._state.exaggeration)
131 self._mesh.set_opacity(self._state.opacity)
132 self._mesh.set_smooth(self._state.smooth)
133 self._mesh.set_lookuptable(
134 self._lookuptables[self._state.cpt])
136 self._parent.update_view()
138 def open_file_dialog(self):
139 caption = 'Select a file to open'
141 fn, _ = qw.QFileDialog.getOpenFileName(
142 self._parent, caption, options=common.qfiledialog_options)
144 if fn:
145 self._state.path = str(fn)
147 def _get_controls(self):
148 state = self._state
149 if not self._controls:
150 from ..state import state_bind_slider, state_bind_checkbox, \
151 state_bind_combobox
153 frame = qw.QFrame()
154 layout = qw.QGridLayout()
155 frame.setLayout(layout)
157 lab = qw.QLabel('Load from:')
158 pb_file = qw.QPushButton('File')
160 layout.addWidget(lab, 0, 0)
161 layout.addWidget(pb_file, 0, 1)
163 pb_file.clicked.connect(self.open_file_dialog)
165 # exaggeration
167 layout.addWidget(qw.QLabel('Exaggeration'), 1, 0)
169 slider = qw.QSlider(qc.Qt.Horizontal)
170 slider.setSizePolicy(
171 qw.QSizePolicy(
172 qw.QSizePolicy.Expanding, qw.QSizePolicy.Fixed))
173 slider.setMinimum(0)
174 slider.setMaximum(2000)
175 layout.addWidget(slider, 1, 1)
177 state_bind_slider(self, state, 'exaggeration', slider, factor=0.01)
179 # opacity
181 layout.addWidget(qw.QLabel('Opacity'), 2, 0)
183 slider = qw.QSlider(qc.Qt.Horizontal)
184 slider.setSizePolicy(
185 qw.QSizePolicy(
186 qw.QSizePolicy.Expanding, qw.QSizePolicy.Fixed))
187 slider.setMinimum(0)
188 slider.setMaximum(1000)
189 layout.addWidget(slider, 2, 1)
191 state_bind_slider(self, state, 'opacity', slider, factor=0.001)
193 cb = qw.QCheckBox('Smooth')
194 layout.addWidget(cb, 3, 1)
195 state_bind_checkbox(self, state, 'smooth', cb)
197 cb = common.string_choices_to_combobox(TopoCPTChoice)
198 layout.addWidget(qw.QLabel('CPT'), 4, 0)
199 layout.addWidget(cb, 4, 1)
200 state_bind_combobox(self, state, 'cpt', cb)
202 layout.addWidget(qw.QFrame(), 6, 0, 1, 2)
204 self._controls = frame
206 return self._controls
209__all__ = [
210 'CustomTopoElement',
211 'CustomTopoState',
212]