1# http://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6from __future__ import absolute_import, print_function
8import logging
9import time
10from pyrocko.io.io_common import get_stats, touch # noqa
11from ... import model
14logger = logging.getLogger('psq.io.stationxml')
17Y = 60*60*24*365
20def provided_formats():
21 return ['stationxml']
24def detect(first512):
25 if first512.find(b'<FDSNStationXML') != -1:
26 return 'stationxml'
28 return None
31def iload(format, file_path, segment, content):
32 assert format == 'stationxml'
34 far_future = time.time() + 20*Y
36 from pyrocko.io import stationxml
37 value_or_none = stationxml.value_or_none
39 sx = stationxml.load_xml(filename=file_path)
41 inut = 0
43 for network in sx.network_list:
44 for station in network.station_list:
45 net = network.code
46 sta = station.code
48 tmin = station.start_date
49 tmax = station.end_date
50 if tmax is not None and tmax > far_future:
51 tmax = None
53 station_nut = model.make_station_nut(
54 file_segment=0,
55 file_element=inut,
56 codes=model.CodesNSL(net, sta, '*'),
57 tmin=tmin,
58 tmax=tmax)
60 if 'station' in content:
61 station_nut.content = model.Station(
62 lat=station.latitude.value,
63 lon=station.longitude.value,
64 elevation=value_or_none(station.elevation),
65 **station_nut.station_kwargs)
67 yield station_nut
68 inut += 1
70 for channel in station.channel_list:
71 cha = channel.code
72 loc = channel.location_code.strip()
74 tmin = channel.start_date
75 tmax = channel.end_date
76 if tmax is not None and tmax > far_future:
77 tmax = None
79 deltat = None
80 if channel.sample_rate is not None \
81 and channel.sample_rate.value != 0.0:
83 deltat = 1.0 / channel.sample_rate.value
85 nut = model.make_channel_nut(
86 file_segment=0,
87 file_element=inut,
88 codes=model.CodesNSLCE(net, sta, loc, cha, ''),
89 tmin=tmin,
90 tmax=tmax,
91 deltat=deltat)
93 if 'channel' in content:
94 nut.content = model.Channel(
95 lat=channel.latitude.value,
96 lon=channel.longitude.value,
97 elevation=value_or_none(channel.elevation),
98 depth=value_or_none(channel.depth),
99 azimuth=value_or_none(channel.azimuth),
100 dip=value_or_none(channel.dip),
101 **nut.channel_kwargs)
103 yield nut
104 inut += 1
106 context = '%s.%s.%s.%s' % (net, sta, loc, cha)
108 if channel.response:
110 nut = model.make_response_nut(
111 file_segment=0,
112 file_element=inut,
113 codes=model.CodesNSLCE(net, sta, loc, cha, ''),
114 tmin=tmin,
115 tmax=tmax,
116 deltat=deltat)
118 try:
119 resp = channel.response.get_squirrel_response(
120 context, **nut.response_kwargs)
122 if 'response' in content:
123 nut.content = resp
125 yield nut
126 inut += 1
128 except stationxml.StationXMLError as e:
129 logger.debug('Bad instrument response: %s' % str(e))