Migration

1.0 to 1.1

Version 1.1 is source compatible with 1.0, but a few behaviours changed for camera streams and metadata.

Camera stream timeouts

A camera stream read that waits longer than wait_timeout now raises TimeoutError instead of ending the stream as if no more frames would arrive. The default timeout is 3 s. Iterating over a stream stops it on a timeout, while get_frame() leaves the stream running so the call can be retried.

Code that treated an early end of the stream as “the camera stopped” should catch TimeoutError instead:

from qtec_hv_sdk import control

cam = control.Camera("<camera_ip>")

try:
    for meta, frame in cam.to_hs_image().stream():
        ...
except TimeoutError:
    print("The camera stopped delivering frames")

Camera stream buffering

In 1.0 the frame queue between the camera and the consumer was unbounded, so a slow consumer grew memory without limit. Camera streams now buffer 20 frames and stall the camera when the buffer is full. Frames the camera drops while stalled are reported in hs.FrameMeta.dropped, and counted by dropped(). Behaviour is unchanged when the consumer keeps up.

Buffering is configured on the camera with a hs.control.StreamOptions in stream_options, and applies to streams started afterwards. Use on_full="evict" to discard the oldest buffered frame instead of stalling the camera:

import datetime
from qtec_hv_sdk import control

cam = control.Camera("<camera_ip>")
cam.stream_options = control.StreamOptions(
    capacity=50,
    on_full="evict",
    wait_timeout=datetime.timedelta(seconds=5),
)

Measurement units

Camera images now report hs.RadiometricMeta.unit as hs.MeasurementUnit.Dn instead of hs.MeasurementUnit.Raw, and set hs.DataProductsMeta.output_data to hs.OutputDataType.RawData. Code comparing the unit to Raw should check for Dn instead.

ENVI files written from a camera therefore contain measurement units = DN, which 1.0 readers do not recognise.

hs.MeasurementUnit.Raw, hs.MeasurementUnit.Absorbance and hs.MeasurementUnit.Arbitrary are deprecated, and assigning them to hs.RadiometricMeta.unit or hs.MeasurementInfo.unit raises a DeprecationWarning:

Existing files using these units still load.

import qtec_hv_sdk as hs

meta = img.meta
meta.radiometric = hs.RadiometricMeta(unit=hs.MeasurementUnit.Dn)
meta.data_products = hs.DataProductsMeta(output_data=hs.OutputDataType.RawData)

Scale factor

hs.RadiometricMeta.scaling is deprecated in favour of hs.EncodingMeta.scale_factor:

# 1.0
scale = img.meta.radiometric.scaling

# 1.1
scale = img.meta.encoding.scale_factor

The ENVI reader still accepts the old measurement scaling key. The writer stores the value under the reflectance scale factor key, so a header written by 1.1 stores it under a different key than 1.0 did.

ENVI metadata

The ENVI reader and writer now handle all metadata fields. In 1.0, many standard ENVI fields were only available through the extra metadata, and some were lost when writing. Code that read standard fields with hs.ImageMeta.extra() should use the corresponding typed metadata field instead.

0.10.2 to 1.0.0

Version 1.0.0 renames several public Python and C APIs to remove the redundant HS and HSI prefixes and to make camera and stage-control APIs explicit. Most image processing code keeps the same lazy execution model: build pipelines first, then evaluate them with operations such as hs.Image.to_numpy(), hs.Image.resolve(), hs.Image.stream(), or hs.write().

Python package and type names

The Python package was imported as hsi in 0.10.2. It is now imported as qtec_hv_sdk:

# 0.10.2
import hsi
# 1.0.0
import qtec_hv_sdk as hs

img = hs.open("input.hdr")
result = img.ensure_dtype(hs.float32).to_numpy()

The v1 names are shorter and match the current documentation.

0.10.2 name

1.0.0 name

Notes

hsi.HSImage

hs.Image

Main image and pipeline type.

hsi.InMemoryCube

hs.ImageArray

In-memory image data.

hsi.HSIFile

hs.ImageFile

File-backed image data.

hsi.HSIHeader

hs.ImageMeta

Metadata now groups fields by topic, see Metadata.

hsi.HSCamera

hs.control.Camera

Now exposed from the control submodule.

hsi.StageController

hs.control.StageController

Now exposed from the control submodule.

hsi.list_devices

hs.control.list_devices()

Now exposed from the control submodule.

The old names are not available in 1.0.0, so imports and type annotations have to be updated.

Removed and added Python APIs

The write_header function was removed. Metadata should be carried by the image object and written together with image data through hs.write().

Images now expose a deterministic structural UUID for pipeline nodes through the hs.Image.uuid property:

import qtec_hv_sdk as hs

img = hs.open("input.hdr")
print(img.uuid)

The Python package also ships with .pyi type stubs. Type checkers and editors can use these stubs to find old imports, old type names, and calls to removed functions during migration.

Camera and stage control

Camera and stage APIs now live in the control submodule. Import the submodule from the package, since qtec_hv_sdk.control cannot be imported directly:

# 0.10.2
from hsi import HSCamera, StageController

cam = HSCamera("<camera_ip>")
stage = StageController("<camera_ip>")
# 1.0.0
from qtec_hv_sdk import control

cam = control.Camera("<camera_ip>")
stage = control.StageController("<camera_ip>")

The stage-controller lens-size helper has been replaced by explicit optical parameters:

from qtec_hv_sdk import control

stage = control.StageController("<camera_ip>", fps=30.0, distance=150.0)
stage.focal_length = 12.0      # mm
stage.object_distance = 258.0  # mm
stage.pixel_pitch = 5.0        # um
stage.slit_width = 20.0        # um

These values are used to derive the pixel and slit field of view used by the stage controller. Code that relied on the old lens-size helper should set the explicit optical parameters instead.

Errors

Python code receives standard Python exceptions: ValueError for invalid input and processing errors, IOError for camera and scanner errors such as a camera that cannot be found, and TimeoutError for camera timeouts.

In Rust, the error types were renamed: HSIError is now Error, and CameraError is now ControlError to cover both camera and stage failures. Missing camera controls report the ControlNotFound variant.

C FFI names

The C API follows the same v1 naming cleanup. Update public image and metadata types and function prefixes:

0.10.2 C API

1.0.0 C API

hv_hs_image_t

hv_image_t

hv_hs_image_*

hv_image_*

hv_hsi_header_t

hv_image_meta_t

hv_hsi_header_*

hv_image_meta_*

The v1 metadata struct groups public metadata fields by topic, including camera, spectral, spatial, radiometric, temporal, calibration, sensor, encoding, and display metadata. See the C metadata reference for the current hv_image_meta_t layout.

Metadata

The image metadata is now read with hs.Image.meta instead of img.header, and its type is hs.ImageMeta. It keeps core shape and layout information directly and groups richer metadata into focused objects.

# 0.10.2
header = img.header
wavelengths = header.wavelength_info
byte_order = header.byte_order
# 1.0.0
meta = img.meta
wavelengths = meta.spectral.wavelengths
byte_order = meta.encoding.byte_order

The legacy accessors byte_order, capture, default_bands, measurement_info and wavelength_info are still available on hs.ImageMeta for older code. Prefer the grouped metadata objects, such as spectral and encoding, in new code.

Versioned documentation

The documentation is now built for both current and previous SDK versions. Keep the 0.10.2 documentation available while migrating if you need to compare old examples with the v1 API.