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 

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

9from pyrocko import trace 

10from ... import model 

11 

12 

13km = 1000. 

14 

15 

16def provided_formats(): 

17 return ['sac'] 

18 

19 

20def detect(first512): 

21 from pyrocko.io import sac 

22 

23 if sac.detect(first512): 

24 return 'sac' 

25 else: 

26 return None 

27 

28 

29def agg(*ds): 

30 out = {} 

31 for d in ds: 

32 out.update(d) 

33 

34 return out 

35 

36 

37def nonetoempty(x): 

38 if x is None: 

39 return x 

40 else: 

41 return x.strip() 

42 

43 

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

45 assert format == 'sac' 

46 

47 from pyrocko.io import sac 

48 

49 load_data = 'waveform' in content 

50 

51 s = sac.SacFile(file_path, load_data=load_data) 

52 

53 codes = dict( 

54 agency='', 

55 network=nonetoempty(s.knetwk), 

56 station=nonetoempty(s.kstnm), 

57 location=nonetoempty(s.khole), 

58 channel=nonetoempty(s.kcmpnm)) 

59 

60 tmin = s.get_ref_time() + s.b 

61 tmax = tmin + s.delta * s.npts 

62 

63 tspan = dict( 

64 tmin=tmin, 

65 tmax=tmax, 

66 deltat=s.delta) 

67 

68 inut = 0 

69 nut = model.make_waveform_nut( 

70 file_segment=0, 

71 file_element=inut, 

72 **agg(codes, tspan)) 

73 

74 if 'waveform' in content: 

75 nut.content = trace.Trace( 

76 ydata=s.data[0], 

77 **nut.waveform_kwargs) 

78 

79 yield nut 

80 inut += 1 

81 

82 if None not in (s.stla, s.stlo): 

83 position = dict( 

84 lat=s.stla, 

85 lon=s.stlo, 

86 elevation=s.stel, 

87 depth=s.stdp) 

88 

89 codes_without_channel = codes.copy() 

90 del codes_without_channel['channel'] 

91 nut = model.make_station_nut( 

92 file_segment=0, 

93 file_element=inut, 

94 **agg(codes_without_channel, tspan)) 

95 

96 if 'station' in content: 

97 nut.content = model.Station( 

98 **agg(position, nut.station_kwargs)) 

99 

100 yield nut 

101 inut += 1 

102 

103 dip = None 

104 if s.cmpinc is not None: 

105 dip = s.cmpinc - 90. 

106 

107 nut = model.make_channel_nut( 

108 file_segment=0, 

109 file_element=inut, 

110 **agg(codes, tspan)) 

111 

112 if 'channel' in content: 

113 nut.content = model.Channel( 

114 azimuth=s.cmpaz, 

115 dip=dip, 

116 **agg(position, nut.channel_kwargs)) 

117 

118 yield nut 

119 inut += 1 

120 

121 if None not in (s.evla, s.evlo, s.o): 

122 etime = s.get_ref_time() + s.o 

123 depth = None 

124 if s.evdp is not None: 

125 depth = s.evdp # * km # unclear specs 

126 

127 nut = model.make_event_nut( 

128 name=nonetoempty(s.kevnm), 

129 file_segment=0, 

130 file_element=inut, 

131 tmin=etime, 

132 tmax=etime) 

133 

134 if 'event' in content: 

135 nut.content = model.Event( 

136 lat=s.evla, 

137 lon=s.evlo, 

138 depth=depth, 

139 magnitude=s.mag, 

140 **nut.event_kwargs) 

141 

142 yield nut 

143 inut += 1