Package c3d


Python C3D Processing

This package provides pure Python modules for reading, writing, and editing binary motion-capture files in the C3D file format.

Installing

See the main page or github page.

Examples

Access to data blocks in a .c3d file is provided through the Reader and Writer classes. Implementation of the examples below are provided in the examples/ directory in the github repository.

Reading

To read the frames from a C3D file, use a Reader instance:

import c3d

with open('my-motion.c3d', 'rb') as file:
    reader = c3d.Reader(file)
    for i, points, analog in reader.read_frames():
        print('frame {}: point {}, analog {}'.format(
              i, points.shape, analog.shape))

The method Reader.read_frames() generates tuples containing the trial frame number, a numpy array of point data, and a numpy array of analog data.

Writing

To write data frames to a C3D file, use a Writer instance:

import c3d
import numpy as np

# Writes 100 frames recorded at 200 Hz.
# Each frame contains recordings for 24 coordinate markers.
writer = c3d.Writer(point_rate=200)
for _ in range(100):
    writer.add_frames((np.random.randn(24, 5), ()))

writer.set_point_labels(['RFT1', 'RFT2', 'RFT3', 'RFT4',
                         'LFT1', 'LFT2', 'LFT3', 'LFT4',
                         'RSK1', 'RSK2', 'RSK3', 'RSK4',
                         'LSK1', 'LSK2', 'LSK3', 'LSK4',
                         'RTH1', 'RTH2', 'RTH3', 'RTH4',
                         'LTH1', 'LTH2', 'LTH3', 'LTH4'
                        ])
writer.set_analog_labels(None)

with open('random-points.c3d', 'wb') as h:
    writer.write(h)

The function Writer.add_frames() take pairs of numpy or python arrays, with the first array in each tuple defining point data and the second analog data for the frame. Leaving one of the arrays empty indicates to the writer that no analog — or point data— should be included in the file. References of the data arrays are tracked until Writer.write() is called, which serializes the metadata and data frames into a C3D binary file stream.

Editing

Editing c3d files is possible by combining the use of Reader and Writer instances through the Reader.to_writer() method. To edit a file, open a file stream and pass it to the Reader constructor. Use the Reader.to_writer() method to create an independent Writer instance containing a heap copy of its file contents. To edit the sequence, one can now reread the data frames from the reader and through inserting the frames in reverse to create a looped version of the original motion sequence!

import c3d

with open('my-motion.c3d', 'rb') as file:
    reader = c3d.Reader(file)
    writer = reader.to_writer('copy')
    for i, points, analog in reader.read_frames():
        writer.add_frames((points, analog), index=reader.frame_count)

with open('my-looped-motion.c3d', 'wb') as h:
    writer.write(h)

Accessing Metadata

Metadata in a .c3d file exists in two forms, a Header and ParamData. Reading metadata fields can be done though the Reader but editing requires a Writer instance.

Header fields can be accessed from the common Manager.header attribute. Parameters are available through a parameter Group, and can be accessed through the Manager.get() and Group.get() methods:

group = reader.get('POINT')
param = group.get('LABELS')

or simply use

param = reader.get('POINT:LABELS')

Note that for accessing parameters in the Reader, Reader.get() returns a GroupReadonly instance. Convenience functions are provided for some of the common metadata fields such as Manager.frame_count. In the case you require specific metadata fields, consider exploring the C3D format manual and/or inspect the file using the c3d-metadata script.

Writing Metadata

Once a Writer instance is created, to edit parameter data Writer.get_create() a group:

group = writer.get_create('ANALOG')

and to write a float32 entry, use the Group.add() or Group.set() functions

group.set('GEN_SCALE', 'Analog general scale factor', 4, '<f', value)

In this case, one can use the Writer.set_analog_general_scale() method instead. For serializing other types, see the source code for some of the convenience functions. For example: Writer.set_point_labels() (2D string array) or Writer.set_analog_scales() (1D float array).

Expand source code
"""
---------------------
Python C3D Processing
---------------------

This package provides pure Python modules for reading, writing, and editing binary
motion-capture files in the [C3D file format].

[C3D file format]: https://www.c3d.org/HTML/default.htm

Installing
----------

See the [main page] or [github page].

[main page]: https://mattiasfredriksson.github.io/py-c3d/
[github page]: https://github.com/EmbodiedCognition/py-c3d

.. include:: ../docs/examples.md

"""
from . import dtypes
from . import group
from . import header
from . import manager
from . import parameter
from . import utils
from .reader import Reader
from .writer import Writer

Sub-modules

c3d.dtypes

State object defining the data types associated with a given .c3d processor format.

c3d.group

Classes used to represent the concept of parameter groups in a .c3d file.

c3d.header

Defines the header class used for reading, writing and tracking metadata in the .c3d header.

c3d.manager

Manager base class defining common attributes for both Reader and Writer instances.

c3d.parameter

Classes used to represent the concept of a parameter in a .c3d file.

c3d.reader

Contains the Reader class for reading C3D files.

c3d.utils

Trailing utility functions.

c3d.writer

Contains the Writer class for writing C3D files.