Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased
0.8.0 - 2026-07-02
Fixed
equser plotnow works. It previously raised aTypeErroron every invocation.-o/--outputsets the output directory for the generated SVG file(s); without it, plots are written alongside the input file.equser pmon <cmd>now forwards option flags (e.g.-c config.yaml,--remove) to the subcommand instead of rejecting them.- CPOW neutral-current (
IN) scaling.load_cpow_scaled()now divides the neutral channel by the neutral-CT ratio (default 30, overridable via aneutral_ct_ratiofile-metadata key), consistent with the plotter. The loader previously returnedIN30x too high. Behavior change:INmagnitude fromload_cpow_scaled()is now ~30x smaller for int32 files. - The waveform plotter now reads scaling metadata from the Arrow schema (where producer files carry it) rather than the Parquet footer, so int32 waveforms are scaled correctly.
parse_start_time()accepts ISO 8601 timestamps without a fractional-seconds component.- Importing
equserno longer reconfigures the root logger as a side effect. Logging is opt-in viaequser.utils.logging.configure_logging()(the CLI enables it automatically).
Added
equser.data.get_cpow_scales(): the shared helper that returns the voltage, phase-current, and neutral-current scale factors for a CPOW table. Used by bothload_cpow_scaled()and the plotters.- Continuous integration (lint, tests) and release-time packaging checks.
Changed
find_zero_crossings()is vectorized, which is substantially faster on long CPOW records.equser snapshotdefaults to port 80, matching theGatewayClientdefault.
[0.0.7] - 2026-06-22
Added
- Bundled top-level
welcome.ipynbnotebook — the entry point for EQ Lab (JupyterLab on a gateway). Checks the environment, shows where CPOW/PMon data lives, runs a smallload_cpow_scaled+GatewayClientexample, and links the tutorial/analysis notebooks. Picked up automatically bydescribe_notebooks()and copied byeq lab install/equser notebooks(category: root).
[0.0.5] - 2026-06-16
Removed
- Removed the deprecated
SynapseClientalias and its__getattr__hooks fromequser.apiandequser.api.client(deprecated in 0.0.4). ImportingSynapseClientnow raises; useGatewayClient.
Added
equser notebooks launchcopies the bundled notebooks to a directory (default./equser-notebooks) and opens JupyterLab there, andequser notebooks path [NAME]prints the install location of the notebooks (or one notebook). New public helperequser.notebooks.get_notebooks_dir()returns the bundled notebooks directory. These address the difficulty of finding the notebooks insidesite-packagesafterpip install.- README “Reference notebooks” section documenting how to locate, copy, and launch the bundled notebooks (CLI and in-notebook one-liner).
Changed
GatewayClient.list_devices()andGatewayClient.get_events()now unwrap the gateway’s JSON envelope and return the bare list. The gateway returns{"timezone", "devices": [...]}and{"events": [...], "count"}respectively; the client previously returned the whole dict, solen()/indexing in the tutorials failed. Aligns with EQ gateway software v3.8.connect_spectral_stream()rewritten for the v3.8 spectral WebSocket. It now takeschannels(e.g.['VA', 'IA']),mode(cycle_aligned/fixed),cycles,fft_size,freq_min,freq_max, andinclude_phaseinstead of the olddevice_id/phase/update_rateparams (the stream is a broadcast consumer, not per-device). Binary messages are now pure Arrow IPC windows (yielded aspyarrow.Tablewith per-window metadata inschema.metadata); text messages remain JSON gap markers.- Bundled tutorials
03-backend-apiand04-live-streamingupdated toGatewayClient, the new spectral API, the{"files": [...]}list-files envelope, and the spectral control protocol (set_channels,set_mode, …). analysis/ai-event-analysisnotebook updated to the v3.8 RAG API: endpoints are under/api/v1(/api/v1/query,/api/v1/health), the request field istext(wasquery), and the answer is read fromcontent. The report cell now generates its report through/api/v1/querysince the standalone/reportendpoint is not exposed by the RAG server. Switched off the deprecatedSynapseClient.tutorials/01-parquet-filesnotebook: brand text updated to “EQ Wave”/“EQ gateway”.
[0.0.4] - 2026-05-02
Changed
- Renamed
SynapseClienttoGatewayClient. The class addresses one EQ gateway over REST; the new name matches the addressing model (the gateway is the unit you connect to). - Updated docstrings and brand text throughout (
equser.api,equser.api.streaming,equser.snapshot,equser.notebooks, README, CHANGELOG note for v0.0.1) to use “EQ gateway” for the hardware and reference EQ Coherence™ where the gateway-internal software is meant.
Deprecated
SynapseClientis now a deprecated module-level alias forGatewayClient. Importing it (fromequser.apiorequser.api.client) still resolves toGatewayClientso existing user code keeps working, but emits aDeprecationWarningso users see the migration signal. The alias and its__getattr__hooks will be removed in a future release; migrate tofrom equser.api import GatewayClient.
Fixed
connect_cpow_streamnow strips the 11-byte cycle header before Arrow IPC parse (commite3879fe). Resolves a parse error on real CPOW WebSocket streams that include the cycle header prefix.
[0.0.3] - 2026-04-23
Added
RELEASE.mddocumenting the PyPI release procedure.
Fixed
load_cpow_scaled()now reads scaling metadata (iscale,vscale,schema_version,topology,neutral_connected,start_time) from the Arrow schema. Production CPOW files carry these on the schema only; the previous implementation read the Parquet footer key-value map and silently returnediscale=1.0on those files.scripts/bump-version.pyandscripts/release.shnow look forequser/_version.pyin the correct location; previously both scripts referenced a non-existent repo-root path.
0.0.2 - 2026-04-11
Changed
load_cpow_scaled()now reads v3 schema metadata and returns additional keys:schema_version,topology, andneutral_connected.- CPOW channel arrays are now explicitly promoted to float64 before applying the scale factor, preserving the full 24-bit ADC dynamic range for v3 int32 files.
Added
CYCLE_START_CHANNELSconstant listing the optional v3 phase cycle-boundary columns (cycle_start_a,cycle_start_b,cycle_start_c).load_cpow_scaled()returnscycle_start_a,cycle_start_b, andcycle_start_cas numpy int64 arrays when those columns are present in the file. Values are nanoseconds since epoch; zero means no boundary at that sample.
0.0.1 - 2026-02-06
Initial public release. User toolkit for EQ Wave power quality data.
Modules
- equser.data - Load CPOW and PMon Parquet files with automatic scaling, timestamp parsing
- equser.analysis - Waveform analysis: zero-crossing detection, AC cycle extraction
- equser.api - REST and WebSocket clients for EQ gateways (requires
[analysis]; class was originally namedSynapseClient, renamed toGatewayClientin Unreleased;SynapseClientpreserved as a deprecated backward-compat alias) - equser.plotting - Static matplotlib plots for PMon and CPOW data (requires
[analysis]) - equser.pmon - Live sensor acquisition and Avro-to-Parquet conversion (requires
[daq]) - equser.core - YAML configuration loading, XDG-compliant path resolution
- equser.utils - Logging with optional color, DateTime with floor-division
- equser.notebooks - Bundled reference notebooks with list/copy API
- equser.widgets - Interactive file selector for JupyterLab (requires
[jupyter]) - equser.snapshot - Waveform capture via gateway WebSocket
Dependency Tiers
- Base: numpy, pyarrow, pyyaml, argcomplete, colorlog (data loading, analysis, CLI)
- [daq]: avro, fastavro (live sensor acquisition)
- [analysis]: matplotlib, requests, websocket-client (plotting + API)
- [jupyter]:
[analysis]+ jupyterlab, duckdb, ipywidgets, ipykernel, nbconvert - [full]: all of the above
CLI
equser pmon acquire- Start power monitoring from EQ Wave sensorequser pmon convert- Convert Avro files to Parquetequser plot- Plot PMon or CPOW data filesequser notebooks list- List bundled reference notebooksequser notebooks copy- Copy reference notebooks to a directoryequser snapshot- Capture live waveform data to a Parquet file