Python Easy API
Quick summary:
Use this layer when you want “just give me arrays”.
Think of
Viewas “arrays + current selection state”.When you need more control, drop to
View._chunk(CoreChunk).
Mental model: View is a small dashboard; you change selectors, then read tables.
This layer is for “give me arrays for analysis/simulation”. You do not need to learn chunk/query/recipe internals. Remember:
sqzc3d.read(...)loads data into aView.Viewholds the current selection state (labels/type-groups) and exposes data + validity as properties.When you need advanced features, drop to
View._chunk(CoreChunk).
If you already have indices, or you need precise layout/view/copy control, use the Core API (Decoder / Chunk).
Load: read
import sqzc3d as sq
v = sq.read("trial.c3d") # materialize from C3D
v = sq.read("trial.sqzc3d") # load a single-file bundle
v = sq.read("bundle_dir/") # load a directory bundle
Common parameters:
start_frame,frame_count: frame window selectionpoints,analogs: label selectorsanalog_range: analog window selection (advanced, in the same frame index space asstart_frame)label_norm: label normalization mode (ambiguous matches raise)recipe: reusable filtering recipe (currently mainly type-groups)
Selector semantics:
Nonemeans default (ALL)[]means empty selectionstrorsequence[str]means label selection
Windows and time axis
View.meta includes time-axis metadata (when available):
source_first_frame,source_last_frame: absolute frame indices from the original C3Dpoint_rate_hz,analog_rate_hz: sampling ratesframe_start,frame_start_abs: point window origin (relative / absolute)analog_frame_start,analog_frame_start_abs: analog window origin (relative / absolute)
If you want analogs aligned with the point window, pass analog_range=(start_frame, frame_count) explicitly:
import sqzc3d as sq
v = sq.read("trial.c3d", start_frame=100, frame_count=200, analog_range=(100, 200))
print(v.meta["frame_start_abs"], v.meta["analog_frame_start_abs"])
Selection state: mutate View fields
View keeps selection state in fields you can inspect and update:
import sqzc3d as sq
v = sq.read("trial.c3d")
# Inspect
print(v.point_labels) # None means ALL
print(v.analog_labels) # None means ALL
# Update (labels-only)
v.point_labels = ["LASI", "RASI"]
v.analog_labels = ["EMG1"]
Order (important):
If
view.point_labelsis set,view.pointsreturns points in the same order aspoint_labels.If
view.analog_labelsis set,view.analogsreturns channels in the same order asanalog_labels.
Get data: properties + validity
view.points/view.points_validview.analogs/view.analogs_valid
pts = v.points
valid = v.points_valid
By-label access: one marker / one channel
Convenient label accessors (avoids manual index lookup):
ank = v.point["LANK"] # (T, 3)
ank_valid = v.point_valid["LANK"] # (T,)
emg = v.analog["EMG1"] # (N,) or (T, S) depending on analog_layout
emg_valid = v.analog_valid["EMG1"]
Type-groups
Optional.
If type-groups exist on the chunk, they can be applied as an extra AND-filter:
import sqzc3d as sq
v = sq.read("trial.c3d")
v.type_groups = ["MARKER"] # AND with point_labels if set
pts = v.points
Missing-metadata behavior:
type_groups_missing_meta="all"(default): missing TYPE_GROUPS metadata is treated as no-optype_groups_missing_meta="empty": missing metadata yields an empty set
Strict mode:
type_groups_strict=Truemakes missing/invalid cases raise.
Recipe
Optional.
A Recipe is a reusable config object that can be passed into read(...):
import sqzc3d as sq
rcp = sq.Recipe(
type_groups=("MARKER",),
type_groups_strict=False,
type_groups_missing_meta="all",
)
v = sq.read("trial.c3d", recipe=rcp)
print(v.describe())
Advanced: drop to Core
Always available.
View._chunk exposes the underlying Core Chunk:
chunk = v._chunk
pts, valid = chunk.points(None, copy=False)