Coverage for C: \ Users \ peaco \ OneDrive \ Documents \ GitHub \ mth5 \ mth5 \ groups \ filter_groups \ fap_filter_group.py: 73%

60 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-01-10 00:01 -0800

1# -*- coding: utf-8 -*- 

2""" 

3Created on Wed Jun 9 08:55:16 2021 

4 

5:copyright: 

6 Jared Peacock (jpeacock@usgs.gov) 

7 

8:license: MIT 

9 

10""" 

11 

12# ============================================================================= 

13# Imports 

14# ============================================================================= 

15import numpy as np 

16from mt_metadata.timeseries.filters import FrequencyResponseTableFilter 

17 

18from mth5.groups.base import BaseGroup 

19 

20 

21# ============================================================================= 

22# fap Group 

23# ============================================================================= 

24class FAPGroup(BaseGroup): 

25 """ 

26 Container for fap type filters 

27 

28 """ 

29 

30 def __init__(self, group, **kwargs): 

31 super().__init__(group, **kwargs) 

32 

33 @property 

34 def filter_dict(self): 

35 """ 

36 

37 Dictionary of available fap filters 

38 

39 :return: DESCRIPTION 

40 :rtype: TYPE 

41 

42 """ 

43 f_dict = {} 

44 for key in self.hdf5_group.keys(): 

45 fap_group = self.hdf5_group[key] 

46 f_dict[key] = { 

47 "type": fap_group.attrs["type"], 

48 "hdf5_ref": fap_group.ref, 

49 } 

50 

51 return f_dict 

52 

53 def add_filter(self, name, frequency, amplitude, phase, fap_metadata): 

54 """ 

55 

56 create an HDF5 group/dataset from information given. 

57 

58 :param name: name of the filter 

59 :type name: string 

60 :param frequency: frequency array in samples per second 

61 :type frequency: list, np.ndarray 

62 :param amplitude: amplitude array in units of units out 

63 :type amplitude: list, np.ndarray 

64 :param phase: Phase in degrees 

65 :type phase: list, np.ndarray 

66 :param fap_metadata: other metadata for the filter see 

67 :class:`mt_metadata.timeseries.filters.FrequencyResponseTableFilter` \ 

68 for details on entries 

69 :type fap_metadata: dictionary 

70 :return: DESCRIPTION 

71 :rtype: TYPE 

72 

73 """ 

74 

75 # create a group for the filter by the name 

76 fap_filter_group = self.hdf5_group.create_group(name) 

77 

78 # create datasets for the poles and zeros 

79 fap_ds = fap_filter_group.create_dataset( 

80 "fap_table", 

81 frequency.shape, 

82 dtype=np.dtype( 

83 [("frequency", float), ("amplitude", float), ("phase", float)] 

84 ), 

85 **self.dataset_options, 

86 ) 

87 

88 fap_ds[:] = [(f, a, p) for f, a, p in zip(frequency, amplitude, phase)] 

89 

90 # fill in the metadata 

91 fap_filter_group.attrs.update(fap_metadata) 

92 

93 return fap_filter_group 

94 

95 def remove_filter(self): 

96 pass 

97 

98 def get_filter(self, name): 

99 """ 

100 Get a filter from the name 

101 

102 :param name: name of the filter 

103 :type name: string 

104 

105 :return: HDF5 group of the fap filter 

106 """ 

107 return self.hdf5_group[name] 

108 

109 def update_filter(self, fap_object): 

110 """ 

111 update values from fap object 

112 

113 :param fap_object: DESCRIPTION 

114 :type fap_object: TYPE 

115 :return: DESCRIPTION 

116 :rtype: TYPE 

117 

118 """ 

119 if fap_object.name in self.groups_list: 

120 self.hdf5_group.pop(fap_object.name) 

121 

122 self.from_object(fap_object) 

123 

124 def from_object(self, fap_object): 

125 """ 

126 make a filter from a :class:`mt_metadata.timeseries.filters.PoleZeroFilter` 

127 

128 :param fap_object: MT metadata PoleZeroFilter 

129 :type fap_object: :class:`mt_metadata.timeseries.filters.PoleZeroFilter` 

130 

131 """ 

132 

133 if not isinstance(fap_object, FrequencyResponseTableFilter): 

134 msg = ( 

135 f"Filter must be a FrequencyResponseTableFilter not {type(fap_object)}" 

136 ) 

137 self.logger.error(msg) 

138 raise TypeError(msg) 

139 

140 input_dict = fap_object.to_dict(single=True, required=False) 

141 input_dict.pop("frequencies") 

142 input_dict.pop("amplitudes") 

143 input_dict.pop("phases") 

144 for k, v in input_dict.items(): 

145 if v is None: 

146 input_dict[k] = str(v) 

147 

148 fap_group = self.add_filter( 

149 fap_object.name, 

150 fap_object.frequencies, 

151 fap_object.amplitudes, 

152 fap_object.phases, 

153 input_dict, 

154 ) 

155 return fap_group 

156 

157 def to_object(self, name): 

158 """ 

159 make a :class:`mt_metadata.timeseries.filters.pole_zeros_filter` object 

160 

161 :return: DESCRIPTION 

162 :rtype: TYPE 

163 

164 """ 

165 

166 fap_group = self.get_filter(name) 

167 

168 fap_obj = FrequencyResponseTableFilter(**fap_group.attrs) 

169 

170 try: 

171 fap_obj.frequencies = fap_group["fap_table"]["frequency"][:] 

172 except TypeError: 

173 self.logger.debug(f"fap filter {name} has no frequency") 

174 fap_obj.frequencies = [] 

175 

176 try: 

177 fap_obj.amplitudes = fap_group["fap_table"]["amplitude"][:] 

178 except TypeError: 

179 self.logger.debug(f"fap filter {name} has no amplitudes") 

180 fap_obj.amplitudes = [] 

181 

182 try: 

183 fap_obj.phases = fap_group["fap_table"]["phase"][:] 

184 except TypeError: 

185 self.logger.debug(f"fap filter {name} has no phases") 

186 fap_obj.phases = [] 

187 

188 return fap_obj