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/--recursiveto process subdirectories - In-place editing: Use
-i/--in-placeto 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:
Options:
-m, --map TEXT- Channel mapping in formatOLD=>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:
Rename multiple channels:
Process entire directory:
In-place rename (modifies originals):
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:
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:
Combine directories (matches frame files by time):
Combine with channel filtering (keep only specific channels):
Combine and drop unwanted channels:
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:
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:
Keep multiple channels:
Process directory and keep only selected channels:
In-place selection (modifies originals):
drop - Remove Channels¶
Remove specified channels from frame files. This is the inverse of select.
Usage:
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:
Drop multiple channels:
Process directory and drop channels:
In-place removal (modifies originals):
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:
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:
Combine 1-second frames into 16-second frames:
Convert entire directory:
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-durationto 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:
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):
Replace specific sentinel value:
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:
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:
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:
Replace only specific channel:
Replace data in entire directory (matches by filename/time):
Replace multiple specific channels:
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:
Options:
-c, --compression TEXT- Compression type (default: ZERO_SUPPRESS_OTHERWISE_GZIP)RAW- No compression (fastest, largest)GZIP- Standard gzip compressionDIFF_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:
Re-compress entire directory with optimal settings:
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:
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;transformnever 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-DESCRIPTIONprefix 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:
Re-chunk 64 s files into 4096 s archive files with 4096 s frames:
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:
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:
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:
List all channels with their types:
Show channels and per-frame metadata:
Full detail including sample rates, dtypes, units, and validity:
Report which ADC channels are flagged invalid (dataValid != 0), and in which frames:
Preview the actual sample data, frame by frame:
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:
Compare directories, restricted to what both sides have:
Fast metadata-only check of a single channel:
Tolerate tiny floating-point differences (e.g. after recalibration):
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"¶
Solution: List available channels withinspect:
"Time ranges don't match"¶
Solution: Usecombine 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"¶
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).