pqopen-lib 0.8.5__py3-none-any.whl → 0.9.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pqopen/powerquality.py +13 -0
- pqopen/powersystem.py +31 -4
- {pqopen_lib-0.8.5.dist-info → pqopen_lib-0.9.0.dist-info}/METADATA +1 -1
- {pqopen_lib-0.8.5.dist-info → pqopen_lib-0.9.0.dist-info}/RECORD +6 -6
- {pqopen_lib-0.8.5.dist-info → pqopen_lib-0.9.0.dist-info}/WHEEL +0 -0
- {pqopen_lib-0.8.5.dist-info → pqopen_lib-0.9.0.dist-info}/licenses/LICENSE +0 -0
pqopen/powerquality.py
CHANGED
|
@@ -63,6 +63,19 @@ def calc_thd(harm_rms: np.ndarray, max_harmonic: int = 40, min_harmonic: int = 2
|
|
|
63
63
|
thd = np.sqrt(np.sum(np.power(harm_rms[min_harmonic:max_harmonic+1]/fund_rms, 2)))*100
|
|
64
64
|
return thd
|
|
65
65
|
|
|
66
|
+
def calc_hf_1khz_band(fft_data: np.ndarray, samplerate: float):
|
|
67
|
+
fft_data_abs = np.abs(fft_data)
|
|
68
|
+
freq_resolution = 0.5*samplerate / fft_data_abs.shape[0]
|
|
69
|
+
freq_steps = np.arange(-500, (samplerate/2) + 1500 - (samplerate/2) % 1000, 1000)
|
|
70
|
+
freq_steps[0] = 0
|
|
71
|
+
freq_steps[-1] = samplerate/2
|
|
72
|
+
freq_band_idx = (freq_steps / freq_resolution).astype(int)
|
|
73
|
+
hf_1khz_band_rms = []
|
|
74
|
+
for band_idx in range(freq_band_idx.shape[0] - 1):
|
|
75
|
+
hf_1khz_band_rms.append(np.sqrt(np.sum(fft_data_abs[freq_band_idx[band_idx]:freq_band_idx[band_idx+1]])))
|
|
76
|
+
|
|
77
|
+
return np.array(hf_1khz_band_rms)
|
|
78
|
+
|
|
66
79
|
def resample_and_fft(data: np.ndarray, resample_size: int = None) -> np.ndarray:
|
|
67
80
|
"""
|
|
68
81
|
Resample the input data to a specified size and compute its FFT.
|
pqopen/powersystem.py
CHANGED
|
@@ -24,6 +24,7 @@ from typing import List, Dict
|
|
|
24
24
|
import logging
|
|
25
25
|
from pathlib import Path
|
|
26
26
|
import json
|
|
27
|
+
from scipy.signal import get_window
|
|
27
28
|
|
|
28
29
|
from daqopen.channelbuffer import AcqBuffer, DataChannelBuffer
|
|
29
30
|
from pqopen.zcd import ZeroCrossDetector
|
|
@@ -91,7 +92,8 @@ class PowerSystem(object):
|
|
|
91
92
|
"energy_channels": {},
|
|
92
93
|
"one_period_fundamental": 0,
|
|
93
94
|
"rms_trapz_rule": False,
|
|
94
|
-
"pmu_calculation": False
|
|
95
|
+
"pmu_calculation": False,
|
|
96
|
+
"hf_1khz_band_calculation": False}
|
|
95
97
|
self._prepare_calc_channels()
|
|
96
98
|
self.output_channels: Dict[str, DataChannelBuffer] = {}
|
|
97
99
|
self._last_processed_sidx = 0
|
|
@@ -246,6 +248,15 @@ class PowerSystem(object):
|
|
|
246
248
|
self._pmu_last_processed_ts_us = 0
|
|
247
249
|
self._pmu_time_increment_us = int(1_000_000 / self.nominal_frequency)
|
|
248
250
|
|
|
251
|
+
def enable_hf_1khz_band_calculation(self):
|
|
252
|
+
"""
|
|
253
|
+
Enables the calculation of wide band analysis with 1 kHz bands (non standard)
|
|
254
|
+
"""
|
|
255
|
+
num_bands = int(self._samplerate*0.5 / 1000) + 1
|
|
256
|
+
self._features["hf_1khz_band_calculation"] = num_bands
|
|
257
|
+
self._hf_1khz_window = get_window("hann", self._harm_fft_resample_size)
|
|
258
|
+
self._channel_update_needed = True
|
|
259
|
+
|
|
249
260
|
def _resync_nper_abs_time(self, zc_idx: int):
|
|
250
261
|
if not self._features["nper_abs_time_sync"]:
|
|
251
262
|
return None
|
|
@@ -305,11 +316,11 @@ class PowerSystem(object):
|
|
|
305
316
|
if self._features["harmonics"]:
|
|
306
317
|
for phase in self._phases:
|
|
307
318
|
if phase._u_channel.freq_response:
|
|
308
|
-
phase._u_fft_corr_array = create_fft_corr_array(self.
|
|
319
|
+
phase._u_fft_corr_array = create_fft_corr_array(int((self._samplerate / self.nominal_frequency) * self.nper / 2),
|
|
309
320
|
self._samplerate/2,
|
|
310
321
|
phase._u_channel.freq_response)
|
|
311
322
|
if phase._i_channel is not None and phase._i_channel.freq_response:
|
|
312
|
-
phase._i_fft_corr_array = create_fft_corr_array(self.
|
|
323
|
+
phase._i_fft_corr_array = create_fft_corr_array(int((self._samplerate / self.nominal_frequency) * self.nper / 2),
|
|
313
324
|
self._samplerate/2,
|
|
314
325
|
phase._i_channel.freq_response)
|
|
315
326
|
|
|
@@ -482,7 +493,8 @@ class PowerSystem(object):
|
|
|
482
493
|
data_fft_U = pq.resample_and_fft(u_values, self._harm_fft_resample_size)
|
|
483
494
|
if phase._u_fft_corr_array is not None:
|
|
484
495
|
resample_factor = min(self._harm_fft_resample_size / u_values.size, 1)
|
|
485
|
-
|
|
496
|
+
corr_freq_idx = np.linspace(0, self._samplerate*0.5*resample_factor*self.nper/self.nominal_frequency, self._harm_fft_resample_size//2+1).astype(np.int32)
|
|
497
|
+
data_fft_U *= phase._u_fft_corr_array[corr_freq_idx]
|
|
486
498
|
u_h_mag, u_h_phi = pq.calc_harmonics(data_fft_U, self.nper, self._features["harmonics"])
|
|
487
499
|
u_ih_mag = pq.calc_interharmonics(data_fft_U, self.nper, self._features["harmonics"])
|
|
488
500
|
if phase._number == 1: # use phase 1 angle as reference
|
|
@@ -511,6 +523,17 @@ class PowerSystem(object):
|
|
|
511
523
|
output_channel.put_data_single(stop_sidx, u_rms)
|
|
512
524
|
if phys_type == "over":
|
|
513
525
|
output_channel.put_data_single(stop_sidx, u_rms)
|
|
526
|
+
if phys_type == "hf_1khz_rms":
|
|
527
|
+
u_values_windowed = u_values[:self._harm_fft_resample_size]*self._hf_1khz_window
|
|
528
|
+
u_real_fft = np.fft.rfft(u_values_windowed)
|
|
529
|
+
#u_real_fft = np.fft.rfft(u_values_windowed)
|
|
530
|
+
if phase._u_fft_corr_array is not None:
|
|
531
|
+
corr_freq_idx = np.linspace(0, self._samplerate*0.5, u_real_fft.shape[0]).astype(np.int32)
|
|
532
|
+
u_real_fft *= phase._u_fft_corr_array[corr_freq_idx]
|
|
533
|
+
u_Pxx = (np.abs(u_real_fft) ** 2) / np.sum(self._hf_1khz_window ** 2)
|
|
534
|
+
u_Pxx /= self._harm_fft_resample_size * 0.5
|
|
535
|
+
u_hf_1khz = pq.calc_hf_1khz_band(u_Pxx, self._samplerate)
|
|
536
|
+
output_channel.put_data_single(stop_sidx, u_hf_1khz)
|
|
514
537
|
|
|
515
538
|
if phase._i_channel:
|
|
516
539
|
i_values = phase._i_channel.read_data_by_index(start_sidx, stop_sidx)
|
|
@@ -810,6 +833,10 @@ class PowerPhase(object):
|
|
|
810
833
|
self._calc_channels["pmu"]["voltage"]["rms"] = DataChannelBuffer('U{:s}_pmu_rms'.format(self.name), agg_type='rms', unit="V")
|
|
811
834
|
self._calc_channels["pmu"]["voltage"]["phi"] = DataChannelBuffer('U{:s}_pmu_phi'.format(self.name), agg_type='phi', unit="°")
|
|
812
835
|
|
|
836
|
+
if "hf_1khz_band_calculation" in features and features["hf_1khz_band_calculation"]:
|
|
837
|
+
num_bands = features["hf_1khz_band_calculation"]
|
|
838
|
+
self._calc_channels["multi_period"]["voltage"]["hf_1khz_rms"] = DataChannelBuffer('U{:s}_HF_1kHz_rms'.format(self.name), sample_dimension=num_bands, agg_type='rms', unit="V")
|
|
839
|
+
|
|
813
840
|
# Create Current Channels
|
|
814
841
|
if self._i_channel:
|
|
815
842
|
self._calc_channels["one_period"]["current"] = {}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pqopen-lib
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0
|
|
4
4
|
Summary: A power quality processing library for calculating parameters from waveform data
|
|
5
5
|
Project-URL: Homepage, https://github.com/DaqOpen/pqopen-lib
|
|
6
6
|
Project-URL: Issues, https://github.com/DaqOpen/pqopen-lib/issues
|
|
@@ -2,11 +2,11 @@ pqopen/__init__.py,sha256=sMVEOm5j6AZYnnEox5PHOUyZlL5TJjpsNMm5ATLx6ec,329
|
|
|
2
2
|
pqopen/auxcalc.py,sha256=P11Nu9pgJRoPYZDjLk-mXI6Ha02LoTH5bS9FdFTvC9M,2733
|
|
3
3
|
pqopen/eventdetector.py,sha256=NKZU7GbeorZdkYu3ET4lhMaeynw70GhIGO2p1xH4aTA,11962
|
|
4
4
|
pqopen/helper.py,sha256=0msrm6i1v8jj2Z5X8F7wDEW0KD5i91RBNZwPJC05YrA,2533
|
|
5
|
-
pqopen/powerquality.py,sha256=
|
|
6
|
-
pqopen/powersystem.py,sha256=
|
|
5
|
+
pqopen/powerquality.py,sha256=Cg7rwXOo3S63idE4XmrlC8CXHgGHbqI6-Urmhlg6ySc,16558
|
|
6
|
+
pqopen/powersystem.py,sha256=1Fi5SbS4PsUNz3hANjJBzTNtuM5bvQ6Oivae80K6RXI,52415
|
|
7
7
|
pqopen/storagecontroller.py,sha256=8JkeRX3HDWGFR40wO1ejxctQp53eMgEtsJMbOl7ea1Y,33468
|
|
8
8
|
pqopen/zcd.py,sha256=olJZsHRd1CjU65vysc2emR5wFGMkayIWdUEDNE8jfIc,6253
|
|
9
|
-
pqopen_lib-0.
|
|
10
|
-
pqopen_lib-0.
|
|
11
|
-
pqopen_lib-0.
|
|
12
|
-
pqopen_lib-0.
|
|
9
|
+
pqopen_lib-0.9.0.dist-info/METADATA,sha256=-UoUljXNQMLQUuR0GE_bBZpBY_sdBl5k5G1ZZ8GCwOw,4787
|
|
10
|
+
pqopen_lib-0.9.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
11
|
+
pqopen_lib-0.9.0.dist-info/licenses/LICENSE,sha256=yhYwu9dioytbAvNQa0UBwaBVcALqiOoBViEs4HLW6aU,1064
|
|
12
|
+
pqopen_lib-0.9.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|