pqopen-lib 0.7.8__py3-none-any.whl → 0.8.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/powersystem.py +124 -15
- pqopen/zcd.py +3 -5
- {pqopen_lib-0.7.8.dist-info → pqopen_lib-0.8.0.dist-info}/METADATA +1 -1
- {pqopen_lib-0.7.8.dist-info → pqopen_lib-0.8.0.dist-info}/RECORD +6 -6
- {pqopen_lib-0.7.8.dist-info → pqopen_lib-0.8.0.dist-info}/WHEEL +0 -0
- {pqopen_lib-0.7.8.dist-info → pqopen_lib-0.8.0.dist-info}/licenses/LICENSE +0 -0
pqopen/powersystem.py
CHANGED
|
@@ -88,7 +88,9 @@ class PowerSystem(object):
|
|
|
88
88
|
"mains_signaling_tracer": {},
|
|
89
89
|
"debug_channels": False,
|
|
90
90
|
"energy_channels": {},
|
|
91
|
-
"one_period_fundamental":
|
|
91
|
+
"one_period_fundamental": 0,
|
|
92
|
+
"rms_trapz_rule": False,
|
|
93
|
+
"pmu_calculation": False}
|
|
92
94
|
self._prepare_calc_channels()
|
|
93
95
|
self.output_channels: Dict[str, DataChannelBuffer] = {}
|
|
94
96
|
self._last_processed_sidx = 0
|
|
@@ -100,6 +102,7 @@ class PowerSystem(object):
|
|
|
100
102
|
self._last_zc_frac = 0.0
|
|
101
103
|
self._calculation_mode = "NORMAL"
|
|
102
104
|
self._last_known_freq = self.nominal_frequency
|
|
105
|
+
self._fund_freq_list = np.zeros(1)
|
|
103
106
|
self._channel_update_needed = False
|
|
104
107
|
|
|
105
108
|
|
|
@@ -107,7 +110,8 @@ class PowerSystem(object):
|
|
|
107
110
|
self._calc_channels = {"half_period": {"voltage": {}, "current": {}, "power": {}, "_debug": {}},
|
|
108
111
|
"one_period": {"voltage": {}, "current": {}, "power": {}, "_debug": {}},
|
|
109
112
|
"one_period_ovlp": {"voltage": {}, "current": {}, "power": {}, "_debug": {}},
|
|
110
|
-
"multi_period": {"voltage": {}, "current": {}, "power": {}, "energy": {}, "_debug": {}}
|
|
113
|
+
"multi_period": {"voltage": {}, "current": {}, "power": {}, "energy": {}, "_debug": {}},
|
|
114
|
+
"pmu": {"voltage": {}, "current": {}, "power": {}, "_debug": {}}}
|
|
111
115
|
|
|
112
116
|
def add_phase(self, u_channel: AcqBuffer, i_channel: AcqBuffer = None, name: str = ""):
|
|
113
117
|
"""
|
|
@@ -214,13 +218,33 @@ class PowerSystem(object):
|
|
|
214
218
|
self._features["energy_channels"] = {"persist_file": persist_file, "energy_counters": energy_counters}
|
|
215
219
|
self._channel_update_needed = True
|
|
216
220
|
|
|
217
|
-
def enable_one_period_fundamental(self):
|
|
221
|
+
def enable_one_period_fundamental(self, freq_agg_cycles: int = 50):
|
|
218
222
|
"""
|
|
219
223
|
Enables the calculation of one (single) period fundamental values
|
|
220
224
|
"""
|
|
221
|
-
self._features["one_period_fundamental"] =
|
|
225
|
+
self._features["one_period_fundamental"] = freq_agg_cycles
|
|
226
|
+
self._fund_freq_list = np.zeros(freq_agg_cycles)
|
|
222
227
|
self._channel_update_needed = True
|
|
223
228
|
|
|
229
|
+
def enable_rms_trapz_rule(self):
|
|
230
|
+
"""
|
|
231
|
+
Enables the trapezoidal integration rule for rms calculation
|
|
232
|
+
"""
|
|
233
|
+
self._features["rms_trapz_rule"] = True
|
|
234
|
+
|
|
235
|
+
def enable_pmu_calculation(self):
|
|
236
|
+
"""
|
|
237
|
+
Enables the calculation of equidistant PMU values
|
|
238
|
+
"""
|
|
239
|
+
if not self._features["nper_abs_time_sync"]:
|
|
240
|
+
logger.warning("To enable pmu_calculation, nper_abs_time_sync must be enabled first.")
|
|
241
|
+
return False
|
|
242
|
+
self._features["pmu_calculation"] = True
|
|
243
|
+
self._channel_update_needed = True
|
|
244
|
+
self._pmu_last_processed_sidx = 0
|
|
245
|
+
self._pmu_last_processed_ts_us = 0
|
|
246
|
+
self._pmu_time_increment_us = int(1_000_000 / self.nominal_frequency)
|
|
247
|
+
|
|
224
248
|
def _resync_nper_abs_time(self, zc_idx: int):
|
|
225
249
|
if not self._features["nper_abs_time_sync"]:
|
|
226
250
|
return None
|
|
@@ -269,6 +293,8 @@ class PowerSystem(object):
|
|
|
269
293
|
self._calc_channels["multi_period"]["energy"]["w_pos"].last_sample_value = self._features["energy_channels"]["energy_counters"].get("W_pos", 0.0)
|
|
270
294
|
self._calc_channels["multi_period"]["energy"]["w_neg"] = DataChannelBuffer('W_neg', agg_type='max', unit="Wh", dtype=np.float64)
|
|
271
295
|
self._calc_channels["multi_period"]["energy"]["w_neg"].last_sample_value = self._features["energy_channels"]["energy_counters"].get("W_neg", 0.0)
|
|
296
|
+
if self._features["pmu_calculation"]:
|
|
297
|
+
self._calc_channels["pmu"]["power"]["freq"] = DataChannelBuffer('Freq_pmu', agg_type='mean', unit="Hz")
|
|
272
298
|
|
|
273
299
|
for agg_interval, phys_types in self._calc_channels.items():
|
|
274
300
|
for phys_type, calc_type in phys_types.items():
|
|
@@ -320,30 +346,34 @@ class PowerSystem(object):
|
|
|
320
346
|
self._zero_crossings.append(actual_zc)
|
|
321
347
|
if self._zero_cross_counter <= 1:
|
|
322
348
|
continue
|
|
323
|
-
# Calculate Frequency
|
|
324
|
-
frequency = self._samplerate/(self._zero_crossings[-1] + actual_zc_frac - self._zero_crossings[-2] - self._last_zc_frac)
|
|
325
|
-
self._last_zc_frac = actual_zc_frac
|
|
326
349
|
# Add actual zero cross counter to debug channel if enabled
|
|
327
350
|
if "pidx" in self._calc_channels["one_period"]['_debug']:
|
|
328
351
|
self._calc_channels["one_period"]['_debug']['pidx'].put_data_single(self._zero_crossings[-1], self._zero_cross_counter)
|
|
329
352
|
# Process one period calculation, start with second zc
|
|
330
|
-
self._process_one_period(self._zero_crossings[-2], self._zero_crossings[-1],
|
|
353
|
+
self._process_one_period(self._zero_crossings[-2], self._zero_crossings[-1], actual_zc_frac)
|
|
354
|
+
self._last_zc_frac = actual_zc_frac
|
|
331
355
|
if ((self._zero_cross_counter-1) % self.nper) == 0 and (self._zero_cross_counter > self.nper):
|
|
332
356
|
# Process multi-period
|
|
333
357
|
self._process_multi_period(self._zero_crossings[-self.nper - 1], self._zero_crossings[-1])
|
|
334
358
|
self._resync_nper_abs_time(-1)
|
|
335
359
|
self._process_fluctuation_calc(self._zero_crossings[-self.nper - 1], self._zero_crossings[-1])
|
|
360
|
+
|
|
361
|
+
# Process fixed-time (PMU) channels
|
|
362
|
+
self._process_pmu_calc(self._zero_crossings[-1])
|
|
336
363
|
|
|
337
364
|
self._last_processed_sidx = stop_acq_sidx
|
|
338
365
|
|
|
339
|
-
def _process_one_period(self, period_start_sidx: int, period_stop_sidx: int,
|
|
366
|
+
def _process_one_period(self, period_start_sidx: int, period_stop_sidx: int, actual_zc_frac: float= 0):
|
|
340
367
|
"""
|
|
341
368
|
Processes data for a single period, calculating voltage, current, and power.
|
|
342
369
|
|
|
343
370
|
Parameters:
|
|
344
371
|
period_start_sidx: Start sample index of the period.
|
|
345
372
|
period_stop_sidx: Stop sample index of the period.
|
|
373
|
+
frequency: Fundamental frequency
|
|
346
374
|
"""
|
|
375
|
+
# Calculate Frequency
|
|
376
|
+
frequency = self._samplerate/(period_stop_sidx + actual_zc_frac - period_start_sidx - self._last_zc_frac)
|
|
347
377
|
self._calc_channels["one_period"]['power']['freq'].put_data_single(period_stop_sidx, frequency)
|
|
348
378
|
if "sidx" in self._calc_channels["one_period"]['_debug']:
|
|
349
379
|
self._calc_channels["one_period"]['_debug']['sidx'].put_data_single(period_stop_sidx, period_stop_sidx)
|
|
@@ -363,9 +393,30 @@ class PowerSystem(object):
|
|
|
363
393
|
u_values = phase._u_channel.read_data_by_index(phase_period_start_sidx, phase_period_stop_sidx)
|
|
364
394
|
if self._features["mains_signaling_tracer"]:
|
|
365
395
|
msv_edge, msv_value = phase._mains_signaling_tracer.process(u_values[::10])
|
|
396
|
+
if self._features["one_period_fundamental"]:
|
|
397
|
+
# Use sample-discrete frequency, not the exact one for full cycle
|
|
398
|
+
u_values_sync = phase._u_channel.read_data_by_index(period_start_sidx, period_stop_sidx)
|
|
399
|
+
self._fund_freq_list = np.roll(self._fund_freq_list,-1)
|
|
400
|
+
self._fund_freq_list[-1] = self._samplerate/len(u_values_sync)
|
|
401
|
+
mean_freq = self._fund_freq_list[self._fund_freq_list>0].mean()
|
|
402
|
+
fund_amp, fund_phase = calc_single_freq(u_values_sync, mean_freq, self._samplerate)
|
|
366
403
|
for phys_type, output_channel in phase._calc_channels["one_period"]["voltage"].items():
|
|
367
404
|
if phys_type == "trms":
|
|
368
|
-
|
|
405
|
+
if self._features["rms_trapz_rule"]:
|
|
406
|
+
add_start_idx_sample = 1 if self._last_zc_frac < 0 else 0
|
|
407
|
+
add_stop_idx_sample = 1 if actual_zc_frac > 0 else 0
|
|
408
|
+
u_trapz_values = phase._u_channel.read_data_by_index(phase_period_start_sidx-add_start_idx_sample, phase_period_stop_sidx+add_stop_idx_sample)
|
|
409
|
+
sample_points = np.arange(len(u_values), dtype=np.float64)
|
|
410
|
+
if add_start_idx_sample:
|
|
411
|
+
u_trapz_values[0] = (u_trapz_values[1] - u_trapz_values[0])*(1+self._last_zc_frac) + u_trapz_values[0]
|
|
412
|
+
sample_points = np.insert(sample_points,0,self._last_zc_frac)
|
|
413
|
+
if add_stop_idx_sample:
|
|
414
|
+
u_trapz_values[-1] = (u_trapz_values[-1] - u_trapz_values[-2])*self._last_zc_frac + u_trapz_values[-2]
|
|
415
|
+
sample_points = np.insert(sample_points,len(sample_points),sample_points[-1]+actual_zc_frac)
|
|
416
|
+
integral = np.trapezoid(np.power(u_trapz_values,2), sample_points)
|
|
417
|
+
u_rms = np.sqrt(integral * frequency / self._samplerate)
|
|
418
|
+
else:
|
|
419
|
+
u_rms = np.sqrt(np.mean(np.power(u_values, 2)))
|
|
369
420
|
output_channel.put_data_single(phase_period_stop_sidx, u_rms)
|
|
370
421
|
if phys_type == "msv_bit":
|
|
371
422
|
if msv_edge is not None:
|
|
@@ -375,9 +426,10 @@ class PowerSystem(object):
|
|
|
375
426
|
if phys_type == "slope":
|
|
376
427
|
output_channel.put_data_single(phase_period_stop_sidx, np.abs(np.diff(u_values)).max())
|
|
377
428
|
if phys_type == "fund_rms":
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
output_channel.put_data_single(
|
|
429
|
+
output_channel.put_data_single(period_stop_sidx, fund_amp)
|
|
430
|
+
if phys_type == "fund_phi":
|
|
431
|
+
output_channel.put_data_single(period_stop_sidx, pq.normalize_phi(np.rad2deg(fund_phase+np.pi/2)))
|
|
432
|
+
|
|
381
433
|
for phys_type, output_channel in phase._calc_channels["half_period"]["voltage"].items():
|
|
382
434
|
if phys_type == "trms":
|
|
383
435
|
# First half period
|
|
@@ -544,6 +596,52 @@ class PowerSystem(object):
|
|
|
544
596
|
self._pst_last_calc_sidx = stop_sidx
|
|
545
597
|
self._pst_next_round_ts = floor_timestamp(stop_ts, self._pst_interval_sec, ts_resolution="us")+self._pst_interval_sec*1_000_000
|
|
546
598
|
|
|
599
|
+
def _process_pmu_calc(self, stop_sidx: int):
|
|
600
|
+
"""
|
|
601
|
+
Process data to calculate PMU (Phasor Measurement Unit) parameters.
|
|
602
|
+
|
|
603
|
+
Parameters:
|
|
604
|
+
stop_sidx: Stop sample index for calculation
|
|
605
|
+
|
|
606
|
+
Returns:
|
|
607
|
+
None
|
|
608
|
+
"""
|
|
609
|
+
if not self._features["pmu_calculation"]:
|
|
610
|
+
return None
|
|
611
|
+
# Read timestamps
|
|
612
|
+
start_sidx = int(self._pmu_last_processed_sidx - 1.5*self._samplerate / self.nominal_frequency)
|
|
613
|
+
start_sidx = max(0, start_sidx)
|
|
614
|
+
ts_us = self._time_channel.read_data_by_index(start_sidx, stop_sidx)
|
|
615
|
+
first_pmu_ts = (self._pmu_last_processed_ts_us + self._pmu_time_increment_us) if self._pmu_last_processed_ts_us > 0 else ts_us[0] - ts_us[0] % self._pmu_time_increment_us + self._pmu_time_increment_us
|
|
616
|
+
last_pmu_ts = ts_us[-1] - (ts_us[-1] % self._pmu_time_increment_us) - self._pmu_time_increment_us # convert until n-1
|
|
617
|
+
logger.debug(f"first_pmu_ts: {first_pmu_ts:d}, last_pmu_ts: {last_pmu_ts:d}, self._pmu_time_increment_us: {self._pmu_time_increment_us:d}")
|
|
618
|
+
wanted_pmu_ts = np.arange(first_pmu_ts, last_pmu_ts+1, self._pmu_time_increment_us, dtype=np.int64)
|
|
619
|
+
wanted_pmu_sidx = [int(np.searchsorted(ts_us, pmu_ts)+start_sidx) for pmu_ts in wanted_pmu_ts]
|
|
620
|
+
wanted_pmu_ts_map = dict(zip(wanted_pmu_sidx, wanted_pmu_ts))
|
|
621
|
+
real_pmu_ts_map = {pmu_sidx: int(ts_us[pmu_sidx - start_sidx]) for pmu_sidx in wanted_pmu_sidx}
|
|
622
|
+
ovlp_window_start = max(0, int(wanted_pmu_sidx[0] - 1.5*self._samplerate / self.nominal_frequency))
|
|
623
|
+
freq, sample_indices = self._calc_channels["one_period"]["power"]["freq"].read_data_by_acq_sidx(ovlp_window_start, stop_sidx)
|
|
624
|
+
|
|
625
|
+
if len(sample_indices) == 0:
|
|
626
|
+
return None
|
|
627
|
+
for phase in self._phases:
|
|
628
|
+
u_raw = phase._u_channel.read_data_by_index(ovlp_window_start, stop_sidx)
|
|
629
|
+
for pmu_sidx in wanted_pmu_sidx:
|
|
630
|
+
# Search for previous zc
|
|
631
|
+
zc_idx = np.searchsorted(sample_indices, pmu_sidx,side="left")
|
|
632
|
+
if zc_idx == len(sample_indices):
|
|
633
|
+
zc_idx -= 1
|
|
634
|
+
local_stop_idx = max(0, pmu_sidx - ovlp_window_start)
|
|
635
|
+
local_start_idx = max(0, local_stop_idx - int(np.round(self._samplerate/freq[zc_idx])))
|
|
636
|
+
fund_amp, fund_phase = calc_single_freq(u_raw[local_start_idx:local_stop_idx], freq[zc_idx], self._samplerate)
|
|
637
|
+
frac_sidx_phi_offset = (wanted_pmu_ts_map[pmu_sidx] - real_pmu_ts_map[pmu_sidx])/1e6*2*np.pi*freq[zc_idx]
|
|
638
|
+
phase._calc_channels["pmu"]["voltage"]["rms"].put_data_single(pmu_sidx, fund_amp)
|
|
639
|
+
phase._calc_channels["pmu"]["voltage"]["phi"].put_data_single(pmu_sidx, pq.normalize_phi(np.rad2deg(fund_phase+np.pi/2+frac_sidx_phi_offset)))
|
|
640
|
+
# TODO: Add Frequency PMU Channel as well??
|
|
641
|
+
# TODO: Add current channels?
|
|
642
|
+
self._pmu_last_processed_sidx = stop_sidx
|
|
643
|
+
self._pmu_last_processed_ts_us = last_pmu_ts
|
|
644
|
+
|
|
547
645
|
def _detect_zero_crossings(self, start_acq_sidx: int, stop_acq_sidx: int) -> List[float]:
|
|
548
646
|
"""
|
|
549
647
|
Detects zero crossings in the signal.
|
|
@@ -644,12 +742,13 @@ class PowerPhase(object):
|
|
|
644
742
|
Parameters:
|
|
645
743
|
features: Dict of features
|
|
646
744
|
"""
|
|
647
|
-
self._calc_channels = {"half_period": {}, "one_period": {}, "one_period_ovlp": {}, "multi_period": {}}
|
|
745
|
+
self._calc_channels = {"half_period": {}, "one_period": {}, "one_period_ovlp": {}, "multi_period": {}, "pmu": {}}
|
|
648
746
|
# Create Voltage Channels
|
|
649
747
|
self._calc_channels["half_period"]["voltage"] = {}
|
|
650
748
|
self._calc_channels["one_period"]["voltage"] = {}
|
|
651
749
|
self._calc_channels["one_period_ovlp"]["voltage"] = {}
|
|
652
750
|
self._calc_channels["multi_period"]["voltage"] = {}
|
|
751
|
+
self._calc_channels["pmu"]["voltage"] = {}
|
|
653
752
|
self._calc_channels["half_period"]["voltage"]["trms"] = DataChannelBuffer('U{:s}_hp_rms'.format(self.name), agg_type='rms', unit="V")
|
|
654
753
|
self._calc_channels["one_period"]["voltage"]["trms"] = DataChannelBuffer('U{:s}_1p_rms'.format(self.name), agg_type='rms', unit="V")
|
|
655
754
|
self._calc_channels["one_period"]["voltage"]["slope"] = DataChannelBuffer('U{:s}_1p_slope'.format(self.name), agg_type='max', unit="V/s")
|
|
@@ -677,8 +776,13 @@ class PowerPhase(object):
|
|
|
677
776
|
self._calc_channels["one_period"]["voltage"]["msv_mag"] = DataChannelBuffer('U{:s}_1p_msv'.format(self.name), agg_type='max', unit="V")
|
|
678
777
|
self._calc_channels["one_period"]["voltage"]["msv_bit"] = DataChannelBuffer('U{:s}_msv_bit'.format(self.name), unit="")
|
|
679
778
|
|
|
680
|
-
if "one_period_fundamental" in features and features["one_period_fundamental"]:
|
|
779
|
+
if "one_period_fundamental" in features and features["one_period_fundamental"] > 0:
|
|
681
780
|
self._calc_channels["one_period"]["voltage"]["fund_rms"] = DataChannelBuffer('U{:s}_1p_H1_rms'.format(self.name), agg_type='rms', unit="V")
|
|
781
|
+
self._calc_channels["one_period"]["voltage"]["fund_phi"] = DataChannelBuffer('U{:s}_1p_H1_phi'.format(self.name), agg_type='phi', unit="°")
|
|
782
|
+
|
|
783
|
+
if "pmu_calculation" in features and features["pmu_calculation"]:
|
|
784
|
+
self._calc_channels["pmu"]["voltage"]["rms"] = DataChannelBuffer('U{:s}_pmu_rms'.format(self.name), agg_type='rms', unit="V")
|
|
785
|
+
self._calc_channels["pmu"]["voltage"]["phi"] = DataChannelBuffer('U{:s}_pmu_phi'.format(self.name), agg_type='phi', unit="°")
|
|
682
786
|
|
|
683
787
|
# Create Current Channels
|
|
684
788
|
if self._i_channel:
|
|
@@ -686,6 +790,7 @@ class PowerPhase(object):
|
|
|
686
790
|
self._calc_channels["multi_period"]["current"] = {}
|
|
687
791
|
self._calc_channels["one_period"]["current"]["trms"] = DataChannelBuffer('I{:s}_1p_rms'.format(self.name), agg_type='rms', unit="A")
|
|
688
792
|
self._calc_channels["multi_period"]["current"]["trms"] = DataChannelBuffer('I{:s}_rms'.format(self.name), agg_type='rms', unit="A")
|
|
793
|
+
self._calc_channels["pmu"]["current"] = {}
|
|
689
794
|
self._calc_channels["one_period"]["power"] = {}
|
|
690
795
|
self._calc_channels["multi_period"]["power"] = {}
|
|
691
796
|
|
|
@@ -698,6 +803,10 @@ class PowerPhase(object):
|
|
|
698
803
|
self._calc_channels["multi_period"]["power"]['p_fund_mag'] = DataChannelBuffer('P{:s}_H1'.format(self.name), agg_type='mean', unit="W")
|
|
699
804
|
self._calc_channels["multi_period"]["power"]['q_fund_mag'] = DataChannelBuffer('Q{:s}_H1'.format(self.name), agg_type='mean', unit="var")
|
|
700
805
|
|
|
806
|
+
if "pmu_calculation" in features and features["pmu_calculation"]:
|
|
807
|
+
self._calc_channels["pmu"]["current"]["rms"] = DataChannelBuffer('I{:s}_pmu_rms'.format(self.name), agg_type='rms', unit="A")
|
|
808
|
+
self._calc_channels["pmu"]["current"]["phi"] = DataChannelBuffer('I{:s}_pmu_phi'.format(self.name), agg_type='phi', unit="°")
|
|
809
|
+
|
|
701
810
|
# Create Power Channels
|
|
702
811
|
self._calc_channels["one_period"]["power"]['p_avg'] = DataChannelBuffer('P{:s}_1p'.format(self.name), agg_type='mean', unit="W")
|
|
703
812
|
self._calc_channels["multi_period"]["power"]['p_avg'] = DataChannelBuffer('P{:s}'.format(self.name), agg_type='mean', unit="W")
|
pqopen/zcd.py
CHANGED
|
@@ -40,8 +40,7 @@ class ZeroCrossDetector:
|
|
|
40
40
|
self.samplerate = samplerate
|
|
41
41
|
|
|
42
42
|
# Design a Butterworth low-pass filter
|
|
43
|
-
|
|
44
|
-
self._filter_coeff = signal.iirfilter(2, normal_cutoff, btype='lowpass', ftype='butter')
|
|
43
|
+
self._filter_coeff = signal.iirfilter(2, self.f_cutoff, btype='lowpass', ftype='butter', fs=self.samplerate)
|
|
45
44
|
self._filter_zi = np.zeros(len(self._filter_coeff[0]) - 1)
|
|
46
45
|
|
|
47
46
|
self._last_filtered_sample = 0
|
|
@@ -51,9 +50,8 @@ class ZeroCrossDetector:
|
|
|
51
50
|
self._last_zc_n_val = None
|
|
52
51
|
|
|
53
52
|
# Calculate the filter delay in samples
|
|
54
|
-
w, h = signal.freqz(self._filter_coeff[0], self._filter_coeff[1],
|
|
55
|
-
|
|
56
|
-
self.filter_delay_samples = np.angle(h)[0] / (2 * np.pi) * self.samplerate / self.f_cutoff
|
|
53
|
+
w, h = signal.freqz(self._filter_coeff[0], self._filter_coeff[1], worN=[self.f_cutoff], fs=self.samplerate)
|
|
54
|
+
self.filter_delay_samples = np.angle(h)[0] / (2 * np.pi) * self.samplerate / self.f_cutoff - 1 # due to adding sample in front for continuity
|
|
57
55
|
self.filtered_data = []
|
|
58
56
|
|
|
59
57
|
def process(self, data: np.ndarray)-> list:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pqopen-lib
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.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
|
|
@@ -3,10 +3,10 @@ pqopen/eventdetector.py,sha256=NKZU7GbeorZdkYu3ET4lhMaeynw70GhIGO2p1xH4aTA,11962
|
|
|
3
3
|
pqopen/goertzel.py,sha256=JhehuEj-xNnwQEh4Ti8dXiGvfDmxbdEoaxIsFswZNcM,2008
|
|
4
4
|
pqopen/helper.py,sha256=bM_wDck5OfeEy96U_2FjCwZuLZRPYyKVeiYD3-vzP6M,1761
|
|
5
5
|
pqopen/powerquality.py,sha256=Qwyaj7BQqQPRivei140mv-Leh6u9uIQzViKLOY7bHyw,17877
|
|
6
|
-
pqopen/powersystem.py,sha256=
|
|
6
|
+
pqopen/powersystem.py,sha256=unaQLrCb5V1l6kjX6R186MflAV9BsWVeJd_Sc8azsq8,48895
|
|
7
7
|
pqopen/storagecontroller.py,sha256=AhVaPgIh4CBKKMJm9Ja0dOjVd4dLppWprxeeg3vrmAk,31266
|
|
8
|
-
pqopen/zcd.py,sha256=
|
|
9
|
-
pqopen_lib-0.
|
|
10
|
-
pqopen_lib-0.
|
|
11
|
-
pqopen_lib-0.
|
|
12
|
-
pqopen_lib-0.
|
|
8
|
+
pqopen/zcd.py,sha256=cqGURF6dtvdYanI-vby95Gn9Kvh8F4cfKCqUFlyM15Y,5678
|
|
9
|
+
pqopen_lib-0.8.0.dist-info/METADATA,sha256=pvr3sXmlAPcGiEYp9KEqgcrZ1-qKEFkVrgxvRQQKB5E,4780
|
|
10
|
+
pqopen_lib-0.8.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
11
|
+
pqopen_lib-0.8.0.dist-info/licenses/LICENSE,sha256=yhYwu9dioytbAvNQa0UBwaBVcALqiOoBViEs4HLW6aU,1064
|
|
12
|
+
pqopen_lib-0.8.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|