1# http://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

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

5 

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

7from pyrocko import trace 

8from ... import model 

9 

10 

11km = 1000. 

12 

13 

14def provided_formats(): 

15 return ['sac'] 

16 

17 

18def detect(first512): 

19 from pyrocko.io import sac 

20 

21 if sac.detect(first512): 

22 return 'sac' 

23 else: 

24 return None 

25 

26 

27def agg(*ds): 

28 out = {} 

29 for d in ds: 

30 out.update(d) 

31 

32 return out 

33 

34 

35def nonetoempty(x): 

36 if x is None: 

37 return x 

38 else: 

39 return x.strip() 

40 

41 

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

43 assert format == 'sac' 

44 

45 from pyrocko.io import sac 

46 

47 load_data = 'waveform' in content 

48 

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

50 

51 codes = model.CodesNSLCE( 

52 nonetoempty(s.knetwk), 

53 nonetoempty(s.kstnm), 

54 nonetoempty(s.khole), 

55 nonetoempty(s.kcmpnm)) 

56 

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

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

59 

60 tspan = dict( 

61 tmin=tmin, 

62 tmax=tmax, 

63 deltat=s.delta) 

64 

65 inut = 0 

66 nut = model.make_waveform_nut( 

67 file_segment=0, 

68 file_element=inut, 

69 codes=codes, 

70 **tspan) 

71 

72 if 'waveform' in content: 

73 nut.content = trace.Trace( 

74 ydata=s.data[0], 

75 **nut.waveform_kwargs) 

76 

77 yield nut 

78 inut += 1 

79 

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

81 position = dict( 

82 lat=s.stla, 

83 lon=s.stlo, 

84 elevation=s.stel, 

85 depth=s.stdp) 

86 

87 nut = model.make_station_nut( 

88 file_segment=0, 

89 file_element=inut, 

90 codes=model.CodesNSL(*codes.nsl), 

91 **tspan) 

92 

93 if 'station' in content: 

94 nut.content = model.Station( 

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

96 

97 yield nut 

98 inut += 1 

99 

100 dip = None 

101 if s.cmpinc is not None: 

102 dip = s.cmpinc - 90. 

103 

104 nut = model.make_channel_nut( 

105 file_segment=0, 

106 file_element=inut, 

107 codes=codes, 

108 **tspan) 

109 

110 if 'channel' in content: 

111 nut.content = model.Channel( 

112 azimuth=s.cmpaz, 

113 dip=dip, 

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

115 

116 yield nut 

117 inut += 1 

118 

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

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

121 depth = None 

122 if s.evdp is not None: 

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

124 

125 nut = model.make_event_nut( 

126 codes=model.CodesX(''), 

127 # name=nonetoempty(s.kevnm), 

128 file_segment=0, 

129 file_element=inut, 

130 tmin=etime, 

131 tmax=etime) 

132 

133 if 'event' in content: 

134 nut.content = model.Event( 

135 lat=s.evla, 

136 lon=s.evlo, 

137 depth=depth, 

138 magnitude=s.mag, 

139 **nut.event_kwargs) 

140 

141 yield nut 

142 inut += 1