HaloViewer
A viewer and plotting toolkit for Halo Photonics wind lidar data
(.hpl files) covering the processed-product tree
(Proc/YYYY/YYYYMM/YYYYMMDD/*.hpl). Every kind found there is
plottable: the instrument-processed Processed Wind Profile (a
single scan's height/speed/direction profile, or many combined into a
height/time History image), and the raw regular-scan kinds --
VAD, Stare, Wind Profile and RHI -- each of which gets
a distance/time intensity+beta History image built from their raw
per-gate data (no instrument-processed profile of their own), plus two
single-scan views of radial velocity and beta: RHI (the scan's
points projected onto the vertical plane along the first ray's
azimuth) and PPI (projected onto the horizontal plane), each drawn
as dots or, optionally, filled by inverse-distance-weighted interpolation.
Any other kind found on disk is still listed (so you can see what's in
your data tree) but reported as not yet implemented.
Installation
Conda (recommended -- minimal footprint on top of miniconda)
conda env create -f environment.yml
conda activate haloviewer
This only adds numpy, pandas, matplotlib and scipy on top of a
base Python; the GUI toolkit (Tkinter) ships with the standard python
conda package on Linux, macOS and Windows, so nothing extra is needed
for the GUI itself. Tested against Python 3.9+ on Ubuntu 22.04, 24.04
and 26.04, macOS and Windows.
Plain pip
pip install -e .
(On some minimal Linux distributions Tkinter is a separate OS package,
e.g. sudo apt install python3-tk on Debian/Ubuntu -- not needed when
using the conda environment above, since conda's python package
already includes it.)
Version numbers
The version is derived from the git history by
setuptools-scm and written to
haloviewer/_version.py when the package is installed. To make a
release, tag it (e.g. git tag v0.2.0) and reinstall. Without git
metadata (e.g. installed from a zip) the version falls back to 0.1.0.
Static project information (author, licence, ...) is in
haloviewer/_metadata.py.
Contents
HaloViewer provides four ways to work with the data. Each has its own page in the full documentation (see below).
Graphic viewer -- haloviewer.
A Tkinter desktop application for browsing a Proc tree: pick a
directory, a file kind and a plot type (Profile, History, RHI or
PPI), then step through single files or whole time windows, with
adjustable height, distance and speed ranges.
haloviewer /path/to/Data/Proc
Command-line tool -- haloplot.
Plots files, directories or glob patterns straight to an image file,
without the GUI. File kind, plot mode and time range are inferred where
possible and can be set explicitly.
haloplot Proc/2026/202609 --kind RHI --start 24h -p rhi_24h.png
Sync tool -- halosync.
A separate GUI for selectively copying the Metek, Proc and Raw
trees from the lidar control PC to a backup or analysis disk. It skips
files that are already there, leaves out the file the lidar is still
writing, and can run on a fixed schedule.
halosync
Python API -- haloviewer.plot().
The same functionality as haloplot for scripts and notebooks. It
returns a matplotlib Figure for further customisation.
import haloviewer
fig = haloviewer.plot("Proc/2026/202609/20260919",
kind="Processed_Wind_Profile", start="24h")
Documentation
The full documentation (Sphinx, in docs/) describes each tool in
detail and includes the API reference generated from the docstrings.
Build it from the project root; the HTML ends up in build/html/:
pip install -e ".[docs]"
sphinx-build -b html docs build/html
Design
File structure
The code is layered so each piece can be used, tested and understood on its own:
| module | responsibility |
|---|---|
haloviewer.hpl |
.hpl file format parser (adapted from cdruee/python-readmet's hpl module) |
haloviewer.scan |
finds .hpl files under a root directory, classifies them by kind from the filename, indexes by timestamp |
haloviewer.data |
turns parsed files into plain numpy/pandas arrays ready to plot |
haloviewer.plotting |
pure matplotlib, no GUI toolkit imports: figure/axes creation and drawing functions |
haloviewer.api |
programmatic entry points (plot, plot_file, plot_files); plot also re-exported as haloviewer.plot |
haloviewer.cli |
command-line interface on top of api |
haloviewer.gui |
Tkinter desktop app; wires widgets to scan/data/plotting and contains no plotting logic itself |
haloviewer.halosync |
standalone data-sync GUI (halosync command); standard library only, independent of the other modules |
haloviewer._metadata |
static project information (name, author, licence, ...) |
haloviewer._version |
version number, generated by setuptools-scm at install time (not under version control) |
plotting.py never imports tkinter, and gui.py never calls
matplotlib drawing primitives directly -- it only calls functions in
plotting.py. This means the exact same plotting code is used by the
GUI, the CLI, and any script that imports haloviewer.api.
Extending to more scan kinds
Processed_Wind_Profile, VAD, Stare, Wind_Profile and RHI are
all implemented; a user-defined pattern (User1...User5 in the raw
.hpl header's Scan type) or a future Halo scan kind would follow
the same recipe:
- Add a reader to
data.pythat turns a parsedhpl.DataFile(or a set of them) into plain arrays. A regular scan file can usually reuseload_scan_historyandload_scan_pointsas they are. - Add drawing function(s) to
plotting.pythat take those arrays and axes/figure objects -- reusecreate_timeseries_figure's two stacked, colour-mapped panels (all History flavours) orcreate_scan_pair_figure's two side-by-side panels (the RHI/PPI views) if one of those shapes fits. - Register the kind's capabilities in
scan.KIND_CAPABILITIES(supported=True, its plot modes). - Wire the new mode(s) into
api.plot_file/plot_files, and intogui.HaloViewerApp._plot_kind(which of the five load/render pipelines applies) and_update_range_controls_enabled(which of Height/Distance/Speed/Fill make sense for it).
The GUI will then automatically offer that kind and mode as soon as it is discovered on disk -- no other GUI changes are needed.
Tests
pip install -e ".[dev]"
pytest
Licence
HaloViewer is licensed under the European Union Public Licence v1.2
(EUPL-1.2); see LICENSE for the full licence text.
haloviewer/hpl.py is adapted from the hpl module of
cdruee/python-readmet,
which is itself licensed under the EUPL-1.2.
Copyright
(c) 2026 Clemens Drüe, Universität Trier
Developed with support of Anthropic Claude Opus 5.5.
Release files for haloviewer 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| haloviewer-0.4.0.tar.gz | 529.5 kB | Details |
Release files / haloviewer-0.4.0.tar.gz
| Download URL | haloviewer-0.4.0.tar.gz |
|---|---|
| Size | 529.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
47619921de40a4893795063954d20a9a3177bb889d15508ee479b3c20eb1fe78
|
|
BLAKE2b-256 checksum How to use checksums |
42e1b5f7d5b8b5de884deca7d9d6b3df5929ffc8acd733955dca18e5c5fdcdd7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|