Skip to content

Changelog

Unreleased

0.7.0 - 2026-09-15

Added

  • File-processing commands (transform, rename, drop, select, resize, impute, combine, replace, recompress) show a progress bar with frame count, elapsed and remaining time when run in a terminal
  • progress= keyword on Pipeline.run() and the operations functions: a callable receiving (frames_done, frames_total, path) after each input frame
  • transform --strict (and strict=True on Pipeline.run()) makes preflight warnings fail the run before anything is written

Changed

  • validate on directories pairs frames by GPS span across files instead of pairing whole files by their first frame, so two productions of the same data compare equal even when their file boundaries differ; a frame without a counterpart is reported as unmatched_frame (a whole file as unmatched_file, as before)
  • transform preflight warnings say where a missing channel was looked for: in the input, or after a named earlier stage

0.6.0 - 2026-09-14

Added

  • gwframe transform INPUT... -o DIR [STAGE [OPTIONS]]... applies a chain of rename, drop, select, impute, fill-gaps and resize stages in a single read/write pass; --compression/--level set the output compression, --file-duration/--prefix re-chunk the output into PREFIX-GPS-DURATION.gwf files, --dry-run shows the plan, and @FILE splices in a recipe of stages. The stage chain is checked against the first file's channel list before anything is read
  • fill-gaps [-f VALUE] [--invalid] stage: inserts constant-valued frames across gaps in GPS time (like GStreamer's audiorate) so re-chunked output stays contiguous; --invalid flags the inserted data on ADC channels via dataValid
  • gwframe.pipeline: Pipeline and the Stage classes behind transform, usable from Python
  • Frame.frame_spec (read-only); assigning Frame.frame_number now takes effect on write

Changed

  • resize merges consecutive contiguous frames when the target duration is longer than the source (the last frame of a file may be shorter), and raises ValueError when a frame's duration is not a whole multiple of a shorter target instead of silently dropping the remainder

0.5.0 - 2026-09-10

Added

  • aux_mask=True on read(), read_bytes(), read_frames() and FrameReader.read() decodes a CDS-style "dataValid" auxiliary vector on ADC channels into the TimeSeries mask, combined with the channel-level flag; vectors that don't look like a mask are ignored
  • aux_mask=True on Frame.add_channel(), write(), write_bytes() and FrameWriter.write() stores a partial mask on an ADC channel as an auxiliary vector (1/16 s blocks for integer rates divisible by 16 Hz, one value per sample otherwise) instead of flagging the whole channel
  • read_frames(aux_mask=True) re-encodes decoded masks in the yielded frames, so read-modify-write pipelines preserve partial masks

0.4.4 - 2026-09-09

Added

  • FrameWriter.discard(): abandon a file mid-write, removing the temporary file instead of finalizing a truncated one; the writer can be reopened afterwards
  • close() on the output file stream, so the table of contents is written explicitly rather than on destruction

Changed

  • A failed open or write raises OSError with the C errno frameCPP reported (e.g. ENOSPC when the disk is full) instead of a ValueError or RuntimeError carrying it only in the message

Fixed

  • A write failure while finalizing a file, for example on a full disk, no longer terminates the process: frameCPP raised it from the stream destructor, which ran when the writer was closed, discarded, or the interpreter exited

0.4.3 - 2026-07-28

Added

  • Support for free-threaded CPython: the extension declares it can run without the GIL, and Linux wheels are published for 3.13t and 3.14t

Fixed

  • Fix thread-safety of shared FrameReader/FrameWriter objects — the bindings release the GIL around frame I/O, so concurrent use of a shared stream from multiple threads could corrupt reads or crash; stream access is now serialized per object
  • FrameWriter now raises ValueError when a frame's channel set differs from the frames already written — the GWF table of contents cannot represent per-frame channel sets, and such writes silently produced unreadable files

0.4.2 - 2026-07-27

Added

  • Support for Python 3.14 — wheels are now built and published for CPython 3.14 on all supported platforms

0.4.1 - 2026-07-16

Fixed

  • Fix written files being created with mode 0600 regardless of umask — the temporary file used for atomic writes now gets standard umask-respecting permissions, so output frames are no longer unreadable by group/other

0.4.0 - 2026-07-16

Added

  • gwframe validate command to check two GWF files or directories for consistency, comparing channel sets, frame structure, per-channel metadata, sample data, and dataValid masks
  • gwframe.compare module with compare_files() and compare_paths() returning structured comparison results for programmatic use
  • gwframe inspect now marks invalid (dataValid != 0) ADC channels in the -vvv detail table, with new -vvvv (invalid-channel report) and -vvvvv (per-frame data preview) verbosity levels
  • ChannelInfo.data_valid / ChannelInfo.is_valid and gwframe.inspect.get_invalid_channels() exposing the ADC dataValid flag

0.3.2 - 2026-07-07

Added

  • FrameReader.frame_spans property returning the start/stop times of each frame in the file

Changed

  • Release the GIL around read/write I/O in the C++ bindings, allowing other Python threads to run during frame I/O

Fixed

  • Fix dangling pointer bugs in the frameCPP read bindings — six read/TOC methods returned pointers whose backing memory was freed on return, which could cause crashes or corrupted reads
  • Fix build failure with scikit-build-core 1.0.0 by replacing the removed cmake.minimum-version and cmake.verbose config keys

0.3.1 - 2026-05-11

Added

  • FrameReader context manager for efficient repeated reads from the same file — holds the stream and TOC open, avoiding re-opening on every call
  • FrameReader.read() supports the same parameters as read(): single/multi channel, time-based slicing, frame_index, and allow_invalid
  • FrameReader.info, FrameReader.channels, FrameReader.frames, and FrameReader.channel_details() for metadata access without re-reading

Changed

  • read() now opens the file stream once per call instead of re-opening for each channel or frame index in multi-channel and time-sliced reads

0.3.0 - 2026-04-13

Added

  • Masked array support for ADC channels using the channel-level dataValid flag (frame spec v3-v8)
  • allow_invalid parameter on read(), read_bytes(), and read_frames() to return numpy.ma.MaskedArray for channels with invalid data
  • InvalidDataError exception raised when reading invalid data without allow_invalid=True
  • OnMaskLoss enum (warn, raise, ignore) to control behavior when mask fidelity is lost on write
  • TimeSeries.mask field and TimeSeries.to_masked() convenience method for working with masked data without storing masked arrays directly
  • Frame spec version detection via get_version() in the inspect module
  • gwframe inspect CLI command with tiered verbosity (-v channels, -vv frames, -vvv per-channel detail)
  • ChannelInfo dataclass, get_channels_by_type(), and get_channel_details() in the inspect module
  • FrameWriter.open() / FrameWriter.close() methods as an alternative to the context manager protocol
  • Atomic file writes — FrameWriter now writes to a temporary file and atomically moves it to the final path on close
  • FrameIndexError for clearer error messages when accessing invalid frame indices

Changed

  • Operations now preserve masks and frame spec version through read/write roundtrips
  • TimeSeries stores mask as a separate field instead of using numpy.ma.MaskedArray directly in the array field
  • Use native NumPy dtypes where applicable across read, write, and inspect

Fixed

  • Frame.start setter now propagates to the written GPS time (previously the original GPS time was silently kept)

0.2.2 - 2026-03-25

Fixed

  • Fix memory leak in nanobind bindings for bytes-based frame reading
  • Update minimum version of typer to 0.20

0.2.1 - 2026-03-18

Added

  • Add ADC channel write support

Fixed

  • Fix read() and read_bytes() returning empty results for frames with many channels (e.g. large ADC files) by switching to TOC-based channel enumeration

0.2.0 - 2026-03-17

Added

  • Add gwframe select command to keep only specified channels

Changed

  • Renamed t0 parameter/attribute to start across TimeSeries, FrameInfo, and related APIs
  • Renamed channel parameter to channels in read() and read_bytes()

0.1.2 - 2025-11-18

Added

  • Allow writing frames as bytes

0.1.1 - 2025-11-06

Fixed

  • Fix issue with wheels with 'dirty' tags being generated randomly in CI jobs
  • Prevented a subset of wheels from being published
  • No functional API change

0.1.0 - 2025-11-06

  • Initial release