corems.transient.calc.TransientCalc
1import gc 2import warnings 3 4from numpy import ( 5 arange, 6 blackman, 7 ceil, 8 fft, 9 hamming, 10 hanning, 11 kaiser, 12 linspace, 13 log2, 14 pi, 15 power, 16 sin, 17 sqrt, 18 where, 19 zeros, 20) 21 22__author__ = "Yuri E. Corilo" 23__date__ = "Jun 12, 2019" 24 25 26class TransientCalculations(object): 27 """Transient Calculations 28 29 Parameters 30 ---------- 31 parameters : corems.transient.parameters.TransientParameters 32 The transient parameters 33 bandwidth : float 34 The bandwidth of the transient (Hz) 35 number_data_points : int 36 The number of data points of the transient 37 exc_low_freq : float 38 The low frequency of the excitation (Hz) 39 exc_high_freq : float 40 The high frequency of the excitation (Hz) 41 42 Attributes 43 ---------- 44 parameters : corems.transient.parameters.TransientParameters 45 The transient parameters 46 bandwidth : float 47 The bandwidth of the transient (Hz) 48 number_data_points : int 49 The number of data points of the transient 50 exc_low_freq : float 51 The low frequency of the excitation (Hz) 52 exc_high_freq : float 53 The high frequency of the excitation (Hz) 54 55 Methods 56 ------- 57 * cal_transient_time(). 58 Calculate the time domain length of the transient 59 * zero_fill(transient). 60 Zero fill the transient 61 * truncation(transient). 62 Truncate the transient 63 * apodization(transient). 64 Apodization of the transient 65 * calculate_frequency_domain(number_data_points). 66 Calculate the frequency domain (axis) of the transient 67 * cut_freq_domain(freqdomain_X, freqdomain_Y). 68 Cut the frequency domain of the transient 69 * phase_and_absorption_mode_ft(). 70 [Not Functional] Produce a phased absorption mode FT spectrum 71 * magnitude_mode_ft(transient). 72 Perform magnitude mode FT of the transient 73 * correct_dc_offset(). 74 [Not Yet Implemented] Correct the DC offset of the transient 75 76 """ 77 78 def cal_transient_time(self): 79 """Calculate the time domain length of the transient 80 81 Returns 82 ------- 83 float 84 The time domain length of the transient (s) 85 """ 86 return (1 / self.bandwidth) * ((self.number_data_points) / 2) 87 88 def zero_fill(self, transient): 89 """Zero fill the transient 90 91 Parameters 92 ---------- 93 transient : numpy.ndarray 94 The transient data points 95 96 Returns 97 ------- 98 numpy.ndarray 99 The transient data points zerofilled 100 101 Notes 102 ----- 103 The number of zero fills is defined by the transient parameter number_of_zero_fills. 104 The function first calculate the next power of two of the transient length and zero fills to that length, to take advantage of FFT algorithm. 105 If the parameter next_power_of_two is set to False, the function will zero fill to the length of the original transient times the number of zero fills 106 107 """ 108 if self.parameters.next_power_of_two: 109 exponent = int( 110 ceil(log2(len(transient) * (self.parameters.number_of_zero_fills + 1))) 111 ) 112 zeros_filled_transient = zeros(2**exponent) 113 else: 114 zeros_filled_transient = zeros( 115 len(transient) * (self.parameters.number_of_zero_fills + 1) 116 ) 117 118 zeros_filled_transient[0 : len(transient)] = transient 119 120 del transient 121 122 gc.collect() 123 124 return zeros_filled_transient 125 126 def truncation(self, transient): 127 """Truncate the transient 128 129 Parameters 130 ---------- 131 transient : numpy.ndarray 132 The transient data points 133 134 Returns 135 ------- 136 numpy.ndarray 137 The truncated transient data points 138 139 Notes 140 ----- 141 The number of truncations is defined by the transient parameter number_of_truncations 142 """ 143 144 data_count = len(transient) 145 146 for _ in range(self.parameters.number_of_truncations): 147 data_count = int(data_count / 2) 148 149 time_domain_truncated = transient[0:data_count] 150 151 del transient 152 153 gc.collect() 154 155 return time_domain_truncated 156 157 def apodization(self, transient): 158 """Apodization of the transient 159 160 Parameters 161 ---------- 162 transient : numpy.ndarray 163 The transient data points 164 165 Returns 166 ------- 167 numpy.ndarray 168 The apodized transient data points 169 170 Notes 171 ----- 172 The apodization method is defined by the transient parameter apodization_method. 173 The following apodization methods are available: 174 Hamming, 175 Hanning, 176 Blackman, 177 Full-Sine, 178 Half-Sine, 179 Kaiser, 180 Half-Kaiser. 181 182 For Kaiser and Half-Kaiser, an additional parameter 'beta' is required, set by the transient parameter kaiser_beta. 183 184 """ 185 186 apodi_method = self.parameters.apodization_method 187 beta = self.parameters.kaiser_beta 188 189 length = len(transient) 190 191 if apodi_method == "Hamming": 192 H_function = hamming(length) 193 elif apodi_method == "Hanning": 194 H_function = hanning(length) 195 elif apodi_method == "Blackman": 196 H_function = blackman(length) 197 elif apodi_method == "Full-Sine": 198 H_function = sin(linspace(0, pi, num=length)) 199 elif apodi_method == "Half-Sine": 200 H_function = sin(linspace((pi / 2), 0, num=length)) 201 elif apodi_method == "Kaiser": 202 H_function = kaiser(length, beta) 203 elif apodi_method == "Half-Kaiser": 204 H_function = kaiser(length * 2, beta)[length:] 205 206 S_x = transient * H_function 207 208 del transient 209 gc.collect() 210 211 return S_x 212 213 def calculate_frequency_domain(self, number_data_points): 214 """Calculate the frequency domain (axis) of the transient 215 216 Parameters 217 ---------- 218 number_data_points : int 219 The number of data points of the transient 220 221 Returns 222 ------- 223 numpy.ndarray 224 The frequency domain of the transient (Hz) 225 226 227 """ 228 229 qntpoints = arange(0, (number_data_points)) 230 231 factor_distancy = (self.bandwidth) / (number_data_points) 232 233 frequency_domain = qntpoints * factor_distancy 234 235 del qntpoints 236 del factor_distancy 237 gc.collect() 238 239 return frequency_domain 240 241 def cut_freq_domain(self, freqdomain_X, freqdomain_Y): 242 """Cut the frequency domain of the transient 243 244 Parameters 245 ---------- 246 freqdomain_X : numpy.ndarray 247 The frequency domain of the transient (Hz) 248 freqdomain_Y : numpy.ndarray 249 The frequency domain of the transient (Hz) 250 251 Returns 252 ------- 253 numpy.ndarray 254 The frequency domain of the transient (Hz) 255 numpy.ndarray 256 The frequency domain of the transient (Hz) 257 258 259 """ 260 # If the mw_low and mw_high are set, the frequency domain is cut to the mw range 261 # this accounts for the detection settings, not the excitation settings. 262 # TODO: Implement this - right now the f to mz function is in the ms class, not the transient class, so it doesnt work. 263 # if (self._mw_low != 0) & (self._mw_high != 0): 264 # high_freq = self._f_to_mz(self._mw_high) 265 # low_freq = self._f_to_mz(self._mw_low) 266 # 267 # final = where(freqdomain_X < high_freq)[-1][-1] 268 # start = where(freqdomain_X > low_freq)[0][0] 269 # else: 270 if self._qpd_enabled == 1: 271 low_freq = self._exc_low_freq * 2 272 high_freq = self._exc_high_freq * 2 273 else: 274 low_freq = self._exc_low_freq 275 high_freq = self._exc_high_freq 276 277 if self._exc_low_freq > self._exc_high_freq: 278 # TODO: This needs to be tested 279 # I'm not sure that this is relevant anyway - the excitation pulse is ramped in frequency but the detection is simulatenous 280 warnings.warn("This is not tested. Please check the results.") 281 final = where(freqdomain_X > low_freq)[0][0] 282 start = where(freqdomain_X > high_freq)[0][0] 283 284 else: 285 final = where(freqdomain_X < high_freq)[-1][-1] 286 start = where(freqdomain_X > low_freq)[0][0] 287 288 return freqdomain_X[start:final], freqdomain_Y[start:final] 289 # del freqdomain_X, freqdomain_Y 290 # gc.collect() 291 292 def phase_and_absorption_mode_ft(self): 293 """[Not Functional] Produce a phased absorption mode FT spectrum""" 294 # anyone wants to play with this part please make yourself comfortable. I will: 295 pass 296 297 def perform_magniture_mode_ft(self, transient): 298 """Perform magnitude mode FT of the transient 299 300 Parameters 301 ---------- 302 transient : numpy.ndarray 303 The transient data points 304 305 Returns 306 ------- 307 numpy.ndarray 308 The frequency domain of the transient (Hz) 309 numpy.ndarray 310 The magnitude of the transient (a.u.) 311 312 313 """ 314 315 A = fft.rfft(transient) 316 317 # A = fft.fft(transient) 318 # A = A[0:int(len(A)/2)] 319 320 factor = int(self.parameters.number_of_zero_fills - 1) 321 if self.parameters.number_of_zero_fills: 322 if self.parameters.number_of_zero_fills == 1: 323 factor = 1 / 2 324 325 else: 326 factor = int(1 / self.parameters.number_of_zero_fills + 1) 327 328 Max_index = int(len(A) / factor) 329 330 else: 331 Max_index = int(len(A)) 332 333 A = A[0:Max_index] 334 335 datapoints = len(A) 336 337 freqdomain_X = self.calculate_frequency_domain(datapoints) 338 339 magnitude_Y = sqrt((power(A.real, 2)) + (power(A.imag, 2))) 340 341 freqdomain_X_cut, magnitude_Y_cut = self.cut_freq_domain( 342 freqdomain_X, magnitude_Y 343 ) 344 345 del transient 346 # del freqdomain_X 347 # del magnitude_Y 348 gc.collect() 349 350 return freqdomain_X_cut, magnitude_Y_cut 351 352 def correct_dc_offset(self): 353 """[Not Yet Implemented] Correct the DC offset of the transient 354 355 A simple baseline correction to compensate for a DC offset in the recorded transient. 356 Not implemented. 357 358 """ 359 pass
27class TransientCalculations(object): 28 """Transient Calculations 29 30 Parameters 31 ---------- 32 parameters : corems.transient.parameters.TransientParameters 33 The transient parameters 34 bandwidth : float 35 The bandwidth of the transient (Hz) 36 number_data_points : int 37 The number of data points of the transient 38 exc_low_freq : float 39 The low frequency of the excitation (Hz) 40 exc_high_freq : float 41 The high frequency of the excitation (Hz) 42 43 Attributes 44 ---------- 45 parameters : corems.transient.parameters.TransientParameters 46 The transient parameters 47 bandwidth : float 48 The bandwidth of the transient (Hz) 49 number_data_points : int 50 The number of data points of the transient 51 exc_low_freq : float 52 The low frequency of the excitation (Hz) 53 exc_high_freq : float 54 The high frequency of the excitation (Hz) 55 56 Methods 57 ------- 58 * cal_transient_time(). 59 Calculate the time domain length of the transient 60 * zero_fill(transient). 61 Zero fill the transient 62 * truncation(transient). 63 Truncate the transient 64 * apodization(transient). 65 Apodization of the transient 66 * calculate_frequency_domain(number_data_points). 67 Calculate the frequency domain (axis) of the transient 68 * cut_freq_domain(freqdomain_X, freqdomain_Y). 69 Cut the frequency domain of the transient 70 * phase_and_absorption_mode_ft(). 71 [Not Functional] Produce a phased absorption mode FT spectrum 72 * magnitude_mode_ft(transient). 73 Perform magnitude mode FT of the transient 74 * correct_dc_offset(). 75 [Not Yet Implemented] Correct the DC offset of the transient 76 77 """ 78 79 def cal_transient_time(self): 80 """Calculate the time domain length of the transient 81 82 Returns 83 ------- 84 float 85 The time domain length of the transient (s) 86 """ 87 return (1 / self.bandwidth) * ((self.number_data_points) / 2) 88 89 def zero_fill(self, transient): 90 """Zero fill the transient 91 92 Parameters 93 ---------- 94 transient : numpy.ndarray 95 The transient data points 96 97 Returns 98 ------- 99 numpy.ndarray 100 The transient data points zerofilled 101 102 Notes 103 ----- 104 The number of zero fills is defined by the transient parameter number_of_zero_fills. 105 The function first calculate the next power of two of the transient length and zero fills to that length, to take advantage of FFT algorithm. 106 If the parameter next_power_of_two is set to False, the function will zero fill to the length of the original transient times the number of zero fills 107 108 """ 109 if self.parameters.next_power_of_two: 110 exponent = int( 111 ceil(log2(len(transient) * (self.parameters.number_of_zero_fills + 1))) 112 ) 113 zeros_filled_transient = zeros(2**exponent) 114 else: 115 zeros_filled_transient = zeros( 116 len(transient) * (self.parameters.number_of_zero_fills + 1) 117 ) 118 119 zeros_filled_transient[0 : len(transient)] = transient 120 121 del transient 122 123 gc.collect() 124 125 return zeros_filled_transient 126 127 def truncation(self, transient): 128 """Truncate the transient 129 130 Parameters 131 ---------- 132 transient : numpy.ndarray 133 The transient data points 134 135 Returns 136 ------- 137 numpy.ndarray 138 The truncated transient data points 139 140 Notes 141 ----- 142 The number of truncations is defined by the transient parameter number_of_truncations 143 """ 144 145 data_count = len(transient) 146 147 for _ in range(self.parameters.number_of_truncations): 148 data_count = int(data_count / 2) 149 150 time_domain_truncated = transient[0:data_count] 151 152 del transient 153 154 gc.collect() 155 156 return time_domain_truncated 157 158 def apodization(self, transient): 159 """Apodization of the transient 160 161 Parameters 162 ---------- 163 transient : numpy.ndarray 164 The transient data points 165 166 Returns 167 ------- 168 numpy.ndarray 169 The apodized transient data points 170 171 Notes 172 ----- 173 The apodization method is defined by the transient parameter apodization_method. 174 The following apodization methods are available: 175 Hamming, 176 Hanning, 177 Blackman, 178 Full-Sine, 179 Half-Sine, 180 Kaiser, 181 Half-Kaiser. 182 183 For Kaiser and Half-Kaiser, an additional parameter 'beta' is required, set by the transient parameter kaiser_beta. 184 185 """ 186 187 apodi_method = self.parameters.apodization_method 188 beta = self.parameters.kaiser_beta 189 190 length = len(transient) 191 192 if apodi_method == "Hamming": 193 H_function = hamming(length) 194 elif apodi_method == "Hanning": 195 H_function = hanning(length) 196 elif apodi_method == "Blackman": 197 H_function = blackman(length) 198 elif apodi_method == "Full-Sine": 199 H_function = sin(linspace(0, pi, num=length)) 200 elif apodi_method == "Half-Sine": 201 H_function = sin(linspace((pi / 2), 0, num=length)) 202 elif apodi_method == "Kaiser": 203 H_function = kaiser(length, beta) 204 elif apodi_method == "Half-Kaiser": 205 H_function = kaiser(length * 2, beta)[length:] 206 207 S_x = transient * H_function 208 209 del transient 210 gc.collect() 211 212 return S_x 213 214 def calculate_frequency_domain(self, number_data_points): 215 """Calculate the frequency domain (axis) of the transient 216 217 Parameters 218 ---------- 219 number_data_points : int 220 The number of data points of the transient 221 222 Returns 223 ------- 224 numpy.ndarray 225 The frequency domain of the transient (Hz) 226 227 228 """ 229 230 qntpoints = arange(0, (number_data_points)) 231 232 factor_distancy = (self.bandwidth) / (number_data_points) 233 234 frequency_domain = qntpoints * factor_distancy 235 236 del qntpoints 237 del factor_distancy 238 gc.collect() 239 240 return frequency_domain 241 242 def cut_freq_domain(self, freqdomain_X, freqdomain_Y): 243 """Cut the frequency domain of the transient 244 245 Parameters 246 ---------- 247 freqdomain_X : numpy.ndarray 248 The frequency domain of the transient (Hz) 249 freqdomain_Y : numpy.ndarray 250 The frequency domain of the transient (Hz) 251 252 Returns 253 ------- 254 numpy.ndarray 255 The frequency domain of the transient (Hz) 256 numpy.ndarray 257 The frequency domain of the transient (Hz) 258 259 260 """ 261 # If the mw_low and mw_high are set, the frequency domain is cut to the mw range 262 # this accounts for the detection settings, not the excitation settings. 263 # TODO: Implement this - right now the f to mz function is in the ms class, not the transient class, so it doesnt work. 264 # if (self._mw_low != 0) & (self._mw_high != 0): 265 # high_freq = self._f_to_mz(self._mw_high) 266 # low_freq = self._f_to_mz(self._mw_low) 267 # 268 # final = where(freqdomain_X < high_freq)[-1][-1] 269 # start = where(freqdomain_X > low_freq)[0][0] 270 # else: 271 if self._qpd_enabled == 1: 272 low_freq = self._exc_low_freq * 2 273 high_freq = self._exc_high_freq * 2 274 else: 275 low_freq = self._exc_low_freq 276 high_freq = self._exc_high_freq 277 278 if self._exc_low_freq > self._exc_high_freq: 279 # TODO: This needs to be tested 280 # I'm not sure that this is relevant anyway - the excitation pulse is ramped in frequency but the detection is simulatenous 281 warnings.warn("This is not tested. Please check the results.") 282 final = where(freqdomain_X > low_freq)[0][0] 283 start = where(freqdomain_X > high_freq)[0][0] 284 285 else: 286 final = where(freqdomain_X < high_freq)[-1][-1] 287 start = where(freqdomain_X > low_freq)[0][0] 288 289 return freqdomain_X[start:final], freqdomain_Y[start:final] 290 # del freqdomain_X, freqdomain_Y 291 # gc.collect() 292 293 def phase_and_absorption_mode_ft(self): 294 """[Not Functional] Produce a phased absorption mode FT spectrum""" 295 # anyone wants to play with this part please make yourself comfortable. I will: 296 pass 297 298 def perform_magniture_mode_ft(self, transient): 299 """Perform magnitude mode FT of the transient 300 301 Parameters 302 ---------- 303 transient : numpy.ndarray 304 The transient data points 305 306 Returns 307 ------- 308 numpy.ndarray 309 The frequency domain of the transient (Hz) 310 numpy.ndarray 311 The magnitude of the transient (a.u.) 312 313 314 """ 315 316 A = fft.rfft(transient) 317 318 # A = fft.fft(transient) 319 # A = A[0:int(len(A)/2)] 320 321 factor = int(self.parameters.number_of_zero_fills - 1) 322 if self.parameters.number_of_zero_fills: 323 if self.parameters.number_of_zero_fills == 1: 324 factor = 1 / 2 325 326 else: 327 factor = int(1 / self.parameters.number_of_zero_fills + 1) 328 329 Max_index = int(len(A) / factor) 330 331 else: 332 Max_index = int(len(A)) 333 334 A = A[0:Max_index] 335 336 datapoints = len(A) 337 338 freqdomain_X = self.calculate_frequency_domain(datapoints) 339 340 magnitude_Y = sqrt((power(A.real, 2)) + (power(A.imag, 2))) 341 342 freqdomain_X_cut, magnitude_Y_cut = self.cut_freq_domain( 343 freqdomain_X, magnitude_Y 344 ) 345 346 del transient 347 # del freqdomain_X 348 # del magnitude_Y 349 gc.collect() 350 351 return freqdomain_X_cut, magnitude_Y_cut 352 353 def correct_dc_offset(self): 354 """[Not Yet Implemented] Correct the DC offset of the transient 355 356 A simple baseline correction to compensate for a DC offset in the recorded transient. 357 Not implemented. 358 359 """ 360 pass
Transient Calculations
Parameters
- parameters (corems.transient.parameters.TransientParameters): The transient parameters
- bandwidth (float): The bandwidth of the transient (Hz)
- number_data_points (int): The number of data points of the transient
- exc_low_freq (float): The low frequency of the excitation (Hz)
- exc_high_freq (float): The high frequency of the excitation (Hz)
Attributes
- parameters (corems.transient.parameters.TransientParameters): The transient parameters
- bandwidth (float): The bandwidth of the transient (Hz)
- number_data_points (int): The number of data points of the transient
- exc_low_freq (float): The low frequency of the excitation (Hz)
- exc_high_freq (float): The high frequency of the excitation (Hz)
Methods
- cal_transient_time(). Calculate the time domain length of the transient
- zero_fill(transient). Zero fill the transient
- truncation(transient). Truncate the transient
- apodization(transient). Apodization of the transient
- calculate_frequency_domain(number_data_points). Calculate the frequency domain (axis) of the transient
- cut_freq_domain(freqdomain_X, freqdomain_Y). Cut the frequency domain of the transient
- phase_and_absorption_mode_ft(). [Not Functional] Produce a phased absorption mode FT spectrum
- magnitude_mode_ft(transient). Perform magnitude mode FT of the transient
- correct_dc_offset(). [Not Yet Implemented] Correct the DC offset of the transient
79 def cal_transient_time(self): 80 """Calculate the time domain length of the transient 81 82 Returns 83 ------- 84 float 85 The time domain length of the transient (s) 86 """ 87 return (1 / self.bandwidth) * ((self.number_data_points) / 2)
Calculate the time domain length of the transient
Returns
- float: The time domain length of the transient (s)
89 def zero_fill(self, transient): 90 """Zero fill the transient 91 92 Parameters 93 ---------- 94 transient : numpy.ndarray 95 The transient data points 96 97 Returns 98 ------- 99 numpy.ndarray 100 The transient data points zerofilled 101 102 Notes 103 ----- 104 The number of zero fills is defined by the transient parameter number_of_zero_fills. 105 The function first calculate the next power of two of the transient length and zero fills to that length, to take advantage of FFT algorithm. 106 If the parameter next_power_of_two is set to False, the function will zero fill to the length of the original transient times the number of zero fills 107 108 """ 109 if self.parameters.next_power_of_two: 110 exponent = int( 111 ceil(log2(len(transient) * (self.parameters.number_of_zero_fills + 1))) 112 ) 113 zeros_filled_transient = zeros(2**exponent) 114 else: 115 zeros_filled_transient = zeros( 116 len(transient) * (self.parameters.number_of_zero_fills + 1) 117 ) 118 119 zeros_filled_transient[0 : len(transient)] = transient 120 121 del transient 122 123 gc.collect() 124 125 return zeros_filled_transient
Zero fill the transient
Parameters
- transient (numpy.ndarray): The transient data points
Returns
- numpy.ndarray: The transient data points zerofilled
Notes
The number of zero fills is defined by the transient parameter number_of_zero_fills. The function first calculate the next power of two of the transient length and zero fills to that length, to take advantage of FFT algorithm. If the parameter next_power_of_two is set to False, the function will zero fill to the length of the original transient times the number of zero fills
127 def truncation(self, transient): 128 """Truncate the transient 129 130 Parameters 131 ---------- 132 transient : numpy.ndarray 133 The transient data points 134 135 Returns 136 ------- 137 numpy.ndarray 138 The truncated transient data points 139 140 Notes 141 ----- 142 The number of truncations is defined by the transient parameter number_of_truncations 143 """ 144 145 data_count = len(transient) 146 147 for _ in range(self.parameters.number_of_truncations): 148 data_count = int(data_count / 2) 149 150 time_domain_truncated = transient[0:data_count] 151 152 del transient 153 154 gc.collect() 155 156 return time_domain_truncated
Truncate the transient
Parameters
- transient (numpy.ndarray): The transient data points
Returns
- numpy.ndarray: The truncated transient data points
Notes
The number of truncations is defined by the transient parameter number_of_truncations
158 def apodization(self, transient): 159 """Apodization of the transient 160 161 Parameters 162 ---------- 163 transient : numpy.ndarray 164 The transient data points 165 166 Returns 167 ------- 168 numpy.ndarray 169 The apodized transient data points 170 171 Notes 172 ----- 173 The apodization method is defined by the transient parameter apodization_method. 174 The following apodization methods are available: 175 Hamming, 176 Hanning, 177 Blackman, 178 Full-Sine, 179 Half-Sine, 180 Kaiser, 181 Half-Kaiser. 182 183 For Kaiser and Half-Kaiser, an additional parameter 'beta' is required, set by the transient parameter kaiser_beta. 184 185 """ 186 187 apodi_method = self.parameters.apodization_method 188 beta = self.parameters.kaiser_beta 189 190 length = len(transient) 191 192 if apodi_method == "Hamming": 193 H_function = hamming(length) 194 elif apodi_method == "Hanning": 195 H_function = hanning(length) 196 elif apodi_method == "Blackman": 197 H_function = blackman(length) 198 elif apodi_method == "Full-Sine": 199 H_function = sin(linspace(0, pi, num=length)) 200 elif apodi_method == "Half-Sine": 201 H_function = sin(linspace((pi / 2), 0, num=length)) 202 elif apodi_method == "Kaiser": 203 H_function = kaiser(length, beta) 204 elif apodi_method == "Half-Kaiser": 205 H_function = kaiser(length * 2, beta)[length:] 206 207 S_x = transient * H_function 208 209 del transient 210 gc.collect() 211 212 return S_x
Apodization of the transient
Parameters
- transient (numpy.ndarray): The transient data points
Returns
- numpy.ndarray: The apodized transient data points
Notes
The apodization method is defined by the transient parameter apodization_method. The following apodization methods are available: Hamming, Hanning, Blackman, Full-Sine, Half-Sine, Kaiser, Half-Kaiser.
For Kaiser and Half-Kaiser, an additional parameter 'beta' is required, set by the transient parameter kaiser_beta.
214 def calculate_frequency_domain(self, number_data_points): 215 """Calculate the frequency domain (axis) of the transient 216 217 Parameters 218 ---------- 219 number_data_points : int 220 The number of data points of the transient 221 222 Returns 223 ------- 224 numpy.ndarray 225 The frequency domain of the transient (Hz) 226 227 228 """ 229 230 qntpoints = arange(0, (number_data_points)) 231 232 factor_distancy = (self.bandwidth) / (number_data_points) 233 234 frequency_domain = qntpoints * factor_distancy 235 236 del qntpoints 237 del factor_distancy 238 gc.collect() 239 240 return frequency_domain
Calculate the frequency domain (axis) of the transient
Parameters
- number_data_points (int): The number of data points of the transient
Returns
- numpy.ndarray: The frequency domain of the transient (Hz)
242 def cut_freq_domain(self, freqdomain_X, freqdomain_Y): 243 """Cut the frequency domain of the transient 244 245 Parameters 246 ---------- 247 freqdomain_X : numpy.ndarray 248 The frequency domain of the transient (Hz) 249 freqdomain_Y : numpy.ndarray 250 The frequency domain of the transient (Hz) 251 252 Returns 253 ------- 254 numpy.ndarray 255 The frequency domain of the transient (Hz) 256 numpy.ndarray 257 The frequency domain of the transient (Hz) 258 259 260 """ 261 # If the mw_low and mw_high are set, the frequency domain is cut to the mw range 262 # this accounts for the detection settings, not the excitation settings. 263 # TODO: Implement this - right now the f to mz function is in the ms class, not the transient class, so it doesnt work. 264 # if (self._mw_low != 0) & (self._mw_high != 0): 265 # high_freq = self._f_to_mz(self._mw_high) 266 # low_freq = self._f_to_mz(self._mw_low) 267 # 268 # final = where(freqdomain_X < high_freq)[-1][-1] 269 # start = where(freqdomain_X > low_freq)[0][0] 270 # else: 271 if self._qpd_enabled == 1: 272 low_freq = self._exc_low_freq * 2 273 high_freq = self._exc_high_freq * 2 274 else: 275 low_freq = self._exc_low_freq 276 high_freq = self._exc_high_freq 277 278 if self._exc_low_freq > self._exc_high_freq: 279 # TODO: This needs to be tested 280 # I'm not sure that this is relevant anyway - the excitation pulse is ramped in frequency but the detection is simulatenous 281 warnings.warn("This is not tested. Please check the results.") 282 final = where(freqdomain_X > low_freq)[0][0] 283 start = where(freqdomain_X > high_freq)[0][0] 284 285 else: 286 final = where(freqdomain_X < high_freq)[-1][-1] 287 start = where(freqdomain_X > low_freq)[0][0] 288 289 return freqdomain_X[start:final], freqdomain_Y[start:final] 290 # del freqdomain_X, freqdomain_Y 291 # gc.collect()
Cut the frequency domain of the transient
Parameters
- freqdomain_X (numpy.ndarray): The frequency domain of the transient (Hz)
- freqdomain_Y (numpy.ndarray): The frequency domain of the transient (Hz)
Returns
- numpy.ndarray: The frequency domain of the transient (Hz)
- numpy.ndarray: The frequency domain of the transient (Hz)
293 def phase_and_absorption_mode_ft(self): 294 """[Not Functional] Produce a phased absorption mode FT spectrum""" 295 # anyone wants to play with this part please make yourself comfortable. I will: 296 pass
[Not Functional] Produce a phased absorption mode FT spectrum
298 def perform_magniture_mode_ft(self, transient): 299 """Perform magnitude mode FT of the transient 300 301 Parameters 302 ---------- 303 transient : numpy.ndarray 304 The transient data points 305 306 Returns 307 ------- 308 numpy.ndarray 309 The frequency domain of the transient (Hz) 310 numpy.ndarray 311 The magnitude of the transient (a.u.) 312 313 314 """ 315 316 A = fft.rfft(transient) 317 318 # A = fft.fft(transient) 319 # A = A[0:int(len(A)/2)] 320 321 factor = int(self.parameters.number_of_zero_fills - 1) 322 if self.parameters.number_of_zero_fills: 323 if self.parameters.number_of_zero_fills == 1: 324 factor = 1 / 2 325 326 else: 327 factor = int(1 / self.parameters.number_of_zero_fills + 1) 328 329 Max_index = int(len(A) / factor) 330 331 else: 332 Max_index = int(len(A)) 333 334 A = A[0:Max_index] 335 336 datapoints = len(A) 337 338 freqdomain_X = self.calculate_frequency_domain(datapoints) 339 340 magnitude_Y = sqrt((power(A.real, 2)) + (power(A.imag, 2))) 341 342 freqdomain_X_cut, magnitude_Y_cut = self.cut_freq_domain( 343 freqdomain_X, magnitude_Y 344 ) 345 346 del transient 347 # del freqdomain_X 348 # del magnitude_Y 349 gc.collect() 350 351 return freqdomain_X_cut, magnitude_Y_cut
Perform magnitude mode FT of the transient
Parameters
- transient (numpy.ndarray): The transient data points
Returns
- numpy.ndarray: The frequency domain of the transient (Hz)
- numpy.ndarray: The magnitude of the transient (a.u.)
353 def correct_dc_offset(self): 354 """[Not Yet Implemented] Correct the DC offset of the transient 355 356 A simple baseline correction to compensate for a DC offset in the recorded transient. 357 Not implemented. 358 359 """ 360 pass
[Not Yet Implemented] Correct the DC offset of the transient
A simple baseline correction to compensate for a DC offset in the recorded transient. Not implemented.