Coverage for src/thunderfish/hopkinsloader.py: 0%
88 statements
« prev ^ index » next coverage.py v7.5.0, created at 2024-04-29 16:21 +0000
« prev ^ index » next coverage.py v7.5.0, created at 2024-04-29 16:21 +0000
1"""Load EODs from Hopkins files.
3Carl Hopkins and John Sullivan stored only a few cut-out EOD waveforms
4of Mormyrid EODs in a specific mat file. These recordings are
5available at the Macaulay library.
7## Functions
9- `load_hopkins()`: load a Hopkins file containing a few EOD pulses.
10- `analyse_hopkins()`: analyze the content of Hopkins files.
12"""
14import sys
15import numpy as np
16import matplotlib.pyplot as plt
17from scipy.io import loadmat
18from audioio import print_metadata
21def load_hopkins(file_path):
22 """ Load a Hopkins file containing a few EOD pulses.
24 Parameters
25 ----------
26 file_path: str
27 The mat file with the data.
29 Returns
30 -------
31 data: list of 2-D ndarrays
32 A list of single EOD pulses.
33 First column is time in seconds, second column EOD waveform.
34 md: nested dict
35 Metadata.
37 Raises
38 ------
39 FileNotFoundError
40 `file_path` does not exist.
41 ValueError
42 `file_path` is not a valid mat file.
43 """
44 x = loadmat(file_path, squeeze_me=True)
45 if not 'eod' in x or not hasattr(x['eod'], 'size'):
46 return [], {}
47 y = x['eod'].reshape(x['eod'].size)
48 if not 'wave' in y.dtype.names or not 'time' in y.dtype.names:
49 return [], {}
50 # assemble data:
51 data = []
52 for k in range(len(y['wave'])):
53 eod = np.zeros((len(y['wave'][k]), 2))
54 eod[:, 0] = y['time'][k]
55 eod[:, 1] = (y['wave'][k]).astype(float)
56 data.append(eod)
57 # assemble metadata:
58 md = {}
59 eod_md = []
60 for n in y.dtype.names:
61 t = type(y[n][0])
62 if not t is np.ndarray:
63 # some metadata may or may not differ between EODs:
64 for k in range(len(y[n])):
65 if y[n][k] and n != 'eodnum' and y[n][k] != y[n][0]:
66 while len(eod_md) < len(y[n]):
67 eod_md.append({})
68 for k in range(len(y[n])):
69 v = y[n][k]
70 if isinstance(v, str):
71 v = v.replace('Date:', '')
72 v = v.replace('Time:', '')
73 v = v.replace('Time', '')
74 v = v.strip()
75 eod_md[k][n] = v
76 break
77 else:
78 v = y[n][0]
79 if isinstance(v, str):
80 v = v.replace('Date:', '')
81 v = v.replace('Time:', '')
82 v = v.replace('Time', '')
83 v = v.replace(' T: ', 'T')
84 v = v.strip()
85 md[n] = v
86 for k in range(len(eod_md)):
87 md[f'EOD{k}'] = eod_md[k]
88 return data, md
91def analyse_hopkins(pathes):
92 """ Analyze the content of Hopkins files.
94 Prints out some statistics about the field names and types.
96 Parameters
97 ----------
98 pathes: list of str
99 Files to be analyzed.
100 """
101 keys = {}
102 types = {}
103 data_types = {}
104 for file_path in pathes:
105 x = loadmat(file_path, squeeze_me=True)
106 y = x['eod'].reshape(x['eod'].size)
107 for n in y.dtype.names:
108 c = keys.get(n, 0)
109 keys[n] = c + 1
110 t = type(y[n][0])
111 c = types.get(t, 0)
112 types[t] = c + 1
113 t = y['wave'][0].dtype
114 c = data_types.get(t, 0)
115 data_types[t] = c + 1
117 # each file contains several "wave" and "time" arrays for plotting the EODs.
118 # within a file they might differ in size!
120 # print all keys found in the data with their frequency:
121 print('keys:')
122 for k in keys:
123 print(f' {100*keys[k]/len(pathes):3.0f}%', k)
124 print()
126 # print all wave data types with their frequency:
127 print('data types:')
128 for t in data_types:
129 print(f' {data_types[t]:5d}', t)
130 print()
131 # 226 float64
132 # 57 int16
134 # print types of all fields with their frequency:
135 print('field types:')
136 for t in types:
137 print(f' {types[t]:5d}', t)
138 print()
139 # 2845 <class 'int'>
140 # 4002 <class 'numpy.ndarray'>
141 #14681 <class 'str'>
142 # 1478 <class 'float'>
145if __name__ == '__main__':
147 analyse_hopkins(sys.argv[1:])
149 for file_path in sys.argv[1:]:
150 print(file_path)
151 data, md = load_hopkins(file_path)
152 print_metadata(md, ' ')
153 fig, ax = plt.subplots()
154 ax.set_title(md.get('speciesIDweb', ''))
155 for k in range(len(data)):
156 ax.plot(1000*data[k][:, 0], data[k][:, 1])
157 ax.set_xlabel('Time [ms]')
158 plt.show()
159 print()