Coverage for /usr/local/lib/python3.11/dist-packages/pyrocko/gui/sparrow/elements/stations.py: 27%
148 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-10-23 12:34 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2023-10-23 12:34 +0000
1# https://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6import numpy as num
8from pyrocko.guts import \
9 Object, Bool, Float, StringChoice, Timestamp, String, List
11from pyrocko import cake, table, model, geometry
12from pyrocko.client import fdsn
13from pyrocko.gui.qt_compat import qw, qc
15from pyrocko.gui.vtk_util import ScatterPipe
16from .. import common
18from .base import Element, ElementState
20guts_prefix = 'sparrow'
23def stations_to_points(stations):
24 coords = num.zeros((len(stations), 3))
26 for i, s in enumerate(stations):
27 coords[i, :] = s.lat, s.lon, -s.elevation
29 station_table = table.Table()
31 station_table.add_col(('coords', '', ('lat', 'lon', 'depth')), coords)
33 return geometry.latlondepth2xyz(
34 station_table.get_col('coords'),
35 planetradius=cake.earthradius)
38class FDSNSiteChoice(StringChoice):
39 choices = [key.upper() for key in fdsn.g_site_abbr.keys()]
42class StationSelection(Object):
43 pass
46class FDSNStationSelection(StationSelection):
47 site = String.T()
48 tmin = Timestamp.T()
49 tmax = Timestamp.T()
51 def get_stations(self):
52 return fdsn.station(
53 site=self.site,
54 format='text',
55 level='channel',
56 startbefore=self.tmin,
57 endafter=self.tmax
58 ).get_pyrocko_stations()
61class FileStationSelection(StationSelection):
62 paths = List.T(String.T())
64 def get_stations(self):
65 from pyrocko.io import stationxml
67 stations = []
68 for path in self.paths:
69 if path.split('.')[-1].lower() in ['xml']:
70 stxml = stationxml.load_xml(filename=path)
71 stations.extend(stxml.get_pyrocko_stations())
73 else:
74 stations.extend(model.load_stations(path))
76 return stations
79class StationsState(ElementState):
80 visible = Bool.T(default=True)
81 size = Float.T(default=5.0)
82 station_selection = StationSelection.T(optional=True)
84 @classmethod
85 def get_name(cls):
86 return 'Stations'
88 def create(self):
89 element = StationsElement()
90 return element
93class StationsElement(Element):
95 def __init__(self):
96 Element.__init__(self)
97 self._parent = None
98 self._pipe = None
99 self._state = None
100 self._controls = None
101 self._points = num.array([])
103 def bind_state(self, state):
104 Element.bind_state(self, state)
105 self.talkie_connect(
106 state,
107 ['visible', 'size', 'station_selection'],
108 self.update)
110 self._current_selection = None
112 def get_name(self):
113 return 'Stations'
115 def set_parent(self, parent):
116 self._parent = parent
117 self._parent.add_panel(
118 self.get_title_label(),
119 self._get_controls(),
120 visible=True,
121 title_controls=[
122 self.get_title_control_remove(),
123 self.get_title_control_visible()])
124 self.update()
126 def unset_parent(self):
127 self.unbind_state()
128 if self._parent:
129 if self._pipe:
130 self._parent.remove_actor(self._pipe.actor)
131 self._pipe = None
133 if self._controls:
134 self._parent.remove_panel(self._controls)
135 self._controls = None
137 self._parent.update_view()
138 self._parent = None
140 def update(self, *args):
141 state = self._state
142 if self._pipe and \
143 self._current_selection is not state.station_selection:
145 self._parent.remove_actor(self._pipe.actor)
146 self._pipe = None
148 if self._pipe and not state.visible:
149 self._parent.remove_actor(self._pipe.actor)
150 self._pipe.set_size(state.size)
152 if state.visible:
153 if self._current_selection is not state.station_selection:
154 stations = state.station_selection.get_stations()
155 points = stations_to_points(stations)
156 self._pipe = ScatterPipe(points)
157 self._parent.add_actor(self._pipe.actor)
158 elif self._pipe:
159 self._parent.add_actor(self._pipe.actor)
161 if self._pipe:
162 self._pipe.set_size(state.size)
164 self._parent.update_view()
165 self._current_selection = state.station_selection
167 def open_file_load_dialog(self):
168 caption = 'Select one or more files to open'
170 fns, _ = qw.QFileDialog.getOpenFileNames(
171 self._parent, caption, options=common.qfiledialog_options)
173 self._state.station_selection = FileStationSelection(
174 paths=[str(fn) for fn in fns])
176 def open_fdsn_load_dialog(self):
177 dialog = qw.QDialog(self._parent)
178 dialog.setWindowTitle('Get stations from FDSN web service')
180 layout = qw.QHBoxLayout(dialog)
182 layout.addWidget(qw.QLabel('Site'))
184 sites = [key.upper() for key in fdsn.g_site_abbr.keys()]
186 cb = qw.QComboBox()
187 for i, s in enumerate(sites):
188 cb.insertItem(i, s)
190 layout.addWidget(cb)
192 pb = qw.QPushButton('Cancel')
193 pb.clicked.connect(dialog.reject)
194 layout.addWidget(pb)
196 pb = qw.QPushButton('Ok')
197 pb.clicked.connect(dialog.accept)
198 layout.addWidget(pb)
200 dialog.exec_()
202 site = str(cb.currentText()).lower()
204 vstate = self._parent.state
206 if dialog.result() == qw.QDialog.Accepted:
207 self._state.station_selection = FDSNStationSelection(
208 site=site,
209 tmin=vstate.tmin,
210 tmax=vstate.tmax)
212 def _get_controls(self):
213 if not self._controls:
214 from ..state import state_bind_slider
216 frame = qw.QFrame()
217 layout = qw.QGridLayout()
218 frame.setLayout(layout)
220 layout.addWidget(qw.QLabel('Size'), 0, 0)
222 slider = qw.QSlider(qc.Qt.Horizontal)
223 slider.setSizePolicy(
224 qw.QSizePolicy(
225 qw.QSizePolicy.Expanding, qw.QSizePolicy.Fixed))
226 slider.setMinimum(0)
227 slider.setMaximum(10)
228 slider.setSingleStep(1)
229 slider.setPageStep(1)
230 layout.addWidget(slider, 0, 1)
231 state_bind_slider(self, self._state, 'size', slider)
233 lab = qw.QLabel('Load from:')
234 pb_file = qw.QPushButton('File')
235 pb_fdsn = qw.QPushButton('FDSN')
237 layout.addWidget(lab, 1, 0)
238 layout.addWidget(pb_file, 1, 1)
239 layout.addWidget(pb_fdsn, 1, 2)
241 pb_file.clicked.connect(self.open_file_load_dialog)
242 pb_fdsn.clicked.connect(self.open_fdsn_load_dialog)
244 layout.addWidget(qw.QFrame(), 2, 0, 1, 3)
246 self._controls = frame
248 return self._controls
251__all__ = [
252 'StationsElement',
253 'StationsState',
254]