1# http://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

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

5from __future__ import division, absolute_import 

6 

7import os 

8import numpy as num 

9 

10from pyrocko import util, trace 

11from .io_common import FileLoadError 

12 

13 

14class KanError(Exception): 

15 pass 

16 

17 

18class KanFile: 

19 

20 nbytes_header = 512 

21 

22 def __init__(self, *args, **kwargs): 

23 if args: 

24 self.read(*args, **kwargs) 

25 else: 

26 self.clear() 

27 

28 def clear(self): 

29 ''' 

30 Empty file record. 

31 ''' 

32 

33 # set the required attributes 

34 self.delta = 1.0 

35 self.npts = 0 

36 self.b = 0.0 

37 self.data = [num.arange(0, dtype=num.int32)] 

38 

39 def read(self, filename, load_data=True): 

40 ''' 

41 Read SAC file. 

42 

43 filename -- Name of KAN file. 

44 load_data -- If True, the data is read, otherwise only read headers. 

45 ''' 

46 nbh = KanFile.nbytes_header 

47 

48 # read in all data 

49 with open(filename, 'rb') as f: 

50 if load_data: 

51 filedata = f.read() 

52 else: 

53 filedata = f.read(nbh) 

54 

55 if len(filedata) < nbh: 

56 raise KanError('File too short to be a KAN file.') 

57 

58 header_records = int(filedata[0:8]) 

59 npts = int(filedata[8:20]) 

60 leven = int(filedata[20:28]) 

61 datatype = int(filedata[28:36]) 

62 rate = float(filedata[36:50]) 

63 offset = float(filedata[50:64]) 

64 byte_sex = ('little', 'big')[int(filedata[382:390])] 

65 

66 assert header_records == 1 

67 assert leven == 1 

68 assert datatype == 2 

69 assert offset == 0.0 

70 

71 date = str(filedata[393:405].decode('ascii')).strip() 

72 tim = str(filedata[405:415].decode('ascii')).strip() 

73 microseconds = int(filedata[415:423]) 

74 ref_time = util.to_time_float(util.ctimegm('%s %s' % (date, tim))) \ 

75 + microseconds/1.0e6 

76 

77 stationname = os.path.basename(filename) 

78 stationname = stationname.replace('.kan', '') 

79 stationname = stationname.replace('.KAN', '') 

80 

81 self.npts = npts 

82 self.delta = 1.0/rate 

83 self.kstnm = stationname 

84 self.ref_time = ref_time 

85 

86 if load_data: 

87 if byte_sex == 'little': 

88 dtype = '<i4' 

89 else: 

90 dtype = '>i4' 

91 

92 self.data = num.frombuffer(filedata[nbh:], dtype=dtype) 

93 

94 assert self.data.size == self.npts 

95 else: 

96 self.data = None 

97 

98 def to_trace(self): 

99 return trace.Trace( 

100 '', self.kstnm, '', '', 

101 self.ref_time, 

102 self.ref_time+self.delta*(self.npts-1), 

103 self.delta, 

104 self.data) 

105 

106 

107def iload(filename, load_data): 

108 try: 

109 kanf = KanFile(filename, load_data=load_data) 

110 tr = kanf.to_trace() 

111 yield tr 

112 

113 except (OSError, KanError) as e: 

114 raise FileLoadError(e)