visualdynamics.io.unv¶
unv
¶
Importer for Universal Files (.unv/.uff), per the SDRL specifications (https://www.ceas3.uc.edu/sdrluff/ — local copies in docs/uff_spec).
Geometry datasets supported:
- 164 units: length/force/temperature factors; per spec, file values are DIVIDED by the factors to get SI, so a 164 makes the import unit-aware
- 15 nodes (old single-precision form, one line per node)
- 2411 nodes (double precision: 4I10 record + 3D25.16 record per node)
- 82 tracelines: node list where 0 means pen-up (move without drawing); pen-up runs are split into separate polylines
- 2412 elements: FE descriptor codes match visualdynamics's element vocabulary; beam- class descriptors carry an extra orientation record before the nodes
- 58b the binary form of 58: the same eleven ASCII header records, then
the values as raw floats. Read in either byte order at either
precision, and written little-endian IEEE 754 doubles when
save(..., binary=True)is asked for. Only IEEE 754 floats are decoded — DEC VMS and IBM 5/370 floats are refused by name rather than read as IEEE, which would return wrong numbers instead of failing. - 58 functions at nodal DOFs (time histories, spectra, FRFs, PSDs). The ordinate scale to SI comes from the axis data-type unit exponents combined with the 164 factors; without a 164, unit-bearing data imports unit-less unless ordinate_unit is declared. Functions are grouped by type into one visualdynamics data object per type; unsupported function types (coherence, etc.) are skipped.
A file with several objects (e.g. geometry + FRFs) returns a dict keyed 'geometry', 'time', 'spectrum', 'frf', 'psd'; a file with one object returns it directly. Unrecognized datasets are skipped (a UNV file is a stream of independent datasets delimited by '-1' lines).
Classes:
| Name | Description |
|---|---|
Binary |
The binary half of a dataset 58b: how to read it, and it. |
Functions:
| Name | Description |
|---|---|
iter_datasets |
Yield (dataset_number, record_lines, payload) for each dataset. |
handles_binary |
Only function data, because only dataset 58 has a binary form. |
save |
Write a geometry or a data array as a universal file. |
save_binary |
|
Classes¶
Binary
dataclass
¶
The binary half of a dataset 58b: how to read it, and it.
order and fp_format are the marker line's own fields, carried
with the bytes rather than read again from somewhere else — a blob
whose byte order has been separated from it is a blob that will one
day be decoded by the wrong one.
Functions:¶
iter_datasets
¶
Yield (dataset_number, record_lines, payload) for each dataset.
payload is None for an ordinary ASCII dataset and a Binary for
a binary one (dataset 58b), whose eleven header records stay ASCII
and come back in record_lines like any other.
Bytes rather than text, and a cursor rather than splitlines,
because a binary payload is not text: it contains newlines that are
float bytes, and it can contain the byte pattern of a '-1' delimiter
line. Splitting first and interpreting afterwards would cut a
dataset in half at a number that happened to look like a delimiter.
The payload is therefore taken by the byte count the marker line
declares, and never scanned.
Source code in src/visualdynamics/io/unv.py
handles_binary
¶
Only function data, because only dataset 58 has a binary form.
A geometry or a mode shape offered as "binary" would write exactly
the ASCII file the other exporter writes, under a name promising
something else — 2411, 82, 2412 and 55 have no b variant, and
inventing one would produce a file nothing else reads. Caught by
test_shapes_can_be_written_to_every_format_that_holds_them, which
already knew what a ShapeSet may be written as (2026-08-25).
Source code in src/visualdynamics/io/unv.py
save
¶
save(
obj: Any,
path: str | PathLike,
unit_system: UnitSystem | None = None,
binary: bool = False,
) -> None
Write a geometry or a data array as a universal file.
Geometry goes out as 2420 coordinate systems, 2411 nodes, 82 tracelines and 2412 elements; data as one dataset 58 per record; mode shapes as one dataset 55 per mode.
Shape values stay in each node's own displacement system, which is what dataset 55 means by them — the coordinate systems written alongside are what make that readable.
A dataset 164 declaring SI is written when the object's units have been defined, and left out when they have not. Stored values are SI either way, but only in the first case is that a fact about the data rather than an assumption — and a file that says so reads back with its units, where one that does not reads back unit-less.
binary writes the functions as dataset 58b instead of 58: the
same eleven ASCII header records, and then the values as raw IEEE
754 doubles rather than as 13.5E text. It is roughly a third of
the size and it is exact — a written-and-read float comes back the
float that went in, where five decimal places do not. Only the
functions change form; geometry, mode shapes and the units dataset
have no binary variant and go out as they always do.
Source code in src/visualdynamics/io/unv.py
save_binary
¶
save_binary(
obj: Any,
path: str | PathLike,
unit_system: UnitSystem | None = None,
) -> None
save in the binary form — the registry's entry for 58b.
A separate exporter rather than a checkbox on the other one, because the Export menu is a list of formats and this is one: a file another tool will or will not read. Choosing by suffix still gets the ASCII form, which is the one to hand a stranger.