1# http://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

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

5 

6import os 

7import numpy as num 

8 

9from pyrocko import util, trace 

10from .io_common import FileLoadError 

11 

12 

13class KanError(Exception): 

14 pass 

15 

16 

17class KanFile: 

18 

19 nbytes_header = 512 

20 

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

22 if args: 

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

24 else: 

25 self.clear() 

26 

27 def clear(self): 

28 ''' 

29 Empty file record. 

30 ''' 

31 

32 # set the required attributes 

33 self.delta = 1.0 

34 self.npts = 0 

35 self.b = 0.0 

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

37 

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

39 ''' 

40 Read SAC file. 

41 

42 filename -- Name of KAN file. 

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

44 ''' 

45 nbh = KanFile.nbytes_header 

46 

47 # read in all data 

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

49 if load_data: 

50 filedata = f.read() 

51 else: 

52 filedata = f.read(nbh) 

53 

54 if len(filedata) < nbh: 

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

56 

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

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

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

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

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

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

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

64 

65 assert header_records == 1 

66 assert leven == 1 

67 assert datatype == 2 

68 assert offset == 0.0 

69 

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

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

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

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

74 + microseconds/1.0e6 

75 

76 stationname = os.path.basename(filename) 

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

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

79 

80 self.npts = npts 

81 self.delta = 1.0/rate 

82 self.kstnm = stationname 

83 self.ref_time = ref_time 

84 

85 if load_data: 

86 if byte_sex == 'little': 

87 dtype = '<i4' 

88 else: 

89 dtype = '>i4' 

90 

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

92 

93 assert self.data.size == self.npts 

94 else: 

95 self.data = None 

96 

97 def to_trace(self): 

98 return trace.Trace( 

99 '', self.kstnm, '', '', 

100 self.ref_time, 

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

102 self.delta, 

103 self.data) 

104 

105 

106def iload(filename, load_data): 

107 try: 

108 kanf = KanFile(filename, load_data=load_data) 

109 tr = kanf.to_trace() 

110 yield tr 

111 

112 except (OSError, KanError) as e: 

113 raise FileLoadError(e)