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