Skip to content

CLI Tools

gwframe provides a comprehensive command-line interface for manipulating GWF files without writing Python code. All commands support both single files and batch processing of directories.

Common Options

All commands support these common patterns:

  • File or directory input: Pass individual files or directories
  • Batch processing: Use glob patterns like data/*.gwf
  • Recursive processing: Use -r/--recursive to process subdirectories
  • In-place editing: Use -i/--in-place to modify files directly
  • Output control: Specify output directory with -o/--output-dir
  • Progress: Commands that process files show a progress bar (frames done, elapsed, remaining) when run in a terminal; it is omitted when output is piped or redirected

Tip

Use gwframe COMMAND --help to see detailed help for any command.

Commands

rename - Rename Channels

Rename channels within frame files while preserving all other data.

Usage:

gwframe rename INPUT... -m "OLD=>NEW" [-o OUTPUT] [-i] [-r]

Options:

  • -m, --map TEXT - Channel mapping in format OLD=>NEW (required, can specify multiple)
  • -o, --output-dir PATH - Output directory or file
  • -i, --in-place - Modify files in place
  • -r, --recursive - Recurse into subdirectories

Examples:

Rename a single channel in one file:

gwframe rename input.gwf -o output.gwf -m "L1:OLD_CHAN=>L1:NEW_CHAN"

Rename multiple channels:

gwframe rename input.gwf -o output/ \
    -m "L1:CHAN1=>L1:NEW1" \
    -m "L1:CHAN2=>L1:NEW2"

Process entire directory:

gwframe rename data/ -o output/ -m "L1:GDS-CALIB_STRAIN=>L1:STRAIN"

In-place rename (modifies originals):

gwframe rename data/*.gwf --in-place -m "L1:OLD=>L1:NEW"


combine - Combine Channels

Merge channels from multiple sources covering the same time period. Useful for combining data from different acquisition systems or adding calibrated channels to raw data files.

Usage:

gwframe combine SOURCE1 SOURCE2 [SOURCE3...] -o OUTPUT [--keep CHAN] [--drop CHAN]

Options:

  • -o, --output-dir PATH - Output directory (required)
  • -k, --keep TEXT - Only include these channels (can specify multiple)
  • -d, --drop TEXT - Exclude these channels (can specify multiple)

Examples:

Combine two files:

gwframe combine raw_data.gwf calibrated.gwf -o output/

Combine directories (matches frame files by time):

gwframe combine raw_dir/ calibrated_dir/ -o combined/

Combine with channel filtering (keep only specific channels):

gwframe combine dir1/ dir2/ dir3/ -o output/ \
    --keep L1:STRAIN \
    --keep L1:LSC-DARM_IN1_DQ

Combine and drop unwanted channels:

gwframe combine source1/ source2/ -o output/ \
    --drop L1:TEMPORARY_CHANNEL

Warning

All sources must cover the same time ranges. Mismatched time ranges will cause an error.


select - Keep Specific Channels

Keep only specified channels in frame files, removing all others.

Usage:

gwframe select INPUT... -c CHANNEL [-o OUTPUT] [-i] [-r]

Options:

  • -c, --channel TEXT - Channel(s) to keep (required, can specify multiple)
  • -o, --output-dir PATH - Output directory or file
  • -i, --in-place - Modify files in place
  • -r, --recursive - Recurse into subdirectories

Examples:

Keep a single channel:

gwframe select input.gwf -o output.gwf -c L1:STRAIN

Keep multiple channels:

gwframe select input.gwf -o output.gwf \
    -c L1:STRAIN \
    -c L1:LSC-DARM_IN1_DQ

Process directory and keep only selected channels:

gwframe select data/ -o filtered/ -c L1:STRAIN --recursive

In-place selection (modifies originals):

gwframe select data/*.gwf --in-place -c L1:STRAIN


drop - Remove Channels

Remove specified channels from frame files. This is the inverse of select.

Usage:

gwframe drop INPUT... -c CHANNEL [-o OUTPUT] [-i] [-r]

Options:

  • -c, --channel TEXT - Channel(s) to drop (required, can specify multiple)
  • -o, --output-dir PATH - Output directory or file
  • -i, --in-place - Modify files in place
  • -r, --recursive - Recurse into subdirectories

Examples:

Drop single channel:

gwframe drop input.gwf -o output.gwf -c L1:UNWANTED_CHANNEL

Drop multiple channels:

gwframe drop input.gwf -o output.gwf \
    -c L1:CHAN1 \
    -c L1:CHAN2 \
    -c L1:CHAN3

Process directory and drop channels:

gwframe drop data/ -o cleaned/ -c L1:TEMPORARY_DATA

In-place removal (modifies originals):

gwframe drop data/*.gwf --in-place -c L1:DEBUG_CHANNEL


resize - Change Frame Duration

Split or combine frames to achieve a target duration. Used to convert between different frame lengths (e.g., 64s → 4s).

Usage:

gwframe resize INPUT... -d DURATION [-o OUTPUT] [-i] [-r]

Options:

  • -d, --duration FLOAT - Target frame duration in seconds (required)
  • -o, --output-dir PATH - Output directory or file
  • -i, --in-place - Modify files in place
  • -r, --recursive - Recurse into subdirectories

Examples:

Split 64-second frames into 4-second frames:

gwframe resize input.gwf -o output/ -d 4.0

Combine 1-second frames into 16-second frames:

gwframe resize data/ -o output/ -d 16.0 --recursive

Convert entire directory:

gwframe resize original_data/ -o resized_data/ -d 8.0

Note

  • Splitting requires the source frame duration to be a whole multiple of the target
  • Merging combines consecutive contiguous frames within a file; the last frame of a file may be shorter than the target (use transform --file-duration to merge across files)
  • All channels in the frame are resized together and frames are renumbered from 0
  • Frame metadata (GPS time, run number, etc.) is preserved

impute - Replace Values

Replace specific values (like NaN, -999, or sentinel values) with a fill value.

Usage:

gwframe impute INPUT... [-r VALUE] [-f VALUE] [-c CHANNEL] [-o OUTPUT] [-i]

Options:

  • -r, --replace-value FLOAT - Value to replace (default: NaN)
  • -f, --fill-value FLOAT - Replacement value (default: 0.0)
  • -c, --channel TEXT - Specific channel(s) to impute (if omitted, processes all channels)
  • -o, --output-dir PATH - Output directory or file
  • -i, --in-place - Modify files in place
  • --recursive - Recurse into subdirectories

Examples:

Replace NaN with zeros (default behavior):

gwframe impute input.gwf -o output.gwf

Replace specific sentinel value:

gwframe impute input.gwf -o output.gwf \
    --replace-value -999.0 \
    --fill-value 0.0

Impute only specific channels:

gwframe impute data.gwf -o clean.gwf \
    --fill-value 0.0 \
    --channel L1:STRAIN \
    --channel L1:LSC-DARM

Process directory and replace -inf values:

gwframe impute data/ -o cleaned/ \
    --replace-value -inf \
    --fill-value 0.0

Warning

The fill value is cast to the dtype of each channel, so precision may be lost for integer channels.


replace - Update Channel Data

Replace channel data in base files with updated versions from other files.

Usage:

gwframe replace BASE... --update UPDATE -o OUTPUT [-c CHANNEL] [-r]

Options:

  • -u, --update PATH - Source of updated channel data (required)
  • -o, --output-dir PATH - Output directory (required)
  • -c, --channel TEXT - Specific channel(s) to replace (if omitted, replaces all matching channels)
  • -r, --recursive - Recurse into subdirectories

Examples:

Replace all matching channels from update file:

gwframe replace base.gwf --update updated.gwf -o output/

Replace only specific channel:

gwframe replace base.gwf --update calibrated.gwf -o output/ -c L1:STRAIN

Replace data in entire directory (matches by filename/time):

gwframe replace base_dir/ --update update_dir/ -o output/ --recursive

Replace multiple specific channels:

gwframe replace data.gwf --update new_data.gwf -o output/ \
    -c L1:STRAIN \
    -c L1:LSC-DARM_IN1_DQ

Use Cases

  • Data fixes: Replace corrupted segments with corrected data
  • Reprocessing: Update specific channels while keeping others unchanged

recompress - Change Compression

Rewrite frame files with different compression settings.

Usage:

gwframe recompress INPUT... [-c TYPE] [-l LEVEL] [-o OUTPUT] [-i] [-r]

Options:

  • -c, --compression TEXT - Compression type (default: ZERO_SUPPRESS_OTHERWISE_GZIP)
  • RAW - No compression (fastest, largest)
  • GZIP - Standard gzip compression
  • DIFF_GZIP - Differentiate then gzip (good for slowly-varying data)
  • ZERO_SUPPRESS_OTHERWISE_GZIP - Zero-suppression with gzip fallback (recommended)
  • -l, --level INT - Compression level 0-9 (default: 6, higher = more compression)
  • -o, --output-dir PATH - Output directory or file
  • -i, --in-place - Modify files in place
  • -r, --recursive - Recurse into subdirectories

Examples:

Maximum compression for archival:

gwframe recompress input.gwf -o archive.gwf -c GZIP -l 9

Re-compress entire directory with optimal settings:

gwframe recompress data/ -o compressed/ \
    -c ZERO_SUPPRESS_OTHERWISE_GZIP \
    -l 6 \
    --recursive


transform - Chain Stages in One Pass

Apply a sequence of transformations to a set of frame files in a single read/write pass. This is the tool for turning a raw dataset into a curated one: instead of running rename, then drop, then resize with an intermediate copy of the dataset after each, the stages run back to back on every frame as it streams from input to output.

Usage:

gwframe transform INPUT... -o OUTPUT [OPTIONS] [STAGE [STAGE-OPTIONS]]...

Everything before the first stage name belongs to transform itself: the input paths (in any order with the options) and the output settings. Each stage takes the same options as the standalone command of the same name, minus input, output and in-place. Stages run left to right.

Options:

  • -o, --output-dir PATH - Output directory (required; transform never modifies files in place)
  • -r, --recursive - Recurse into subdirectories
  • --compression TEXT - Compression type for the output (default: ZERO_SUPPRESS_OTHERWISE_GZIP)
  • --level INT - Compression level 0-9 (default: 6)
  • --file-duration FLOAT - Re-chunk the output into files of this many seconds (see below)
  • --prefix TEXT - OBSERVATORY-DESCRIPTION prefix for re-chunked file names (default: from the first input file)
  • --dry-run - Print the plan and preflight warnings without writing anything
  • --strict - Treat preflight warnings as errors: exit 1 and write nothing

Stages:

Stage Options Effect
rename -m OLD=>NEW (repeatable) Rename channels
drop -c CHANNEL (repeatable) Remove channels
select -c CHANNEL (repeatable) Keep only these channels
impute -r VALUE, -f VALUE, -c CHANNEL Replace a value (default NaN) with a fill value
fill-gaps -f VALUE, --invalid Insert constant-valued frames across gaps in GPS time (default 0); --invalid flags them as invalid on ADC channels
resize -d DURATION Split or merge frames to a duration

With no stages at all the files are simply rewritten, which makes transform a recompress and re-chunk tool on its own.

Examples:

Rename, drop and re-frame a raw dataset into a curated one, compressed for archival:

gwframe transform raw/ -o curated/ --compression GZIP --level 9 \
    rename -m "L1:GDS-CALIB_STRAIN=>L1:STRAIN" \
    drop -c L1:DEBUG_CHAN \
    impute --replace-value -999 --fill-value 0 -c L1:STRAIN \
    resize -d 4

Preview what a chain would do before running it:

gwframe transform raw/ -o curated/ --dry-run drop -c L1:DEBUG_CHAN resize -d 4

Re-chunk 64 s files into 4096 s archive files with 4096 s frames:

gwframe transform raw/ -o archive/ --file-duration 4096 --prefix L-L1_CURATED \
    resize -d 4096

Reproduce a gstlal framecpp_channelmux rewrite (1 s frames, 4096 frames per file, gaps zero-filled by audiorate):

gwframe transform $(cat file_list.txt) -o H1/ \
    --file-duration 4096 --prefix H-H1_O4LLPIC \
    --compression ZERO_SUPPRESS_OTHERWISE_GZIP --level 3 \
    select -c H1:GDS-CALIB_STRAIN -c H1:GDS-CALIB_STATE_VECTOR \
    fill-gaps \
    resize -d 1

Keep the recipe for a curated dataset in a file and reuse it:

gwframe transform raw/ -o curated/ @curated.recipe

Preflight and dry runs. Before any data is read, the stage chain is projected through the channel list of the first input file. Channels that a stage names but are not present at that point in the chain are reported as warnings, naming where they were looked for (the input, or the output of the previous stage), since this is usually a typo. A rename that would overwrite an existing channel is an error, and a chain that would leave no channels at all is an error. The plan and the warnings are printed on every run; --dry-run stops there.

By default a warning does not stop the run, so a rename whose source is misspelled quietly produces a dataset without that rename. Pass --strict to make any preflight warning fail the run before anything is written; use it for any recipe you rely on, and --strict --dry-run as a pre-check in scripts (exit code 1 on warnings).

Output modes. By default each input file is processed on its own and written under its own name, exactly as the standalone commands do. With --file-duration the inputs are instead read in GPS order as one continuous stream and the output is cut into files of the given duration. A gap in GPS time starts a new file, so the last file of a run (or of a segment) may be shorter; put a fill-gaps stage in the chain to bridge gaps with constant-valued frames instead, the way GStreamer's audiorate element does in gstlal frame-rewriting pipelines. Add --invalid to that stage so consumers can tell the inserted data from real data: ADC channels get their dataValid flag set (they read back fully masked). Proc and sim channels have no such flag in the frame format and stay unflagged, with a warning naming them. Output files are named PREFIX-GPSSTART-DURATION.gwf; the prefix is taken from the first input file when it follows that convention, else from its stem, and --prefix overrides it. In this mode resize can merge frames across the original file boundaries.

Recipe files. A token of the form @FILE is replaced by the contents of FILE, split like a shell command line: one or more stages per line, quotes as needed, \ at the end of a line to continue it, # to end of line for comments. The recipe holds only stages; inputs, output and options stay on the command line, so the same recipe applies to any dataset.

# curated.recipe
rename -m "L1:GDS-CALIB_STRAIN=>L1:STRAIN"
drop -c L1:DEBUG_CHAN
impute -c L1:STRAIN           # NaN -> 0
resize -d 4

Note

Stage options must follow their stage name. An option placed before the first stage is an error, since it would be read as an option of transform itself.


inspect - Inspect Frame Files

Display metadata and channel information for a GWF file. Supports tiered verbosity to progressively reveal more detail.

Usage:

gwframe inspect FILE [-v] [-vv] [-vvv] [-vvvv] [-vvvvv]

Verbosity levels:

Flag Level Shows
(none) 0 File summary: GPS range, frame/channel counts, compression, file size
-v 1 Add channel listing with types (adc/proc/sim)
-vv 2 Add per-frame table with GPS start, duration, run, frame number
-vvv 3 Replace simple channel listing with detailed table (sample rate, dtype, units, sample count, validity — accurate across all frames)
-vvvv 4 Add invalid-channel report: ADC channels with dataValid != 0, affected frames, raw flag values
-vvvvv 5 Add per-frame data preview tables with abbreviated sample values

Examples:

Quick file summary:

gwframe inspect data.gwf

List all channels with their types:

gwframe inspect -v data.gwf

Show channels and per-frame metadata:

gwframe inspect -vv data.gwf

Full detail including sample rates, dtypes, units, and validity:

gwframe inspect -vvv data.gwf

Report which ADC channels are flagged invalid (dataValid != 0), and in which frames:

gwframe inspect -vvvv data.gwf

Preview the actual sample data, frame by frame:

gwframe inspect -vvvvv data.gwf

Tip

Levels 0-4 read only file/channel headers (fast even for large files) — the validity scan never decompresses sample data. Level 5 (-vvvvv) reads and decompresses all channel data and can be slow for large files.


validate - Check Consistency Between Files

Compare two GWF files (or directories of GWF files) for consistency. Checks channel sets, frame structure (count and GPS spans), per-channel metadata (type, dtype, sample rate, sample count, unit), and sample data, reporting every difference found. Useful for verifying round-trips (e.g. after recompress) or that two productions of the same data agree.

Usage:

gwframe validate PATH1 PATH2 [-c CHANNEL] [--common-channels] [--common-time-spans] [--common] [--ignore-channel-type] [--metadata-only] [--rtol X] [--atol X] [-r] [-v]

Options:

  • -c, --channel TEXT - Compare only the specified channel(s) (can specify multiple)
  • --common-channels - Compare only channels present on both sides (extra channels are not reported)
  • --common-time-spans - Compare only time spans present on both sides (unmatched files and frames are skipped, e.g. for live data with different retention; this includes files deleted from disk while the comparison is running)
  • --common - Shorthand for --common-channels --common-time-spans
  • --ignore-channel-type - Do not report channel type (adc/proc/sim) differences, e.g. when the same data is stored as ADC on one side and proc on the other
  • --metadata-only - Compare structure and metadata only; skip sample data (faster)
  • --rtol FLOAT / --atol FLOAT - Relative/absolute tolerance for float data (default: exact comparison)
  • -r, --recursive - Search directories recursively for GWF files
  • -v, --verbose - Show all differences instead of the first 20 per file pair

Exit codes: 0 consistent, 1 differences found, 2 usage or read error.

Examples:

Compare two files exactly:

gwframe validate a.gwf b.gwf

Compare directories, restricted to what both sides have:

gwframe validate dir1/ dir2/ --common

Fast metadata-only check of a single channel:

gwframe validate a.gwf b.gwf -c L1:STRAIN --metadata-only

Tolerate tiny floating-point differences (e.g. after recalibration):

gwframe validate produced/ reference/ --atol 1e-12

Note

In directory mode, frames are paired across the two sides by their GPS (start, duration) span, regardless of which file holds them, so file names and even file boundaries do not need to match: a dataset re-cut into 4096 s files compares equal to the original 64 s files. Results are reported per pair of files that shared frames; a frame with no counterpart is an unmatched_frame difference, a whole file with none an unmatched_file.


Error Handling

Common errors and solutions:

"Channel not found"

Error: Channel 'L1:MISSING' not found in frame
Solution: List available channels with inspect:
gwframe inspect -v file.gwf

"Time ranges don't match"

Error: Source time ranges do not match
Solution: Use combine only with files covering identical time spans. Check with:
import gwframe
for file in ["file1.gwf", "file2.gwf"]:
    info = gwframe.read(file, channel_list=True)
    print(f"{file}: {info}")

"Not a whole multiple"

Error: frame duration 100s is not a whole multiple of target duration 64s
Solution: When splitting, choose a target duration that evenly divides the frame duration. When merging, the source frames must add up to the target exactly (frames of 3s do not merge evenly into target duration 4s).