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

57 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# ============================================================================= 

15from mt_metadata.timeseries.filters import PoleZeroFilter 

16 

17from mth5.groups.base import BaseGroup 

18 

19 

20# ============================================================================= 

21# ZPK Group 

22# ============================================================================= 

23class ZPKGroup(BaseGroup): 

24 """ 

25 Container for ZPK type filters 

26 

27 """ 

28 

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

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

31 

32 @property 

33 def filter_dict(self): 

34 """ 

35 

36 Dictionary of available ZPK filters 

37 

38 :return: DESCRIPTION 

39 :rtype: TYPE 

40 

41 """ 

42 f_dict = {} 

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

44 zpk_group = self.hdf5_group[key] 

45 f_dict[key] = { 

46 "type": zpk_group.attrs["type"], 

47 "hdf5_ref": zpk_group.ref, 

48 } 

49 

50 return f_dict 

51 

52 def add_filter(self, name, poles, zeros, zpk_metadata): 

53 """ 

54 create an HDF5 group/dataset from information given. 

55 

56 :param name: Nane of the filter 

57 :type name: string 

58 :param poles: poles of the filter as complex numbers 

59 :type poles: np.ndarray(dtype=complex) 

60 :param zeros: zeros of the filter as complex numbers 

61 :type zeros: np.ndarray(dtype=comples) 

62 :param zpk_metadata: metadata dictionary see 

63 :class:`mt_metadata.timeseries.filters.PoleZeroFilter` for details on entries 

64 :type zpk_metadata: dictionary 

65 

66 """ 

67 # create a group for the filter by the name 

68 zpk_filter_group = self.hdf5_group.create_group(name) 

69 

70 # create datasets for the poles and zeros 

71 poles_ds = zpk_filter_group.create_dataset( 

72 "poles", 

73 poles.shape, 

74 dtype=complex, 

75 **self.dataset_options, 

76 ) 

77 zeros_ds = zpk_filter_group.create_dataset( 

78 "zeros", 

79 zeros.shape, 

80 dtype=complex, 

81 **self.dataset_options, 

82 ) 

83 

84 # when filling data need to fill the full row for what ever reason. 

85 poles_ds[:] = poles 

86 zeros_ds[:] = zeros 

87 

88 # fill in the metadata 

89 zpk_filter_group.attrs.update(zpk_metadata) 

90 

91 return zpk_filter_group 

92 

93 def remove_filter(self): 

94 pass 

95 

96 def get_filter(self, name): 

97 """ 

98 Get a filter from the name 

99 

100 :param name: name of the filter 

101 :type name: string 

102 

103 :return: HDF5 group of the ZPK filter 

104 """ 

105 return self.hdf5_group[name] 

106 

107 def from_object(self, zpk_object): 

108 """ 

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

110 

111 :param zpk_object: MT metadata PoleZeroFilter 

112 :type zpk_object: :class:`mt_metadata.timeseries.filters.PoleZeroFilter` 

113 

114 """ 

115 

116 if not isinstance(zpk_object, PoleZeroFilter): 

117 msg = f"Filter must be a PoleZeroFilter not {type(zpk_object)}" 

118 self.logger.error(msg) 

119 raise TypeError(msg) 

120 

121 input_dict = zpk_object.to_dict(single=True, required=False) 

122 input_dict.pop("poles") 

123 input_dict.pop("zeros") 

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

125 if v is None: 

126 input_dict[k] = str(v) 

127 

128 zpk_group = self.add_filter( 

129 zpk_object.name, 

130 zpk_object.poles, 

131 zpk_object.zeros, 

132 input_dict, 

133 ) 

134 return zpk_group 

135 

136 def to_object(self, name): 

137 """ 

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

139 

140 :return: DESCRIPTION 

141 :rtype: TYPE 

142 

143 """ 

144 

145 zpk_group = self.get_filter(name) 

146 

147 zpk_obj = PoleZeroFilter(**zpk_group.attrs) 

148 

149 if "poles" in zpk_group.keys(): 

150 if zpk_group["poles"].dtype == complex: 

151 zpk_obj.poles = zpk_group["poles"][:] 

152 elif "real" in zpk_group["poles"].dtype.names: 

153 zpk_obj.poles = ( 

154 zpk_group["poles"][()]["real"] + 1j * zpk_group["poles"][()]["imag"] 

155 ) 

156 else: 

157 raise ValueError( 

158 f"Cannot convert values to complex valued poles, check filter {name}" 

159 ) 

160 else: 

161 self.logger.debug(f"ZPK filter {name} has no poles") 

162 zpk_obj.poles = [] 

163 

164 if "zeros" in zpk_group.keys(): 

165 if zpk_group["zeros"].dtype == complex: 

166 zpk_obj.zeros = zpk_group["zeros"][:] 

167 elif "real" in zpk_group["zeros"].dtype.names: 

168 zpk_obj.zeros = ( 

169 zpk_group["zeros"][()]["real"] + 1j * zpk_group["zeros"][()]["imag"] 

170 ) 

171 else: 

172 raise ValueError( 

173 f"Cannot convert values to complex valued zeros, check filter {name}" 

174 ) 

175 else: 

176 self.logger.debug(f"ZPK filter {name} has no zeros") 

177 zpk_obj.zeros = [] 

178 

179 return zpk_obj