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-04 09:52 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2023-10-04 09:52 +0000
1# https://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6import numpy as num
8import vtk
10from pyrocko import util, plot
11from pyrocko.guts import Bool, Float
12from pyrocko.gui.qt_compat import qw
13from pyrocko.color import Color
16from pyrocko.gui import vtk_util
17from .base import Element, ElementState
18from .. import common
19from pyrocko.geometry import r2d, d2r
21km = 1000.
23guts_prefix = 'sparrow'
26def nice_value_circle(step):
27 step = plot.nice_value(step)
28 if step > 30.:
29 return 30.
31 return step
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
41class LatLonGrid(object):
42 def __init__(self, r, step_major, step_minor, lat, lon, delta, depth):
44 lat_min, lat_max, lon_min, lon_max, lon_closed = common.cover_region(
45 lat, lon, delta, step_major, avoid_poles=True)
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
52 lat_majors = ticks(lat_min, lat_max, step_major)
53 lon_majors = ticks(lon_min, lon_max, step_major_lon)
55 lat_minors = util.arange2(lat_min, lat_max, step_minor)
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)
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)
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)
75 polyline_grid = vtk_util.make_multi_polyline(
76 lines_latlon=lines, depth=depth)
78 mapper = vtk.vtkDataSetMapper()
79 vtk_util.vtk_set_input(mapper, polyline_grid)
81 actor = vtk.vtkActor()
82 actor.SetMapper(mapper)
84 prop = actor.GetProperty()
85 self.prop = prop
87 prop.SetOpacity(0.15)
89 self._color = None
90 self.set_color(Color('white'))
92 self.actor = actor
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
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)
105 def create(self):
106 element = GridElement()
107 return element
110class GridElement(Element):
112 def __init__(self):
113 Element.__init__(self)
114 self._controls = None
115 self._grid = None
116 self._stepsizes = self.get_stepsizes(10.)
118 def get_name(self):
119 return 'Grid'
121 def bind_state(self, state):
122 Element.bind_state(self, state)
123 self.talkie_connect(state, ['visible', 'color', 'depth'], self.update)
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()])
135 self.talkie_connect(
136 self._parent.state,
137 ['distance', 'lat', 'lon'],
138 self.update)
140 self.update()
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
149 if self._controls:
150 self._parent.remove_panel(self._controls)
151 self._controls = None
153 self._parent.update_view()
154 self._parent = None
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
162 def update(self, *args):
163 state = self._state
164 pstate = self._parent.state
166 stepsizes = self.get_stepsizes(pstate.distance)
167 if self._grid:
168 self._parent.remove_actor(self._grid.actor)
169 self._grid = None
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)
178 if self._grid:
179 self._grid.set_color(state.color)
181 self._parent.update_view()
183 def _get_controls(self):
184 if not self._controls:
185 from ..state import state_bind_combobox_color, \
186 state_bind_lineedit
188 frame = qw.QFrame()
189 layout = qw.QGridLayout()
190 frame.setLayout(layout)
192 # color
194 layout.addWidget(qw.QLabel('Color'), 0, 0)
196 cb = common.strings_to_combobox(
197 ['black', 'white'])
199 layout.addWidget(cb, 0, 1)
200 state_bind_combobox_color(self, self._state, 'color', cb)
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.))
210 layout.addWidget(qw.QFrame(), 2, 0, 1, 2)
212 self._controls = frame
214 return self._controls
217__all__ = [
218 'GridElement',
219 'GridState']