1# http://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6import logging
7import time
8import copy
9from pyrocko.io.io_common import get_stats, touch # noqa
10from ... import model
13logger = logging.getLogger('psq.io.stationxml')
16Y = 60*60*24*365
19def provided_formats():
20 return ['stationxml']
23def detect(first512):
24 if first512.find(b'<FDSNStationXML') != -1:
25 return 'stationxml'
27 return None
30def iload(format, file_path, segment, content):
31 assert format == 'stationxml'
33 far_future = time.time() + 20*Y
35 from pyrocko.io import stationxml
36 value_or_none = stationxml.value_or_none
38 sx = stationxml.load_xml(filename=file_path)
40 inut = 0
42 for network in sx.network_list:
43 for station in network.station_list:
44 net = network.code
45 sta = station.code
47 tmin = station.start_date
48 tmax = station.end_date
49 if tmax is not None and tmax > far_future:
50 tmax = None
52 station_nut = model.make_station_nut(
53 file_segment=0,
54 file_element=inut,
55 codes=model.CodesNSL(net, sta, '*'),
56 tmin=tmin,
57 tmax=tmax)
59 if 'station' in content:
60 station_nut.content = model.Station(
61 lat=station.latitude.value,
62 lon=station.longitude.value,
63 elevation=value_or_none(station.elevation),
64 **station_nut.station_kwargs)
66 station_copy = copy.copy(station)
67 station_copy.channel_list = []
69 station_nut.raw_content['stationxml'] = station_copy
71 yield station_nut
72 inut += 1
74 for channel in station.channel_list:
75 cha = channel.code
76 loc = channel.location_code.strip()
78 tmin = channel.start_date
79 tmax = channel.end_date
80 if tmax is not None and tmax > far_future:
81 tmax = None
83 deltat = None
84 if channel.sample_rate is not None \
85 and channel.sample_rate.value != 0.0:
87 deltat = 1.0 / channel.sample_rate.value
89 if deltat is None and channel.response:
90 out_rate_resp = channel.response.output_sample_rate
91 if out_rate_resp:
92 deltat = 1.0 / out_rate_resp
94 nut = model.make_channel_nut(
95 file_segment=0,
96 file_element=inut,
97 codes=model.CodesNSLCE(net, sta, loc, cha, ''),
98 tmin=tmin,
99 tmax=tmax,
100 deltat=deltat)
102 if 'channel' in content:
103 nut.content = model.Channel(
104 lat=channel.latitude.value,
105 lon=channel.longitude.value,
106 elevation=value_or_none(channel.elevation),
107 depth=value_or_none(channel.depth),
108 azimuth=value_or_none(channel.azimuth),
109 dip=value_or_none(channel.dip),
110 **nut.channel_kwargs)
112 channel_copy = copy.copy(channel)
113 channel_copy.response = None
114 nut.raw_content['stationxml'] = channel_copy
116 yield nut
117 inut += 1
119 context = '%s.%s.%s.%s' % (net, sta, loc, cha)
121 if channel.response:
123 nut = model.make_response_nut(
124 file_segment=0,
125 file_element=inut,
126 codes=model.CodesNSLCE(net, sta, loc, cha, ''),
127 tmin=tmin,
128 tmax=tmax,
129 deltat=deltat)
131 try:
132 resp = channel.response.get_squirrel_response(
133 context, **nut.response_kwargs)
135 if 'response' in content:
136 nut.content = resp
137 nut.raw_content['stationxml'] = channel.response
139 yield nut
140 inut += 1
142 except stationxml.StationXMLError as e:
143 logger.debug('Bad instrument response: %s' % str(e))