1# http://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6import os
7import numpy as num
9from pyrocko import util, trace
10from .io_common import FileLoadError
13class KanError(Exception):
14 pass
17class KanFile:
19 nbytes_header = 512
21 def __init__(self, *args, **kwargs):
22 if args:
23 self.read(*args, **kwargs)
24 else:
25 self.clear()
27 def clear(self):
28 '''
29 Empty file record.
30 '''
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)]
38 def read(self, filename, load_data=True):
39 '''
40 Read SAC file.
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
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)
54 if len(filedata) < nbh:
55 raise KanError('File too short to be a KAN file.')
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])]
65 assert header_records == 1
66 assert leven == 1
67 assert datatype == 2
68 assert offset == 0.0
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
76 stationname = os.path.basename(filename)
77 stationname = stationname.replace('.kan', '')
78 stationname = stationname.replace('.KAN', '')
80 self.npts = npts
81 self.delta = 1.0/rate
82 self.kstnm = stationname
83 self.ref_time = ref_time
85 if load_data:
86 if byte_sex == 'little':
87 dtype = '<i4'
88 else:
89 dtype = '>i4'
91 self.data = num.frombuffer(filedata[nbh:], dtype=dtype)
93 assert self.data.size == self.npts
94 else:
95 self.data = None
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)
106def iload(filename, load_data):
107 try:
108 kanf = KanFile(filename, load_data=load_data)
109 tr = kanf.to_trace()
110 yield tr
112 except (OSError, KanError) as e:
113 raise FileLoadError(e)