1# http://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

4# ---|P------/S----------~Lg---------- 

5 

6import logging 

7import time 

8import copy 

9from pyrocko.io.io_common import get_stats, touch # noqa 

10from ... import model 

11 

12 

13logger = logging.getLogger('psq.io.stationxml') 

14 

15 

16Y = 60*60*24*365 

17 

18 

19def provided_formats(): 

20 return ['stationxml'] 

21 

22 

23def detect(first512): 

24 if first512.find(b'<FDSNStationXML') != -1: 

25 return 'stationxml' 

26 

27 return None 

28 

29 

30def iload(format, file_path, segment, content): 

31 assert format == 'stationxml' 

32 

33 far_future = time.time() + 20*Y 

34 

35 from pyrocko.io import stationxml 

36 value_or_none = stationxml.value_or_none 

37 

38 sx = stationxml.load_xml(filename=file_path) 

39 

40 inut = 0 

41 

42 for network in sx.network_list: 

43 for station in network.station_list: 

44 net = network.code 

45 sta = station.code 

46 

47 tmin = station.start_date 

48 tmax = station.end_date 

49 if tmax is not None and tmax > far_future: 

50 tmax = None 

51 

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) 

58 

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) 

65 

66 station_copy = copy.copy(station) 

67 station_copy.channel_list = [] 

68 

69 station_nut.raw_content['stationxml'] = station_copy 

70 

71 yield station_nut 

72 inut += 1 

73 

74 for channel in station.channel_list: 

75 cha = channel.code 

76 loc = channel.location_code.strip() 

77 

78 tmin = channel.start_date 

79 tmax = channel.end_date 

80 if tmax is not None and tmax > far_future: 

81 tmax = None 

82 

83 deltat = None 

84 if channel.sample_rate is not None \ 

85 and channel.sample_rate.value != 0.0: 

86 

87 deltat = 1.0 / channel.sample_rate.value 

88 

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 

93 

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) 

101 

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) 

111 

112 channel_copy = copy.copy(channel) 

113 channel_copy.response = None 

114 nut.raw_content['stationxml'] = channel_copy 

115 

116 yield nut 

117 inut += 1 

118 

119 context = '%s.%s.%s.%s' % (net, sta, loc, cha) 

120 

121 if channel.response: 

122 

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) 

130 

131 try: 

132 resp = channel.response.get_squirrel_response( 

133 context, **nut.response_kwargs) 

134 

135 if 'response' in content: 

136 nut.content = resp 

137 nut.raw_content['stationxml'] = channel.response 

138 

139 yield nut 

140 inut += 1 

141 

142 except stationxml.StationXMLError as e: 

143 logger.debug('Bad instrument response: %s' % str(e))