Migration Guide from SWIG Bindings¶
This guide helps you migrate from the SWIG-based LDAStools.frameCPP bindings to gwframe.
Key Differences¶
gwframe provides an alternative interface to frameCPP with:
- High level API
- Multi-frame support: Simplified writing of multiple frames per file
- Type hints: Full type annotations for IDE support
- Automatic type handling: Data types inferred from NumPy arrays
- Pre-built wheels: No local compilation required
Quick Comparison¶
Reading Data¶
import LDAStools.frameCPP as fc
# Open file
ifo_file = fc.IFrameFStream("data.gwf")
# Get TOC
toc = ifo_file.GetTOC()
# Read channel
fr_data = ifo_file.ReadFrProcData(0, "L1:STRAIN")
vect = fr_data.GetDataVector(0)
array = vect.GetDataArray()
# Get metadata manually
dt = vect.GetDim(0).dx
n_samples = len(array)
duration = dt * n_samples
Writing Single Frame¶
import LDAStools.frameCPP as fc
import numpy as np
# Create frame
gps_time = fc.GPSTime(1234567890, 0)
frame = fc.FrameH(gps_time, "L1", 1, 1.0)
# Create FrVect
dim = fc.Dimension(len(data), 1.0/16384, "s", 0.0)
vect = fc.FrVect("L1:TEST", fc.FrVect.FR_VECT_8R, 1, dim, "strain")
vect.GetDataArray()[:] = data
# Create FrProcData
fr_data = fc.FrProcData("L1:TEST", "", 1, 0, 0.0, 1.0, 0.0, 0.0, 8192.0, 0.0)
fr_data.AppendData(vect)
frame.AppendFrProcData(fr_data)
# Write frame
stream = fc.OFrameFStream("output.gwf")
frame.Write(stream)
Writing Multiple Frames¶
API Translation Table¶
Data Types¶
| SWIG | gwframe |
|---|---|
fc.FrVect.FR_VECT_8R |
Inferred from np.float64 |
fc.FrVect.FR_VECT_4R |
Inferred from np.float32 |
fc.FrVect.FR_VECT_4S |
Inferred from np.int32 |
fc.FrVect.FR_VECT_2S |
Inferred from np.int16 |
| Compression constant 6 | gwframe.Compression.ZERO_SUPPRESS_OTHERWISE_GZIP |
| Compression constant 257 | gwframe.Compression.GZIP |
Reading Operations¶
| SWIG | gwframe |
|---|---|
IFrameFStream(filename) |
read(filename, channel) |
ReadFrProcData(idx, name) |
read(file, name, frame_index=idx) |
GetDataVector(0).GetDataArray() |
read(...).array |
GetTOC() |
get_info(filename) |
toc.GetProc() |
get_channels(filename)['proc'] |
Writing Operations¶
| SWIG | gwframe |
|---|---|
FrameH(gps_time, name, run, dt) |
Frame(t0, duration, name, run) |
AppendFrProcData(fr_data) |
frame.add_channel(name, data, sample_rate) |
OFrameFStream(filename) |
FrameWriter(filename) |
frame.Write(stream, comp, level) |
writer.write_frame(frame) |
Metadata¶
| SWIG | gwframe |
|---|---|
vect.GetDim(0).dx |
data.dt |
1.0 / vect.GetDim(0).dx |
data.sample_rate |
vect.GetName() |
data.name |
vect.GetUnitY() |
data.unit |
frame.GetGTime() |
data.t0 |
Common Patterns¶
Pattern 1: Reading from Multiple Frames¶
import LDAStools.frameCPP as fc
stream = fc.IFrameFStream("multi.gwf")
n_frames = stream.GetNumberOfFrames()
all_data = []
for i in range(n_frames):
fr_data = stream.ReadFrProcData(i, "L1:STRAIN")
vect = fr_data.GetDataVector(0)
all_data.append(vect.GetDataArray())
combined = np.concatenate(all_data)
Pattern 2: Checking Available Channels¶
Pattern 3: Adding History/Metadata¶
Pattern 4: Different Data Types¶
import LDAStools.frameCPP as fc
# Must specify FrVect type explicitly
if data.dtype == np.float64:
vect_type = fc.FrVect.FR_VECT_8R
elif data.dtype == np.float32:
vect_type = fc.FrVect.FR_VECT_4R
elif data.dtype == np.int32:
vect_type = fc.FrVect.FR_VECT_4S
# ... etc
vect = fc.FrVect(name, vect_type, 1, dim, unit)
Parameter Differences¶
Time Parameters¶
| SWIG | gwframe | Conversion |
|---|---|---|
GPSTime(sec, nsec) |
t0 (float) |
t0 = sec + nsec * 1e-9 |
dt (sample spacing) |
sample_rate or dt |
Both available; sample_rate = 1/dt |
Method vs Property Access¶
| SWIG | gwframe |
|---|---|
vect.GetDataArray() |
data.array |
vect.GetName() |
data.name |
vect.GetUnitY() |
data.unit |
Migration Checklist¶
When migrating from SWIG to gwframe:
- [ ] Replace
import LDAStools.frameCPPwithimport gwframe - [ ] Replace
IFrameFStream.ReadFrProcData()withgwframe.read() - [ ] Replace manual FrVect/FrProcData creation with
gwframe.write()orFrame.add_channel() - [ ] Use
FrameWritercontext manager for multi-frame files - [ ] Replace
GPSTime(sec, nsec)with float GPS time - [ ] Replace
.Get*()method calls with property access (e.g.,.array,.name) - [ ] Remove manual type specifications - inferred from NumPy dtype
- [ ] Consider using time-based slicing instead of manual frame loops
Important Notes¶
GPS Time Handling¶
SWIG uses GPSTime objects with separate seconds and nanoseconds:
# SWIG
gps_time = fc.GPSTime(1234567890, 500000000) # sec, nsec
# gwframe
t0 = 1234567890.5 # Float representation
Frame Number Auto-increment¶
In SWIG, frame numbers must be managed manually. gwframe's FrameWriter auto-increments:
# SWIG - manual tracking needed
for i in range(100):
frame = fc.FrameH(gps_time, "L1", 1, 1.0) # frame number always 1
# gwframe - automatic
with gwframe.FrameWriter("file.gwf") as writer:
for i in range(100):
writer.write(...) # Frame numbers auto-increment: 0, 1, 2, ...
Data Type Specification¶
SWIG requires explicit FrVect type codes. gwframe infers from NumPy dtype:
# SWIG
vect = fc.FrVect(name, fc.FrVect.FR_VECT_8R, ...) # Explicit type
# gwframe
frame.add_channel(name, data, ...) # Type inferred from data.dtype
See Also¶
- Quick Start Guide - Learn gwframe basics
- Examples - Comprehensive examples
- API Reference - Complete API documentation