Coverage for /usr/local/lib/python3.11/dist-packages/pyrocko/io/eventdata.py: 37%
114 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# http://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6'''
7Event data access interface (*deprecated*).
8'''
10from pyrocko import model, response
12import logging
13import copy
14import pickle
16logger = logging.getLogger('pyrocko.io.eventdata')
19class NoRestitution(Exception):
20 pass
23class FileNotFound(Exception):
25 def __init__(self, s):
26 self.s = s
28 def __str__(self):
29 return 'File not found: %s' % self.s
32class Problems(object):
33 def __init__(self):
34 self._problems = {}
36 def add(self, kind, nslct):
37 if kind not in self._problems:
38 self._problems[kind] = set()
39 problem = self._problems[kind]
40 problem.add(nslct)
42 def dump(self, fn):
43 f = open(fn, 'wb')
44 pickle.dump(self._problems, f)
45 f.close()
47 def load(self, fn):
48 f = open(fn, 'rb')
49 self._problems = pickle.load(f)
50 f.close()
52 def mapped(self, mapping=lambda nslct: nslct[:3]):
53 p = {}
54 for kind, problem in self._problems.items():
55 nsl = set()
56 for nslct in problem:
57 nsl.add(mapping(nslct))
58 p[kind] = nsl
60 return p
63class EventDataAccess(object):
64 '''
65 Abstract base class for event data access (see rdseed.py).
66 '''
68 def __init__(self, events=None, stations=None, datapile=None):
70 self._pile = datapile
71 self._events = events
73 if stations is None:
74 self._stations = None
75 else:
76 self._stations = {}
77 for station in stations:
78 self._stations[station.nsl()] = station
80 self._problems = Problems()
82 def get_pile(self):
83 return self._pile
85 def get_pyrocko_events(self):
86 '''
87 Extract :py:class:`~pyrocko.model.event.Event` instances from the
88 volume.
89 '''
91 if not self._events:
92 self._events = self._get_events_from_file()
93 return self._events
95 def get_pyrocko_station(self, tr, relative_event=None):
96 '''
97 Get station information for a given trace.
99 :param tr: :py:class:`~pyrocko.trace.Trace` instance
101 :returns: :py:class:`~pyrocko.model.station.Station` objects.
102 '''
104 self._update_stations()
105 s = copy.deepcopy(self._stations[tr.nslc_id[:3]])
106 if relative_event is not None:
107 s.set_event_relative_data(relative_event)
108 return s
110 def get_pyrocko_channel(self, tr):
111 '''
112 Get channel information for a given trace.
114 :param tr: :py:class:`~pyrocko.trace.Trace` instance
116 :returns: :py:class:`~pyrocko.model.station.Channel` objects.
117 '''
118 sta = self.get_station(tr)
119 return sta.get_channel(tr.channel)
121 def get_pyrocko_stations(self):
122 '''
123 Exctract a list of :py:class:`~pyrocko.model.station.Station`
124 instances.
125 '''
126 return list(self._get_stations().values())
128 def _get_stations(self, relative_event=None):
129 self._update_stations()
130 stations = copy.deepcopy(self._stations)
131 if relative_event is not None:
132 for s in stations.values():
133 s.set_event_relative_data(relative_event)
135 return stations
137 def _update_stations(self):
138 if not self._stations:
139 self._stations = {}
140 for station in self._get_stations_from_file():
141 self._stations[station.nsl()] = station
142 self._insert_channel_descriptions(self._stations)
144 def _insert_channel_descriptions(self, stations):
145 pile = self.get_pile()
146 nslc_ids = pile.gather_keys(
147 lambda tr: (tr.network, tr.station, tr.location, tr.channel))
149 for nslc in nslc_ids:
150 if nslc[:3] not in stations:
151 logger.warning(
152 'No station description for trace %s.%s.%s.%s' % nslc)
153 continue
155 sta = stations[nslc[:3]]
156 try:
157 sta.add_channel(self._get_channel_description_from_file(nslc))
158 except FileNotFound:
159 logger.warning(
160 'No channel description for trace %s.%s.%s.%s' % nslc)
162 def _get_channel_description_from_file(self, nslc):
163 return model.Channel(nslc[3], None, None, 1.)
165 def iter_traces(self, group_selector=None, trace_selector=None):
167 for traces in self.get_pile().chopper_grouped(
168 gather=lambda tr: (tr.network, tr.station, tr.location),
169 group_selector=group_selector,
170 trace_selector=trace_selector):
172 yield traces
174 def problems(self):
175 return self._problems
177 def _redundant_channel_weeder(self, redundant_channel_priorities, nslcs):
179 if redundant_channel_priorities is None:
180 return []
182 # n=network,s=station,l=location,c=channel
183 # channels by station
184 by_nsl = {}
185 for nslc in nslcs:
186 nsl = nslc[:3]
187 if nsl not in by_nsl:
188 by_nsl[nsl] = []
190 by_nsl[nsl].append(nslc)
192 # figure out what items to remove
193 to_delete = []
194 for ((h1, h2), (l1, l2)) in redundant_channel_priorities:
195 for nsl, nslcs in by_nsl.items():
196 channels = [nslc[3] for nslc in nslcs]
197 if h1 in channels and \
198 h2 in channels and \
199 l1 in channels and \
200 l2 in channels:
202 to_delete.append(nslc[:3] + (l1,))
203 to_delete.append(nslc[:3] + (l2,))
205 return to_delete
207 def get_restitution(self, tr, allowed_methods):
208 if 'integration' in allowed_methods:
209 response.IntegrationResponse()
210 else:
211 raise Exception('only "integration" restitution method is allowed')