lvmio
Typed reader and writer for the LabVIEW Measurement (.lvm) file format, stdlib only.
Install
pip install lvmio
Usage
Write channels to a spec-faithful .lvm file and read them back:
from lvmio import Channel, LvmFile, Segment, read_lvm, write_lvm
channels = [
Channel("Voltage", [1.0, 2.0, 3.0], unit="V", delta_x=0.1),
Channel("Current", [0.5, 0.25, 0.125], unit="A", delta_x=0.1),
]
write_lvm("run.lvm", LvmFile(segments=[Segment(channels)]), operator="lab")
lvm = read_lvm("run.lvm")
first = lvm.segments[0].channels[0]
print(first.name, first.data) # Voltage [1.0, 2.0, 3.0]
write_lvm also accepts a bare list of Channel objects, a single Segment,
or a mapping of name to samples:
write_lvm("quick.lvm", {"x": [1.0, 2.0], "y": [3.0, 4.0]})
Keyword arguments override file header fields: operator, date, time,
separator ("Tab" or "Comma"), decimal_separator, and precision (the
number of decimal places used for numeric output).
Working with a parsed file
The parsed objects are frozen dataclasses with convenient access:
lvm = read_lvm("run.lvm")
segment = lvm.segments[0]
for channel in segment: # Segment iterates over its channels
print(channel.name, len(channel))
voltage = segment["Voltage"] # access a channel by name
axis = voltage.time_axis() # [x0, x0 + delta_x, ...], one value per sample
missing = segment.get("absent") # None when the channel is not present
Empty cells in the data (unconnected channels, or rows without a value) parse to
float('nan'), so every channel keeps one value per row and stays aligned with its
own time axis.
parse_lvm(text) parses a .lvm string already in memory; read_lvm(path) is the
path based convenience that calls it.
Command line
Installing the package adds an lvmio console command:
lvmio header run.lvm # file metadata, add --json for JSON
lvmio channels run.lvm # list the channels per segment
lvmio dump run.lvm --channel Voltage --time # one channel as CSV with its time axis
lvmio dump run.lvm --format json # all channels of a segment as JSON
cat run.lvm | lvmio header - # read from standard input
Errors go to standard error and the process exits with status 1. Run lvmio --help
or lvmio <command> --help for the full list of options.
Supported subset
The format has a file header block (LabVIEW Measurement, Writer_Version,
Separator, Decimal_Separator, Multi_Headings, X_Columns, Time_Pref,
Operator, Date, Time) followed by one or more data segments, each with its
own channel header and tab-delimited rows.
Covered:
- Tab and comma separators, and a configurable decimal separator (including the decimal comma and scientific notation that European LabVIEW writes).
- Single or multiple segments (
Multi_Headingsis set from the segment count). X_Columnsset toOne(a shared X axis fromX0andDelta_X) orNo. RealNofiles still carry an empty leading X column, and the reader handles that.- Per-channel
Y_Unit_Label,X_Dimension,X0andDelta_X. - The trailing
Commentcolumn on the data header, and comments on some rows. - Empty data cells, which become
float('nan').
Behaviour on the layouts LabVIEW writes is locked in by golden fixtures under
tests/fixtures/, generated by scripts/make_lvm_fixtures.py (each file says so in its
Description header), and cross-checked against the independent lvm_read package.
Out of scope for now: X_Columns set to Multi (one X column per channel) and
absolute-time X axes. These parse as plain columns but are not modelled.
Why
LabVIEW produces and consumes .lvm natively with its Write/Read To Measurement File
express VIs, and on the Python side lvm-read already reads the format well. Reading,
then, is a solved problem. What is missing is the writer: there is no maintained,
typed Python package that writes a .lvm file a LabVIEW VI will read back, which
otherwise means matching NI's header blocks and tab-delimited segments by hand.
lvmio fills that writer gap and keeps a small, correct reader alongside it as a
convenience, not as the novelty, so a round trip stays within one dependency-free
package. It uses the standard library only.
License
MIT. See LICENSE.
Links
- Website: https://lianes8studio.com
- GitHub: https://github.com/JaviLianes8
- LinkedIn: https://www.linkedin.com/in/jlianes/
Metadata
Release files for lvmio 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| lvmio-0.2.1.tar.gz | 18.2 kB | Without provenance | Details for lvmio-0.2.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| lvmio-0.2.1-py3-none-any.whl | Python 3 | none | any | Details for lvmio-0.2.1-py3-none-any.whl |
Total release size: 30.5 kB
Release files / lvmio-0.2.1.tar.gz
| Download URL | lvmio-0.2.1.tar.gz |
|---|---|
| Size | 18.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
471564b7dbca07046960fa565a58b5143086c9f3bb68dac85ad7533e2ba74f06
|
|
BLAKE2b-256 checksum How to use checksums |
ee642f3b6221e0ca1a8d20417408e4fae699d45e10c57e411124c984a63f740e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.2
|
Release files / lvmio-0.2.1-py3-none-any.whl
| Download URL | lvmio-0.2.1-py3-none-any.whl |
|---|---|
| Size | 12.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9a315b2af8ba3c4efe0e76a030cb24cce1b24cb5bdf18fdd27ccf8367d89cb65
|
|
BLAKE2b-256 checksum How to use checksums |
a10317b1339cd77d1e62ece940760734629ad5f150a86b744d7e850acd47abfc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.2
|
Security for lvmio 0.2.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.