pipeline
Frame pipelines: apply a chain of stages to a stream of frames in one pass.
A pipeline reads frames from one or more GWF files, passes them through a
sequence of :class:Stage objects, and writes the result. Every stage is a
transformation of an iterator of :class:~gwframe.write.Frame objects, so
stages compose freely and the whole chain costs a single decode/encode pass
regardless of its length.
Two output modes are supported:
- per file (the default): each input file is processed independently and
written under its own name in the output directory, exactly like the
single operations in :mod:
gwframe.operations. - re-chunked (
file_durationgiven): the inputs are read in GPS order as one continuous stream and the output is cut into files of the requested duration, namedPREFIX-GPS-DURATION.gwf.
Examples:
>>> from gwframe.pipeline import Pipeline, RenameStage, DropStage, ResizeStage
>>> pipeline = Pipeline([
... RenameStage({"L1:GDS-CALIB_STRAIN": "L1:STRAIN"}),
... DropStage(["L1:DEBUG"]),
... ResizeStage(4.0),
... ])
>>> pipeline.run(["raw/a.gwf", "raw/b.gwf"], "curated/")
DropStage ¶
Bases: MapStage
Remove channels.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
channels
|
sequence of str
|
Channel names to remove. Channels absent from a frame are skipped. |
required |
Source code in gwframe/pipeline.py
FillGapsStage ¶
Bases: Stage
Fill gaps in GPS time between consecutive frames with synthetic frames.
Wherever a frame starts later than the previous one ended, frames of a constant fill value are inserted to cover the gap, so the stream (and files re-chunked from it) is contiguous. The inserted frames copy the previous frame's channels, sample rates, dtypes, units and duration; the last inserted frame is shorter if the gap is not a whole multiple of that duration. Nothing is inserted before the first frame. Frames that overlap the previous one are an error.
This mirrors GStreamer's audiorate skip-to-first=true element as
used in gstlal frame-rewriting pipelines.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fill_value
|
float
|
Sample value for the inserted frames, cast to each channel's dtype (default: 0.0) |
0.0
|
invalid
|
bool
|
If True, flag the inserted data as invalid so consumers can tell it from real data: ADC channels get their channel-level dataValid flag set (they read back fully masked). Proc and sim channels have no such flag in the frame format and are left unflagged; a warning names them once. |
False
|
Source code in gwframe/pipeline.py
ImputeStage ¶
ImputeStage(replace_value: float = nan, fill_value: float = 0.0, channels: Sequence[str] | None = None)
Bases: MapStage
Replace a value in channel data with a fill value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
replace_value
|
float
|
Value to replace (default: NaN) |
nan
|
fill_value
|
float
|
Replacement, cast to each channel's dtype (default: 0.0) |
0.0
|
channels
|
sequence of str
|
Restrict to these channels (default: all channels) |
None
|
Source code in gwframe/pipeline.py
Pipeline ¶
A sequence of stages applied to a stream of frames.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
stages
|
sequence of Stage
|
Stages to apply, in order. May be empty, in which case the pipeline simply rewrites its input (useful for recompressing or re-chunking). |
()
|
Source code in gwframe/pipeline.py
apply ¶
preflight ¶
Check the pipeline against a channel set without reading any data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
channels
|
iterable of str
|
Channel names of the input, typically from
:func: |
required |
Returns:
| Name | Type | Description |
|---|---|---|
channels |
set[str]
|
Channel names expected in the output |
warnings |
list[str]
|
Likely mistakes, one per line, each prefixed with the stage that raised it and the point in the chain the check was made against (the input, or the output of the previous stage) |
Raises:
| Type | Description |
|---|---|
ValueError
|
A stage cannot be applied, or no channels would remain. |
Source code in gwframe/pipeline.py
run ¶
run(input_files: str | PathLike[str] | Sequence[str | PathLike[str]], output_dir: str | PathLike[str], *, compression: int = ZERO_SUPPRESS_OTHERWISE_GZIP, compression_level: int = 6, file_duration: float | None = None, prefix: str | None = None, progress: ProgressCallback | None = None, strict: bool = False) -> list[str]
Run the pipeline over files, writing the result.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_files
|
str, path-like, or sequence of str/path-like
|
Input GWF file(s) |
required |
output_dir
|
str or path - like
|
Directory where output files are written (created if needed) |
required |
compression
|
int
|
Compression scheme for the output |
ZERO_SUPPRESS_OTHERWISE_GZIP
|
compression_level
|
int
|
Compression level 0-9 (default: 6) |
6
|
file_duration
|
float
|
If given, read the inputs in GPS order as one stream and cut the output into files of at most this many seconds (a gap in GPS time also starts a new file). Otherwise each input file is written under its own name. |
None
|
prefix
|
str
|
|
None
|
progress
|
callable
|
Called after each input frame has been processed with
|
None
|
strict
|
bool
|
If True, :meth: |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
output_files |
list[str]
|
Output file paths, in the order written |
Raises:
| Type | Description |
|---|---|
ValueError
|
The pipeline cannot be applied to the input (see
:meth: |
Source code in gwframe/pipeline.py
714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 | |
RenameStage ¶
Bases: MapStage
Rename channels.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
channel_map
|
mapping of str to str
|
Old channel name to new channel name. Channels absent from a frame are skipped. |
required |
Source code in gwframe/pipeline.py
ResizeStage ¶
ResizeStage(duration: float)
Bases: Stage
Resize frames to a target duration.
Frames longer than the target are split into equal parts; the source duration must be a whole multiple of the target. Consecutive shorter frames are merged, also across input file boundaries, until they reach the target; a gap in GPS time or the end of the stream flushes a shorter frame. Output frames are numbered sequentially from 0.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
duration
|
float
|
Target frame duration in seconds |
required |
Source code in gwframe/pipeline.py
SelectStage ¶
Bases: MapStage
Keep only the given channels, removing all others.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
channels
|
sequence of str
|
Channel names to keep |
required |
Source code in gwframe/pipeline.py
Stage ¶
Bases: ABC
One step of a frame pipeline.
A stage transforms an iterator of frames into another iterator of
frames. Most stages act on one frame at a time; subclass
:class:MapStage for those. Stages that change the number of frames
(such as :class:ResizeStage) override :meth:apply directly.
Stages can also predict their effect on the set of channel names, which
lets a pipeline be checked against a file's table of contents before any
data is read (see :meth:Pipeline.preflight).
apply
abstractmethod
¶
project ¶
Predict the channel set after this stage.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
channels
|
set[str]
|
Channel names entering the stage |
required |
Returns:
| Name | Type | Description |
|---|---|---|
channels |
set[str]
|
Channel names leaving the stage |
warnings |
list[str]
|
Human-readable notes about likely mistakes, such as a channel that is named by the stage but not present in the input |
Raises:
| Type | Description |
|---|---|
ValueError
|
The stage cannot be applied to this channel set (for example a rename that would overwrite an existing channel). |
Source code in gwframe/pipeline.py
file_prefix ¶
Return the OBSERVATORY-DESCRIPTION prefix of a frame file name.
Files that don't follow the OBS-DESC-GPS-DURATION.gwf convention
use their whole stem as the prefix.
Examples:
>>> file_prefix("L-L1_HOFT_C00-1238166018-4096.gwf")
'L-L1_HOFT_C00'
>>> file_prefix("data/single.gwf")
'single'
Source code in gwframe/pipeline.py
sort_files_by_gps ¶
Sort frame files by the GPS start of their first frame.
Only file headers are read. Files without frames sort last, in name order.