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 nut = model.make_channel_nut( 

90 file_segment=0, 

91 file_element=inut, 

92 codes=model.CodesNSLCE(net, sta, loc, cha, ''), 

93 tmin=tmin, 

94 tmax=tmax, 

95 deltat=deltat) 

96 

97 if 'channel' in content: 

98 nut.content = model.Channel( 

99 lat=channel.latitude.value, 

100 lon=channel.longitude.value, 

101 elevation=value_or_none(channel.elevation), 

102 depth=value_or_none(channel.depth), 

103 azimuth=value_or_none(channel.azimuth), 

104 dip=value_or_none(channel.dip), 

105 **nut.channel_kwargs) 

106 

107 channel_copy = copy.copy(channel) 

108 channel_copy.response = None 

109 nut.raw_content['stationxml'] = channel_copy 

110 

111 yield nut 

112 inut += 1 

113 

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

115 

116 if channel.response: 

117 

118 nut = model.make_response_nut( 

119 file_segment=0, 

120 file_element=inut, 

121 codes=model.CodesNSLCE(net, sta, loc, cha, ''), 

122 tmin=tmin, 

123 tmax=tmax, 

124 deltat=deltat) 

125 

126 try: 

127 resp = channel.response.get_squirrel_response( 

128 context, **nut.response_kwargs) 

129 

130 if 'response' in content: 

131 nut.content = resp 

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

133 

134 yield nut 

135 inut += 1 

136 

137 except stationxml.StationXMLError as e: 

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