1# http://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

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

5 

6from __future__ import absolute_import, print_function 

7 

8import logging 

9import time 

10import copy 

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

12from ... import model 

13 

14 

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

16 

17 

18Y = 60*60*24*365 

19 

20 

21def provided_formats(): 

22 return ['stationxml'] 

23 

24 

25def detect(first512): 

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

27 return 'stationxml' 

28 

29 return None 

30 

31 

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

33 assert format == 'stationxml' 

34 

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

36 

37 from pyrocko.io import stationxml 

38 value_or_none = stationxml.value_or_none 

39 

40 sx = stationxml.load_xml(filename=file_path) 

41 

42 inut = 0 

43 

44 for network in sx.network_list: 

45 for station in network.station_list: 

46 net = network.code 

47 sta = station.code 

48 

49 tmin = station.start_date 

50 tmax = station.end_date 

51 if tmax is not None and tmax > far_future: 

52 tmax = None 

53 

54 station_nut = model.make_station_nut( 

55 file_segment=0, 

56 file_element=inut, 

57 codes=model.CodesNSL(net, sta, '*'), 

58 tmin=tmin, 

59 tmax=tmax) 

60 

61 if 'station' in content: 

62 station_nut.content = model.Station( 

63 lat=station.latitude.value, 

64 lon=station.longitude.value, 

65 elevation=value_or_none(station.elevation), 

66 **station_nut.station_kwargs) 

67 

68 station_copy = copy.copy(station) 

69 station_copy.channel_list = [] 

70 

71 station_nut.raw_content['stationxml'] = station_copy 

72 

73 yield station_nut 

74 inut += 1 

75 

76 for channel in station.channel_list: 

77 cha = channel.code 

78 loc = channel.location_code.strip() 

79 

80 tmin = channel.start_date 

81 tmax = channel.end_date 

82 if tmax is not None and tmax > far_future: 

83 tmax = None 

84 

85 deltat = None 

86 if channel.sample_rate is not None \ 

87 and channel.sample_rate.value != 0.0: 

88 

89 deltat = 1.0 / channel.sample_rate.value 

90 

91 nut = model.make_channel_nut( 

92 file_segment=0, 

93 file_element=inut, 

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

95 tmin=tmin, 

96 tmax=tmax, 

97 deltat=deltat) 

98 

99 if 'channel' in content: 

100 nut.content = model.Channel( 

101 lat=channel.latitude.value, 

102 lon=channel.longitude.value, 

103 elevation=value_or_none(channel.elevation), 

104 depth=value_or_none(channel.depth), 

105 azimuth=value_or_none(channel.azimuth), 

106 dip=value_or_none(channel.dip), 

107 **nut.channel_kwargs) 

108 

109 channel_copy = copy.copy(channel) 

110 channel_copy.response = None 

111 nut.raw_content['stationxml'] = channel_copy 

112 

113 yield nut 

114 inut += 1 

115 

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

117 

118 if channel.response: 

119 

120 nut = model.make_response_nut( 

121 file_segment=0, 

122 file_element=inut, 

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

124 tmin=tmin, 

125 tmax=tmax, 

126 deltat=deltat) 

127 

128 try: 

129 resp = channel.response.get_squirrel_response( 

130 context, **nut.response_kwargs) 

131 

132 if 'response' in content: 

133 nut.content = resp 

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

135 

136 yield nut 

137 inut += 1 

138 

139 except stationxml.StationXMLError as e: 

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