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

1"""Load EODs from Hopkins files. 

2 

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. 

6 

7## Functions 

8 

9- `load_hopkins()`: load a Hopkins file containing a few EOD pulses. 

10- `analyse_hopkins()`: analyze the content of Hopkins files. 

11 

12""" 

13 

14import sys 

15import numpy as np 

16import matplotlib.pyplot as plt 

17from scipy.io import loadmat 

18from audioio import print_metadata 

19 

20 

21def load_hopkins(file_path): 

22 """ Load a Hopkins file containing a few EOD pulses. 

23 

24 Parameters 

25 ---------- 

26 file_path: str 

27 The mat file with the data. 

28 

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. 

36 

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 

89 

90 

91def analyse_hopkins(pathes): 

92 """ Analyze the content of Hopkins files. 

93 

94 Prints out some statistics about the field names and types. 

95 

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 

116 

117 # each file contains several "wave" and "time" arrays for plotting the EODs. 

118 # within a file they might differ in size! 

119 

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() 

125 

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 

133 

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'> 

143 

144 

145if __name__ == '__main__': 

146 

147 analyse_hopkins(sys.argv[1:]) 

148 

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()