Пример #1
0
def test_create_and_read_c3d_with_nan():
    # Load an empty c3d structure
    c3d = ezc3d.c3d()

    # Fill it with random data
    point_names = ("point1", "point2")
    point_frame_rate = 100
    n_second = 2
    points = np.random.rand(3, len(point_names),
                            point_frame_rate * n_second) * np.nan

    analog_names = ("analog1", "analog2")
    analog_frame_rate = 1000
    analogs = np.random.rand(1, len(analog_names),
                             analog_frame_rate * n_second) * np.nan

    c3d["parameters"]["POINT"]["RATE"]["value"] = [100]
    c3d["parameters"]["POINT"]["LABELS"]["value"] = point_names
    c3d["data"]["points"] = points

    c3d["parameters"]["ANALOG"]["RATE"]["value"] = [1000]
    c3d["parameters"]["ANALOG"]["LABELS"]["value"] = analog_names
    c3d["data"]["analogs"] = analogs

    # Write and read back the data
    c3d.write("temporary.c3d")
    c3d_to_compare = ezc3d.c3d("temporary.c3d")

    # Compare the read c3d
    np.testing.assert_equal(np.sum(np.isnan(c3d_to_compare["data"]["points"])),
                            3 * len(point_names) * point_frame_rate * n_second)
    np.testing.assert_equal(
        np.sum(np.isnan(c3d_to_compare["data"]["analogs"])),
        len(analog_names) * analog_frame_rate * n_second)
Пример #2
0
def test_create_and_read_c3d_with_nan():
    # Load an empty c3d structure
    c3d = ezc3d.c3d()

    # Fill it with random data
    point_names = ('point1', 'point2')
    point_frame_rate = 100
    n_second = 2
    points = np.random.rand(3, len(point_names),
                            point_frame_rate * n_second) * np.nan

    analog_names = ('analog1', 'analog2')
    analog_frame_rate = 1000
    analogs = np.random.rand(1, len(analog_names),
                             analog_frame_rate * n_second) * np.nan

    c3d['parameters']['POINT']['RATE']['value'] = [100]
    c3d['parameters']['POINT']['LABELS']['value'] = point_names
    c3d['data']['points'] = points

    c3d['parameters']['ANALOG']['RATE']['value'] = [1000]
    c3d['parameters']['ANALOG']['LABELS']['value'] = analog_names
    c3d['data']['analogs'] = analogs

    # Write and read back the data
    c3d.write("temporary.c3d")
    c3d_to_compare = ezc3d.c3d("temporary.c3d")

    # Compare the read c3d
    np.testing.assert_equal(np.sum(np.isnan(c3d_to_compare['data']['points'])),
                            3 * len(point_names) * point_frame_rate * n_second)
    np.testing.assert_equal(
        np.sum(np.isnan(c3d_to_compare['data']['analogs'])),
        len(analog_names) * analog_frame_rate * n_second)
Пример #3
0
def test_deepcopy():
    # Load an empty c3d structure
    c3d = ezc3d.c3d()

    # Fill it with random data
    point_names = ("point1", "point2", "point3", "point4", "point5")
    point_frame_rate = 100
    n_second = 2
    points = np.random.rand(4, len(point_names), point_frame_rate * n_second)
    points[3, :, :] = 1

    analog_names = ("analog1", "analog2", "analog3", "analog4", "analog5", "analog6")
    analog_frame_rate = 1000
    analogs = np.random.rand(1, len(analog_names), analog_frame_rate * n_second)

    c3d["parameters"]["POINT"]["RATE"]["value"] = [100]
    c3d["parameters"]["POINT"]["LABELS"]["value"] = point_names
    c3d["data"]["points"] = points

    c3d["parameters"]["ANALOG"]["RATE"]["value"] = [1000]
    c3d["parameters"]["ANALOG"]["LABELS"]["value"] = analog_names
    c3d["data"]["analogs"] = analogs

    # Add a custom parameter to the POINT group
    point_new_param = ("POINT", "newPointParam", (1.0, 2.0, 3.0))
    c3d.add_parameter(point_new_param[0], point_new_param[1], point_new_param[2])

    # Add a custom parameter a new group
    new_group_param = ("NewGroup", "newGroupParam", ["MyParam1", "MyParam2"])
    c3d.add_parameter(new_group_param[0], new_group_param[1], new_group_param[2])

    # Deepcopy the c3d
    c3d_deepcopied = deepcopy(c3d)

    # Change some of its values
    change_new_group_param = ("NewGroup", "newGroupParam", ["MyParam3", "MyParam4"])
    c3d_deepcopied.add_parameter(change_new_group_param[0], change_new_group_param[1], change_new_group_param[2])
    c3d_deepcopied["data"]["points"][:3, :, :] = 0

    # Write the new file and read it back
    c3d_deepcopied.write("temporary.c3d")
    c3d_loaded = ezc3d.c3d("temporary.c3d")

    # Check that the new value changed, but not the old one
    assert c3d["parameters"]["NewGroup"]["newGroupParam"]["value"] == ["MyParam1", "MyParam2"]
    assert c3d_deepcopied["parameters"]["NewGroup"]["newGroupParam"]["value"] == ["MyParam3", "MyParam4"]
    assert c3d_loaded["parameters"]["NewGroup"]["newGroupParam"]["value"] == ["MyParam3", "MyParam4"]

    np.testing.assert_almost_equal(
        c3d["data"]["points"][:3, :, :] - c3d_deepcopied["data"]["points"][:3, :, :], c3d["data"]["points"][:3, :, :]
    )
    np.testing.assert_almost_equal(c3d["data"]["points"][3, :, :], c3d_deepcopied["data"]["points"][3, :, :])
    np.testing.assert_almost_equal(
        c3d["data"]["points"][:3, :, :] - c3d_loaded["data"]["points"][:3, :, :], c3d["data"]["points"][:3, :, :]
    )
    np.testing.assert_almost_equal(c3d["data"]["points"][3, :, :], c3d_loaded["data"]["points"][3, :, :])
Пример #4
0
def test_add_events():
    # Add an event to a file that does not have any before
    c3d = ezc3d.c3d("test/c3dTestFiles/Optotrak.c3d")
    c3d.add_event(
        [0, 0.1],
        label="MyNewEvent",
        context="Left",
        icon_id=2,
        subject="Me",
        description="Hey! This is new!",
        generic_flag=1,
    )
    c3d.add_event([0, 0.2])
    c3d.write("temporary.c3d")
    c3d_to_compare = ezc3d.c3d("temporary.c3d")
    np.testing.assert_equal(c3d_to_compare["parameters"]["EVENT"]["USED"]["value"][0], 2)
    np.testing.assert_almost_equal(
        c3d_to_compare["parameters"]["EVENT"]["TIMES"]["value"], [[0.0, 0.0], [0.1, 0.2]], decimal=6
    )
    np.testing.assert_equal(c3d_to_compare["parameters"]["EVENT"]["CONTEXTS"]["value"], ["Left", ""])
    np.testing.assert_equal(c3d_to_compare["parameters"]["EVENT"]["LABELS"]["value"], ["MyNewEvent", ""])
    np.testing.assert_equal(c3d_to_compare["parameters"]["EVENT"]["DESCRIPTIONS"]["value"], ["Hey! This is new!", ""])
    np.testing.assert_equal(c3d_to_compare["parameters"]["EVENT"]["SUBJECTS"]["value"], ["Me", ""])
    np.testing.assert_equal(c3d_to_compare["parameters"]["EVENT"]["ICON_IDS"]["value"], [2, 0])
    np.testing.assert_equal(c3d_to_compare["parameters"]["EVENT"]["GENERIC_FLAGS"]["value"], [1, 0])

    # Add an event to a file did have events before
    c3d = c3d_to_compare
    c3d.add_event(
        [0, 0.3],
        label="MySecondNewEvent",
        context="Right",
        icon_id=3,
        subject="You",
        description="Hey! This is new again!",
        generic_flag=2,
    )
    c3d.add_event([0, 0.4])
    c3d.write("temporary.c3d")
    c3d_to_compare = ezc3d.c3d("temporary.c3d")
    np.testing.assert_equal(c3d_to_compare["parameters"]["EVENT"]["USED"]["value"][0], 4)
    np.testing.assert_almost_equal(
        c3d_to_compare["parameters"]["EVENT"]["TIMES"]["value"], [[0.0, 0.0, 0.0, 0.0], [0.1, 0.2, 0.3, 0.4]], decimal=6
    )
    np.testing.assert_equal(c3d_to_compare["parameters"]["EVENT"]["CONTEXTS"]["value"], ["Left", "", "Right", ""])
    np.testing.assert_equal(
        c3d_to_compare["parameters"]["EVENT"]["LABELS"]["value"], ["MyNewEvent", "", "MySecondNewEvent", ""]
    )
    np.testing.assert_equal(
        c3d_to_compare["parameters"]["EVENT"]["DESCRIPTIONS"]["value"],
        ["Hey! This is new!", "", "Hey! This is new again!", ""],
    )
    np.testing.assert_equal(c3d_to_compare["parameters"]["EVENT"]["SUBJECTS"]["value"], ["Me", "", "You", ""])
    np.testing.assert_equal(c3d_to_compare["parameters"]["EVENT"]["ICON_IDS"]["value"], [2, 0, 3, 0])
    np.testing.assert_equal(c3d_to_compare["parameters"]["EVENT"]["GENERIC_FLAGS"]["value"], [1, 0, 2, 0])
Пример #5
0
def c3d_build_rebuild(request):
    base_folder = Path("test/c3dTestFiles")
    orig_file = Path(base_folder / (request.param + ".c3d"))
    rebuild_file = Path(base_folder / (request.param + "_after.c3d"))

    original = ezc3d.c3d(orig_file.as_posix())
    original.write(rebuild_file.as_posix())
    rebuilt = ezc3d.c3d(rebuild_file.as_posix())

    yield (original, rebuilt)

    Path.unlink(rebuild_file)
Пример #6
0
def c3d_build_rebuild_reduced(request):
    base_folder = Path("test/c3dTestFiles")
    orig_file = Path(base_folder / (request.param + ".c3d"))
    rebuild_file = Path(base_folder / (request.param + "_after.c3d"))

    original = ezc3d.c3d(orig_file.as_posix())
    original.write(rebuild_file.as_posix())
    rebuilt = ezc3d.c3d(rebuild_file.as_posix())
    if request.param == "C3DRotationExample":
        rebuilt["parameters"]["ROTATION"]["DATA_START"]["value"][0] = 6

    yield (original, rebuilt)

    Path.unlink(rebuild_file)
Пример #7
0
def Get_Event(file):
    # Find event from c3d file : heel strike (HS) and toe off (TO)
    # Determine the indexes of the beginning and end of each phases

    measurements = c3d(file)
    time = np.reshape(
        np.reshape(measurements['parameters']['EVENT']['TIMES']['value'],
                   (7 * 2, 1)), (7, 2))[:, 1]
    labels_time = measurements['parameters']['EVENT']['LABELS']['value']
    freq = measurements['parameters']['POINT']['RATE']['value'][0]
    get_indexes = lambda x, xs: [
        i for (y, i) in zip(xs, range(len(xs))) if x == y
    ]

    RHS = time[get_indexes('RHS', labels_time)]
    RTO = time[get_indexes('RTO', labels_time)]
    if len(RTO) > 1:
        RTO = max(RTO)
    else:
        RTO = RTO[0]

    start = round(RHS[0] * freq) + 1
    stop_stance = round(RTO * freq) + 1
    stop = round(RHS[1] * freq) + 1

    return start, stop_stance, stop
Пример #8
0
	def RetrieveC3dData (self, fullPath):

		# Create some dictionaries to store data 
		self.Gen = {'PathName':[],'FileName':[],'SubjName':[], 'SubjMass':[],'SubjHeight':[],'ModelUsed':[],
					   'NumbItems':[],'Vid_FirstFrame':[],'Vid_LastFrame':[],'Vid_SampRate':[],
					   'Analog_FirstFrame':[],'Analog_LastFrame':[],'Analog_SampRate':[],'Analog_NumbChan':[],'AnalogUnits':[], 
				       'PointsUnit':[], 'AnglesUnit':[], 'ForcesUnit':[], 'MomentsUnit':[],'PowersUnit':[],'ScalarsUnit':[],
					   'SubjLLegLength':[],'SubjRLegLength':[], 'ForcePlateOrigin':[]}

		self.Labels = {'PointsName':[],'Markers':[], 'Angles':[],'Scalars':[],'Powers':[], 'Forces':[],'Moments':[], 'AnalogsName':[],
		 'EventLabels':[], 'AnalysisNames':[]}

		self.Data = {'AllPoints':[], 'Markers':[], 'Angles':[],'Scalars':[],'Powers':[], 'Forces':[],'Moments':[], 'Analogs':[]}

		# returns a handle to RetrieveC3dData
		self.c3d = c3d(os.path.join(fullPath))  

		self.GetHeader(fullPath)
		self.GetSubjects()
		self.GetPoint()
		self.GetAnalog()
		self.GetForcePlatForm()
		self.GetEventContext()
		self.GetAnalysis()
		self.GetProcessing()
Пример #9
0
    def from_c3d(cls, filename, idx=None, names=None, prefix=None):
        """
        Read c3d data and convert to Vectors3d format
        Parameters
        ----------
        filename : Union[str, Path]
            Path of file
        idx : list(int)
            Order of columns given by index
        names : list(str)
            Order of columns given by names, if both names and idx are provided, an error occurs
        prefix : str
            Prefix to remove in the header

        Returns
        -------
        Data set in Vectors3d format or Data set in Vectors3d format and metadata dict if get_metadata is True
        """
        if names and idx:
            raise ValueError("names and idx can't be set simultaneously, please select only one")
        reader = ezc3d.c3d(str(filename))
        data, channel_names, metadata = cls._parse_c3d(reader, prefix)

        if names:
            metadata.update({'get_labels': names})
        else:
            metadata.update({'get_labels': []})
            names = channel_names

        return cls._to_vectors(data=data,
                               idx=idx,
                               all_names=channel_names,
                               target_names=names,
                               metadata=metadata)
Пример #10
0
def test_values():
    c3d = ezc3d.c3d("test/c3dTestFiles/Vicon.c3d")
    array = c3d["data"]["points"]
    decimal = 6

    np.testing.assert_array_equal(x=array.shape,
                                  y=(4, 51, 580),
                                  err_msg="Shape does not match")
    raveled = array.ravel()
    np.testing.assert_array_almost_equal(
        x=raveled[0],
        y=44.16278839111328,
        decimal=decimal,
    )
    np.testing.assert_array_almost_equal(
        x=raveled[-1],
        y=1.0,
        decimal=decimal,
    )
    np.testing.assert_array_almost_equal(x=np.nanmean(array),
                                         y=362.2979849093196,
                                         decimal=decimal)
    np.testing.assert_array_almost_equal(x=np.nanmedian(array),
                                         y=337.7519226074219,
                                         decimal=decimal)
    np.testing.assert_allclose(actual=np.nansum(array),
                               desired=42535594.91827867,
                               rtol=0.05)
    np.testing.assert_array_equal(x=np.isnan(array).sum(), y=915)
Пример #11
0
def test_force_platform_filter():
    c3d = ezc3d.c3d("test/c3dTestFiles/Qualisys.c3d", extract_forceplat_data=True)
    all_pf = c3d["data"]["platform"]
    np.testing.assert_equal(len(all_pf), 2)

    # Frames
    np.testing.assert_equal(all_pf[0]["force"].shape[1], 3400)
    np.testing.assert_equal(all_pf[0]["moment"].shape[1], 3400)
    np.testing.assert_equal(all_pf[0]["center_of_pressure"].shape[1], 3400)
    np.testing.assert_equal(all_pf[0]["Tz"].shape[1], 3400)

    np.testing.assert_equal(all_pf[1]["force"].shape[1], 3400)
    np.testing.assert_equal(all_pf[1]["moment"].shape[1], 3400)
    np.testing.assert_equal(all_pf[1]["center_of_pressure"].shape[1], 3400)
    np.testing.assert_equal(all_pf[1]["Tz"].shape[1], 3400)

    # Units
    np.testing.assert_string_equal(all_pf[0]["unit_force"], "N")
    np.testing.assert_string_equal(all_pf[0]["unit_moment"], "Nmm")
    np.testing.assert_string_equal(all_pf[0]["unit_position"], "mm")

    np.testing.assert_string_equal(all_pf[1]["unit_force"], "N")
    np.testing.assert_string_equal(all_pf[1]["unit_moment"], "Nmm")
    np.testing.assert_string_equal(all_pf[1]["unit_position"], "mm")

    # Position of pf
    np.testing.assert_array_almost_equal(all_pf[0]["origin"], [1.524, -0.762, -34.036])
    np.testing.assert_array_almost_equal(
        all_pf[0]["corners"], [[508, 508, 0, 0], [464, 0, 0, 464], [0, 0, 0, 0]], decimal=3
    )

    np.testing.assert_array_almost_equal(all_pf[1]["origin"], [1.016, 0, -36.322])
    np.testing.assert_array_almost_equal(
        all_pf[1]["corners"], [[1017, 1017, 509, 509], [464, 0, 0, 464], [0, 0, 0, 0]], decimal=3
    )

    # Calibration matrix
    np.testing.assert_array_almost_equal(all_pf[0]["cal_matrix"], np.zeros((6, 6)))

    np.testing.assert_array_almost_equal(all_pf[1]["cal_matrix"], np.zeros((6, 6)))

    # Data at 3 different time
    expected_force = [[0.140, 106.480, -0.140], [0.046, -66.407, -0.138], [-0.184, 763.647, 0.367]]
    expected_moment = [[20.868, 54768.655, 51.780], [-4.623, -24103.676, 4.483], [-29.393, -12229.124, -29.960]]
    expected_cop = [[228.813, 285.564, 241.787], [118.296, 303.720, 373.071], [0, 0, 0]]
    expected_Tz = [[0, 0, 0], [0, 0, 0], [-44.141, -2496.299, -51.390]]
    np.testing.assert_array_almost_equal(all_pf[0]["force"][:, [0, 1000, -1]], expected_force, decimal=3)
    np.testing.assert_array_almost_equal(all_pf[0]["moment"][:, [0, 1000, -1]], expected_moment, decimal=3)
    np.testing.assert_array_almost_equal(all_pf[0]["center_of_pressure"][:, [0, 1000, -1]], expected_cop, decimal=3)
    np.testing.assert_array_almost_equal(all_pf[0]["Tz"][:, [0, 1000, -1]], expected_Tz, decimal=3)

    expected_force = [[0.046, 0.232, 0.185], [-0.185, -0.184, -0.046], [0.723, 0.361, 0.542]]
    expected_moment = [[49.366, 68.671, 16.708], [-96.907, -46.501, 50.403], [0.047, -19.720, 30.122]]
    expected_cop = [[897.0422, 891.673, 670.044], [300.283, 422.019, 262.813], [0, 0, 0]]
    expected_Tz = [[0, 0, 0], [0, 0, 0], [27.944, 48.016, 31.545]]
    np.testing.assert_array_almost_equal(all_pf[1]["force"][:, [0, 1000, -1]], expected_force, decimal=3)
    np.testing.assert_array_almost_equal(all_pf[1]["moment"][:, [0, 1000, -1]], expected_moment, decimal=3)
    np.testing.assert_array_almost_equal(all_pf[1]["center_of_pressure"][:, [0, 1000, -1]], expected_cop, decimal=3)
    np.testing.assert_array_almost_equal(all_pf[1]["Tz"][:, [0, 1000, -1]], expected_Tz, decimal=3)
Пример #12
0
def load_c3d_mocap(filename):
    import ezc3d
    c3d = ezc3d.c3d(os.fspath(filename))
    sample_rate = c3d['parameters']['POINT']['RATE']['value'][0]
    skeleton_name = c3d['parameters']['POINT']['SKEL']['value'][0]
    joints = c3d['data']['points'].transpose(2, 1,
                                             0)[..., :3].astype(np.float32)
    return Mocap(joints, skeleton_name, sample_rate)
Пример #13
0
    def __init__(self, c3d_path: str):

        # Note that we extract the relevant parameters from c3d_obj and then it should be garbage collected -
        # this results in a significant savings in memory.
        c3d_obj = c3d(c3d_path)
        self.marker_names = c3d_obj['parameters']['POINT']['LABELS']['value']
        self._marker_map = dict(zip(self.marker_names, range(len(self.marker_names))))
        self.analog_frame_rate = c3d_obj['header']['analogs']['frame_rate']
        self.marker_frame_rate = c3d_obj['header']['points']['frame_rate']
        self.marker_data = c3d_obj['data']['points']
        self.frames = np.arange(self.marker_data.shape[2])
Пример #14
0
def save_c3d_mocap(mocap: Mocap, filename):
    import ezc3d
    skeleton = skeleton_registry[mocap.skeleton_name]
    assert_plausible_skeleton(mocap.joint_positions, skeleton)
    c3d = ezc3d.c3d()
    c3d['parameters']['POINT']['RATE']['value'] = [mocap.sample_rate]
    c3d['parameters']['POINT']['UNITS']['value'] = ['mm']
    c3d['parameters']['POINT']['LABELS']['value'] = skeleton.joint_names
    c3d.add_parameter('POINT', 'SKEL', [skeleton.name])
    c3d['data']['points'] = mocap.joint_positions.transpose(2, 1, 0).astype(
        np.float64)
    c3d.write(os.fspath(filename))
Пример #15
0
def test_create_c3d():
    c3d = ezc3d.c3d()

    # Test the header
    assert c3d['header']['points']['size'] == 0
    assert c3d['header']['points']['frame_rate'] == 0.0
    assert c3d['header']['points']['first_frame'] == 0
    assert c3d['header']['points']['last_frame'] == 0

    assert c3d['header']['analogs']['size'] == 0
    assert c3d['header']['analogs']['frame_rate'] == 0.0
    assert c3d['header']['analogs']['first_frame'] == 0
    assert c3d['header']['analogs']['last_frame'] == -1

    assert c3d['header']['events']['size'] == 18
    assert c3d['header']['events']['events_time'] \
        == (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
    assert c3d['header']['events']['events_label'] \
        == ('', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '')

    # Test the parameters
    assert c3d['parameters']['POINT']['USED']['value'][0] == 0
    assert c3d['parameters']['POINT']['SCALE']['value'][0] == -1
    assert c3d['parameters']['POINT']['RATE']['value'][0] == 0.0
    assert c3d['parameters']['POINT']['FRAMES']['value'][0] == 0
    assert len(c3d['parameters']['POINT']['LABELS']['value']) == 0
    assert len(c3d['parameters']['POINT']['DESCRIPTIONS']['value']) == 0
    assert len(c3d['parameters']['POINT']['UNITS']['value']) == 0

    assert c3d['parameters']['ANALOG']['USED']['value'][0] == 0
    assert len(c3d['parameters']['ANALOG']['LABELS']['value']) == 0
    assert len(c3d['parameters']['ANALOG']['DESCRIPTIONS']['value']) == 0
    assert c3d['parameters']['ANALOG']['GEN_SCALE']['value'][0] == 1
    assert len(c3d['parameters']['ANALOG']['SCALE']['value']) == 0
    assert len(c3d['parameters']['ANALOG']['OFFSET']['value']) == 0
    assert len(c3d['parameters']['ANALOG']['UNITS']['value']) == 0
    assert c3d['parameters']['ANALOG']['RATE']['value'][0] == 0.0
    assert len(c3d['parameters']['ANALOG']['FORMAT']['value']) == 0
    assert len(c3d['parameters']['ANALOG']['BITS']['value']) == 0

    assert c3d['parameters']['FORCE_PLATFORM']['USED']['value'][0] == 0
    assert len(c3d['parameters']['FORCE_PLATFORM']['TYPE']['value']) == 0
    assert np.all(c3d['parameters']['FORCE_PLATFORM']['ZERO']['value'] == (1,
                                                                           0))
    assert len(c3d['parameters']['FORCE_PLATFORM']['CORNERS']['value']) == 0
    assert len(c3d['parameters']['FORCE_PLATFORM']['ORIGIN']['value']) == 0
    assert len(c3d['parameters']['FORCE_PLATFORM']['CHANNEL']['value']) == 0
    assert len(c3d['parameters']['FORCE_PLATFORM']['CAL_MATRIX']['value']) == 0

    # Test the data
    assert c3d['data']['points'].shape == (4, 0, 0)
    assert c3d['data']['analogs'].shape == (1, 0, 0)
Пример #16
0
	def __init__(self, path):
		self.path =path
		self.c = c3d()
		self.c = c3d(self.path)
		self.point_data = self.c['data']['points']
		self.points_residuals = self.c['data']['meta_points']['residuals']
		self.analog_data = self.c['data']['analogs']
		self.labels = self.c['parameters']['POINT']['LABELS']['value']

		self.length = self.point_data[0][0,:].shape[0]
		self.T = np.arange(0, self.length)
		self.frequency = 250

		self.BVHTop = ''
		self.BVHDict = {}
		self.Channeldict = {}
		self.Offset_dict = {}

		self.BVH_means = {}
		self.BVH_variance = {}
		self.BVH_locale = {}
		self.BVH_Data = {}
Пример #17
0
def read_c3d(
    caller: Callable,
    filename: Union[str, Path],
    usecols: Optional[List[Union[str, int]]] = None,
    prefix_delimiter: Optional[str] = None,
    suffix_delimiter: Optional[str] = None,
    attrs: Optional[dict] = None,
) -> xr.DataArray:
    group = "ANALOG" if caller.__name__ == "Analogs" else "POINT"

    reader = ezc3d.c3d(f"{filename}").c3d_swig
    columns = [
        col_spliter(label, prefix_delimiter, suffix_delimiter) for label in
        reader.parameters().group(group).parameter("LABELS").valuesAsString()
    ]

    get_data_function = getattr(reader, f"get_{group.lower()}s")

    if usecols:
        if isinstance(usecols[0], str):
            idx = [columns.index(channel) for channel in usecols]
        elif isinstance(usecols[0], int):
            idx = usecols
        else:
            raise ValueError(
                "usecols should be None, list of string or list of int."
                f"You provided {type(usecols)}")
        data = get_data_function()[:, idx, :]
        channels = [columns[i] for i in idx]
    else:
        data = get_data_function()
        channels = columns

    data_by_frame = 1 if group == "POINT" else reader.header().nbAnalogByFrame(
    )

    attrs = attrs if attrs else {}
    attrs["first_frame"] = reader.header().firstFrame() * data_by_frame
    attrs["last_frame"] = reader.header().lastFrame() * data_by_frame
    attrs["rate"] = reader.header().frameRate() * data_by_frame
    attrs["units"] = (reader.parameters().group(group).parameter(
        "UNITS").valuesAsString()[0])

    time = np.linspace(start=0,
                       stop=data.shape[-1] / attrs["rate"],
                       num=data.shape[-1],
                       endpoint=False)
    return caller(data[0, ...] if group == "ANALOG" else data,
                  channels,
                  time,
                  attrs=attrs)
Пример #18
0
    def __init__(self, file_path):
        self.c3d = c3d(file_path, extract_forceplat_data=True)
        self.marker_names = [
            "L_IAS",
            "L_IPS",
            "R_IPS",
            "R_IAS",
            "R_FTC",
            "R_Thigh_Top",
            "R_Thigh_Down",
            "R_Thigh_Front",
            "R_Thigh_Back",
            "R_FLE",
            "R_FME",
            "R_FAX",
            "R_TTC",
            "R_Shank_Top",
            "R_Shank_Down",
            "R_Shank_Front",
            "R_Shank_Tibia",
            "R_FAL",
            "R_TAM",
            "R_FCC",
            "R_FM1",
            "R_FMP1",
            "R_FM2",
            "R_FMP2",
            "R_FM5",
            "R_FMP5",
        ]
        self.muscle_names = [
            "R_Tibialis_Anterior",
            "R_Soleus",
            "R_Gastrocnemius_Lateralis",
            "R_Gastrocnemius_Medialis",
            "R_Vastus_Medialis",
            "R_Rectus_Femoris",
            "R_Biceps_Femoris",
            "R_Semitendinosus",
            "R_Gluteus_Medius",
            "R_Gluteus_Maximus",
        ]

        self.trajectories = self.get_marker_trajectories(
            self.c3d, self.marker_names)
        self.forces = self.get_forces(self.c3d)
        self.moments = self.get_moment(self.c3d)
        self.cop = self.get_cop(self.c3d)
        self.emg = self.get_emg(self.c3d, self.muscle_names)
        self.indices = self.get_indices()
        self.phase_time = self.get_time()
Пример #19
0
def test_rotations():
    c3d = ezc3d.c3d("test/c3dTestFiles/C3DRotationExample.c3d")
    array = c3d["data"]["rotations"]
    decimal = 6

    np.testing.assert_array_equal(x=array.shape, y=(4, 4, 21, 340), err_msg="Shape does not match")
    raveled = array.ravel()
    np.testing.assert_array_almost_equal(
        x=array[2, 3, 2, 5],
        y=931.6382446289062,
        decimal=decimal,
    )
    np.testing.assert_array_almost_equal(
        x=raveled[-1],
        y=1.0,
        decimal=decimal,
    )
    np.testing.assert_array_almost_equal(x=np.nansum(array), y=9367125.137371363, decimal=decimal)
Пример #20
0
def GetGroundReactionForces(file):
    measurements = c3d(file)
    analog = measurements['data']['analogs']
    labels_analog = measurements['parameters']['ANALOG']['LABELS']['value']
    nbPF = measurements['parameters']['FORCE_PLATFORM']['USED']['value'][0][0]

    GRF = np.zeros((len(analog[0, 0, :]), 3, nbPF))
    for p in range(nbPF):
        GRF[:, 0,
            p] = analog[0, labels_analog.index("Fx" +
                                               str(p + 1)), :].squeeze()  # Fx
        GRF[:, 1,
            p] = analog[0, labels_analog.index("Fy" +
                                               str(p + 1)), :].squeeze()  # Fy
        GRF[:, 2,
            p] = -analog[0, labels_analog.index("Fz" +
                                                str(p + 1)), :].squeeze()  # Fz
    return GRF
Пример #21
0
def GetMoment(file):
    measurements = c3d(file)
    analog = measurements['data']['analogs']
    labels_analog = measurements['parameters']['ANALOG']['LABELS']['value']
    nbPF = measurements['parameters']['FORCE_PLATFORM']['USED']['value'][0][0]

    M = np.zeros((len(analog[0, 0, :]), 3, nbPF))
    for p in range(nbPF):
        M[:,
          0, p] = analog[0, labels_analog.index("Mx" + str(p + 1)), :].squeeze(
          ) * 1e-3  # Fx
        M[:,
          1, p] = analog[0, labels_analog.index("My" + str(p + 1)), :].squeeze(
          ) * 1e-3  # Fy
        M[:,
          2, p] = analog[0, labels_analog.index("Mz" + str(p + 1)), :].squeeze(
          ) * 1e-3  # Fz

    return M
Пример #22
0
    def __init__(self, file_path):
        self.c3d = c3d(file_path, extract_forceplat_data=True)
        self.marker_names = [
            "L_IAS",
            "L_IPS",
            "R_IPS",
            "R_IAS",
            "R_FTC",
            "R_Thigh_Top",
            "R_Thigh_Down",
            "R_Thigh_Front",
            "R_Thigh_Back",
            "R_FLE",
            "R_FME",
            "R_FAX",
            "R_TTC",
            "R_Shank_Top",
            "R_Shank_Down",
            "R_Shank_Front",
            "R_Shank_Tibia",
            "R_FAL",
            "R_TAM",
            "R_FCC",
            "R_FM1",
            "R_FMP1",
            "R_FM2",
            "R_FMP2",
            "R_FM5",
            "R_FMP5",
        ]

        self.trajectories = self.get_marker_trajectories(
            self.c3d, self.marker_names)
        self.forces = self.get_forces(self.c3d)
        self.moments = self.get_moment(self.c3d)
        self.cop = self.get_cop(self.c3d)
        self.events = self.get_event_rhs_rto(self.c3d)
        self.indices = self.get_indices()
        self.phase_time = self.get_time()
Пример #23
0
def get_events(fname, missing=np.nan):
    """Get events from c3d file.
    """
    c3d = ezc3d.c3d(fname).c3d_swig
    events = {
        '0': [np.inf, ''],
        '1': [-np.inf, ''],
        'LFS': [missing],
        'LFO': [missing],
        'RFS': [missing],
        'RFO': [missing]
    }
    if c3d.parameters().isGroup('EVENT'):
        labels = c3d.parameters().group('EVENT').parameter(
            'LABELS').valuesAsString()
        contexts = c3d.parameters().group('EVENT').parameter(
            'CONTEXTS').valuesAsString()
        times = np.round(
            np.array(c3d.parameters().group('EVENT').parameter(
                'TIMES').valuesAsDouble())[1::2], 6)
        #if times[-1] < times[0]:  # delete possible out-of-order event at the end
        #    times, labels, contexts = times[:-1], labels[:-1], contexts[:-1]
        evs = {}
        for label, context, time in zip(labels, contexts, times):
            key = context + ' ' + label
            key2 = ''.join([i[0] for i in key.strip().split(' ')]).upper()
            evs[key2] = np.r_[evs[key2], np.atleast_1d(time)] if \
                        key2 in evs.keys() else np.atleast_1d(time)
            if time < events['0'][0]:
                events['0'] = [time, key2]
            if time > events['1'][0]:
                events['1'] = [time, key2]
        for ev in evs:
            if len(ev) > 1:
                evs[ev] = np.sort(evs[ev])
        events.update(evs)

    return events
Пример #24
0
def ComputeCoP(file):
    measurements = c3d(file)
    analog = measurements['data']['analogs']
    nbPF = measurements['parameters']['FORCE_PLATFORM']['USED']['value'][0][0]
    corners = np.reshape(
        np.reshape(
            measurements['parameters']['FORCE_PLATFORM']['CORNERS']['value'] *
            1e-3, (3 * 4 * 2, 1)), (2, 4, 3))  #platform x corners x coord

    CoP1 = np.zeros(((len(analog[0, 0, :]), 3, nbPF)))
    CoP = np.zeros(((len(analog[0, 0, :]), 3, nbPF)))
    F = GetForces(file)
    M = GetMoment(file)

    for p in range(nbPF):
        # Attention X et Y sont inversés sur la plaque !!!
        CoP1[:, 0, p] = np.divide(M[:, 0, p], F[:, 2, p])  # Mx/Fz
        CoP1[:, 1, p] = -np.divide(M[:, 1, p], F[:, 2, p])  # -My/Fz
        CoP1[:, :, p][np.isnan(CoP1[:, :, p])] = 0

        # Center of the platform
        if p == 0:
            CoP[:, 0,
                p] = (corners[p, 1, 0] -
                      corners[p, 2, 0]) / 2 + CoP1[:, 0, p]  # xcenter + CoPx
            CoP[:, 1,
                p] = (corners[p, 0, 1] -
                      corners[p, 1, 1]) / 2 + CoP1[:, 1, p]  # ycenter + CoPy
        else:
            CoP[:, 0,
                p] = corners[p, 2, 0] + (corners[p, 1, 0] -
                                         corners[p, 2, 0]) / 2 + CoP1[:, 0, p]
            CoP[:, 1,
                p] = (corners[p, 0, 1] - corners[p, 1, 1]) / 2 + CoP1[:, 1, p]

    return CoP
Пример #25
0
def test_ezc3d():
    c3d = ezc3d.c3d(f"{MARKERS_ANALOGS_C3D}")
    is_expected_array(xr.DataArray(c3d["data"]["points"]),
                      **EXPECTED_VALUES[65])
    is_expected_array(xr.DataArray(c3d["data"]["analogs"]),
                      **EXPECTED_VALUES[66])
Пример #26
0
def test_create_and_read_c3d():
    # Load an empty c3d structure
    c3d = ezc3d.c3d()

    # Fill it with random data
    point_names = ('point1', 'point2', 'point3', 'point4', 'point5')
    point_frame_rate = 100
    n_second = 2
    points = np.random.rand(3, len(point_names), point_frame_rate * n_second)

    analog_names = ('analog1', 'analog2', 'analog3', 'analog4', 'analog5',
                    'analog6')
    analog_frame_rate = 1000
    analogs = np.random.rand(1, len(analog_names),
                             analog_frame_rate * n_second)

    c3d['parameters']['POINT']['RATE']['value'] = [100]
    c3d['parameters']['POINT']['LABELS']['value'] = point_names
    c3d['data']['points'] = points

    c3d['parameters']['ANALOG']['RATE']['value'] = [1000]
    c3d['parameters']['ANALOG']['LABELS']['value'] = analog_names
    c3d['data']['analogs'] = analogs

    # Add a custom parameter to the POINT group
    point_new_param = ("POINT", "newPointParam", (1.0, 2.0, 3.0))
    c3d.add_parameter(point_new_param[0], point_new_param[1],
                      point_new_param[2])

    # Add a custom parameter a new group
    new_group_param = ("NewGroup", "newGroupParam", ["MyParam1", "MyParam2"])
    c3d.add_parameter(new_group_param[0], new_group_param[1],
                      new_group_param[2])

    # Write and read back the data
    c3d.write("temporary.c3d")
    c3d_to_compare = ezc3d.c3d("temporary.c3d")

    # Test the header
    assert c3d_to_compare['header']['points']['size'] == len(point_names)
    assert c3d_to_compare['header']['points']['frame_rate'] == point_frame_rate
    assert c3d_to_compare['header']['points']['first_frame'] == 0
    assert c3d_to_compare['header']['points'][
        'last_frame'] == point_frame_rate * n_second - 1

    assert c3d_to_compare['header']['analogs']['size'] == len(analog_names)
    assert c3d_to_compare['header']['analogs'][
        'frame_rate'] == analog_frame_rate
    assert c3d_to_compare['header']['analogs']['first_frame'] == 0
    assert c3d_to_compare['header']['analogs'][
        'last_frame'] == analog_frame_rate * n_second - 1

    assert c3d_to_compare['header']['events']['size'] == 18
    assert c3d_to_compare['header']['events']['events_time'] == \
        (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
    assert c3d_to_compare['header']['events']['events_label'] == \
        ('', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '')

    # Test the parameters
    assert c3d_to_compare['parameters']['POINT']['USED']['value'][0] == len(
        point_names)
    assert c3d_to_compare['parameters']['POINT']['SCALE']['value'][0] == -1.0
    assert c3d_to_compare['parameters']['POINT']['RATE']['value'][
        0] == point_frame_rate
    assert c3d_to_compare['parameters']['POINT']['FRAMES']['value'][
        0] == point_frame_rate * n_second
    assert c3d_to_compare['parameters']['POINT']['LABELS']['value'] == list(
        point_names)
    assert c3d_to_compare['parameters']['POINT']['DESCRIPTIONS']['value'] == [
        "" for _ in point_names
    ]
    assert len(c3d_to_compare['parameters']['POINT']['UNITS']['value']) == 0
    assert np.all(c3d_to_compare['parameters'][point_new_param[0]][
        point_new_param[1]]['value'] == point_new_param[2])

    assert c3d_to_compare['parameters']['ANALOG']['USED']['value'][0] == len(
        analog_names)
    assert c3d_to_compare['parameters']['ANALOG']['LABELS']['value'] == list(
        analog_names)
    assert c3d_to_compare['parameters']['ANALOG']['DESCRIPTIONS']['value'] == [
        "" for _ in analog_names
    ]
    assert c3d_to_compare['parameters']['ANALOG']['GEN_SCALE']['value'][0] == 1
    assert np.all(c3d_to_compare['parameters']['ANALOG']['SCALE']['value'] ==
                  tuple([1.0 for _ in analog_names]))
    assert np.all(c3d_to_compare['parameters']['ANALOG']['OFFSET']['value'] ==
                  tuple([0 for _ in analog_names]))
    assert c3d_to_compare['parameters']['ANALOG']['UNITS']['value'] == [
        "" for _ in analog_names
    ]
    assert c3d_to_compare['parameters']['ANALOG']['RATE']['value'][
        0] == analog_frame_rate
    assert len(c3d_to_compare['parameters']['ANALOG']['FORMAT']['value']) == 0
    assert len(c3d_to_compare['parameters']['ANALOG']['BITS']['value']) == 0

    assert c3d_to_compare['parameters']['FORCE_PLATFORM']['USED']['value'][
        0] == 0
    assert len(
        c3d_to_compare['parameters']['FORCE_PLATFORM']['TYPE']['value']) == 0
    assert np.all(
        c3d_to_compare['parameters']['FORCE_PLATFORM']['ZERO']['value'] == (1,
                                                                            0))
    assert len(c3d_to_compare['parameters']['FORCE_PLATFORM']['CORNERS']
               ['value']) == 0
    assert len(
        c3d_to_compare['parameters']['FORCE_PLATFORM']['ORIGIN']['value']) == 0
    assert len(c3d_to_compare['parameters']['FORCE_PLATFORM']['CHANNEL']
               ['value']) == 0
    assert len(c3d_to_compare['parameters']['FORCE_PLATFORM']['CAL_MATRIX']
               ['value']) == 0

    assert c3d_to_compare['parameters'][new_group_param[0]][new_group_param[1]]['value'] \
        == new_group_param[2]

    # Test the data
    assert c3d_to_compare['data']['points'].shape == (4, len(point_names),
                                                      point_frame_rate *
                                                      n_second)
    assert c3d_to_compare['data']['analogs'].shape == (1, len(analog_names),
                                                       analog_frame_rate *
                                                       n_second)

    # Compare the read c3d
    np.testing.assert_almost_equal(c3d_to_compare['data']['points'][0:3, :, :],
                                   points)
    np.testing.assert_almost_equal(c3d_to_compare['data']['analogs'], analogs)
Пример #27
0
# import c3d

# with open('E:/VCL/Users/tofis/Data/DATASETS/RGBDIRD_MOCAP_DATASET/Data/ARTANIM/Vicon/Ball_Calibrations/CalibrationBallSequence.c3d', 'rb') as handle:
#     reader = c3d.Reader(handle)
#     for i, (points, analog) in enumerate(reader.read_frames()):
#         print('Frame {}: {}'.format(i, points.round(2)))

import os
from ezc3d import c3d

path = 'E:/VCL/Users/tofis/Data/DATASETS/RGBDIRD_MOCAP_DATASET/Data/ARTANIM/Vicon/Ball_Calibrations'
file = 'Bart_CalibrationBallSequence_04.c3d'

c = c3d(os.path.join(path, file))
print(c['parameters']['POINT']['USED']['value'][0])
# Print the number of points used
point_data = c['data']['points']

f = open(os.path.join(path, file.replace('c3d', 'txt')), 'w')
for i in range(0, point_data.shape[2]):
    f.write(
        str(point_data[0][0][i]) + " " + str(point_data[1][0][i]) + " " +
        str(point_data[2][0][i]) + "\n")

f.close()
Пример #28
0
    def RetrieveC3dData(self, fullPath):

        # Create some dictionaries to store data
        self.Gen = {
            "PathName": [],
            "FileName": [],
            "SubjName": [],
            "SubjMass": [],
            "SubjHeight": [],
            "ModelUsed": [],
            "NumbItems": [],
            "Vid_FirstFrame": [],
            "Vid_LastFrame": [],
            "Vid_SampRate": [],
            "Analog_FirstFrame": [],
            "Analog_LastFrame": [],
            "Analog_SampRate": [],
            "Analog_NumbChan": [],
            "AnalogUnits": [],
            "PointsUnit": [],
            "AnglesUnit": [],
            "ForcesUnit": [],
            "MomentsUnit": [],
            "PowersUnit": [],
            "ScalarsUnit": [],
            "SubjLLegLength": [],
            "SubjRLegLength": [],
            "ForcePlateOrigin": [],
        }

        self.Labels = {
            "PointsName": [],
            "Markers": [],
            "Angles": [],
            "Scalars": [],
            "Powers": [],
            "Forces": [],
            "Moments": [],
            "AnalogsName": [],
            "EventLabels": [],
            "AnalysisNames": [],
        }

        self.Data = {
            "AllPoints": [],
            "Markers": [],
            "Angles": [],
            "Scalars": [],
            "Powers": [],
            "Forces": [],
            "Moments": [],
            "Analogs": [],
        }

        # returns a handle to RetrieveC3dData
        self.c3d = c3d(os.path.join(fullPath))

        self.GetHeader(fullPath)
        self.GetSubjects()
        self.GetPoint()
        self.GetAnalog()
        self.GetForcePlatForm()
        self.GetEventContext()
        self.GetAnalysis()
        self.GetProcessing()
Пример #29
0
def test_create_c3d():
    c3d = ezc3d.c3d()

    # Test the header
    assert c3d["header"]["points"]["size"] == 0
    assert c3d["header"]["points"]["frame_rate"] == 0.0
    assert c3d["header"]["points"]["first_frame"] == 0
    assert c3d["header"]["points"]["last_frame"] == 0

    assert c3d["header"]["analogs"]["size"] == 0
    assert c3d["header"]["analogs"]["frame_rate"] == 0.0
    assert c3d["header"]["analogs"]["first_frame"] == 0
    assert c3d["header"]["analogs"]["last_frame"] == -1

    assert c3d["header"]["events"]["size"] == 18
    assert c3d["header"]["events"]["events_time"] == (
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
    )
    assert c3d["header"]["events"]["events_label"] == (
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
    )

    # Test the parameters
    assert c3d["parameters"]["POINT"]["USED"]["value"][0] == 0
    assert c3d["parameters"]["POINT"]["SCALE"]["value"][0] == -1
    assert c3d["parameters"]["POINT"]["RATE"]["value"][0] == 0.0
    assert c3d["parameters"]["POINT"]["FRAMES"]["value"][0] == 0
    assert len(c3d["parameters"]["POINT"]["LABELS"]["value"]) == 0
    assert len(c3d["parameters"]["POINT"]["DESCRIPTIONS"]["value"]) == 0
    assert len(c3d["parameters"]["POINT"]["UNITS"]["value"]) == 0

    assert c3d["parameters"]["ANALOG"]["USED"]["value"][0] == 0
    assert len(c3d["parameters"]["ANALOG"]["LABELS"]["value"]) == 0
    assert len(c3d["parameters"]["ANALOG"]["DESCRIPTIONS"]["value"]) == 0
    assert c3d["parameters"]["ANALOG"]["GEN_SCALE"]["value"][0] == 1
    assert len(c3d["parameters"]["ANALOG"]["SCALE"]["value"]) == 0
    assert len(c3d["parameters"]["ANALOG"]["OFFSET"]["value"]) == 0
    assert len(c3d["parameters"]["ANALOG"]["UNITS"]["value"]) == 0
    assert c3d["parameters"]["ANALOG"]["RATE"]["value"][0] == 0.0
    assert len(c3d["parameters"]["ANALOG"]["FORMAT"]["value"]) == 0
    assert len(c3d["parameters"]["ANALOG"]["BITS"]["value"]) == 0

    assert c3d["parameters"]["FORCE_PLATFORM"]["USED"]["value"][0] == 0
    assert len(c3d["parameters"]["FORCE_PLATFORM"]["TYPE"]["value"]) == 0
    assert np.all(c3d["parameters"]["FORCE_PLATFORM"]["ZERO"]["value"] == (1,
                                                                           0))
    assert len(c3d["parameters"]["FORCE_PLATFORM"]["CORNERS"]["value"]) == 0
    assert len(c3d["parameters"]["FORCE_PLATFORM"]["ORIGIN"]["value"]) == 0
    assert len(c3d["parameters"]["FORCE_PLATFORM"]["CHANNEL"]["value"]) == 0
    assert len(c3d["parameters"]["FORCE_PLATFORM"]["CAL_MATRIX"]["value"]) == 0

    # Test the data
    assert c3d["data"]["points"].shape == (4, 0, 0)
    assert c3d["data"]["analogs"].shape == (1, 0, 0)
Пример #30
0
def test_create_and_read_c3d():
    # Load an empty c3d structure
    c3d = ezc3d.c3d()

    # Fill it with random data
    point_names = ("point1", "point2", "point3", "point4", "point5")
    point_frame_rate = 100
    n_second = 2
    points = np.random.rand(3, len(point_names), point_frame_rate * n_second)

    analog_names = ("analog1", "analog2", "analog3", "analog4", "analog5",
                    "analog6")
    analog_frame_rate = 1000
    analogs = np.random.rand(1, len(analog_names),
                             analog_frame_rate * n_second)

    c3d["parameters"]["POINT"]["RATE"]["value"] = [100]
    c3d["parameters"]["POINT"]["LABELS"]["value"] = point_names
    c3d["data"]["points"] = points

    c3d["parameters"]["ANALOG"]["RATE"]["value"] = [1000]
    c3d["parameters"]["ANALOG"]["LABELS"]["value"] = analog_names
    c3d["data"]["analogs"] = analogs

    # Add a custom parameter to the POINT group
    point_new_param = ("POINT", "newPointParam", (1.0, 2.0, 3.0))
    c3d.add_parameter(point_new_param[0], point_new_param[1],
                      point_new_param[2])

    # Add a custom parameter a new group
    new_group_param = ("NewGroup", "newGroupParam", ["MyParam1", "MyParam2"])
    c3d.add_parameter(new_group_param[0], new_group_param[1],
                      new_group_param[2])

    # Write and read back the data
    c3d.write("temporary.c3d")
    c3d_to_compare = ezc3d.c3d("temporary.c3d")

    # Test the header
    assert c3d_to_compare["header"]["points"]["size"] == len(point_names)
    assert c3d_to_compare["header"]["points"]["frame_rate"] == point_frame_rate
    assert c3d_to_compare["header"]["points"]["first_frame"] == 0
    assert c3d_to_compare["header"]["points"][
        "last_frame"] == point_frame_rate * n_second - 1

    assert c3d_to_compare["header"]["analogs"]["size"] == len(analog_names)
    assert c3d_to_compare["header"]["analogs"][
        "frame_rate"] == analog_frame_rate
    assert c3d_to_compare["header"]["analogs"]["first_frame"] == 0
    assert c3d_to_compare["header"]["analogs"][
        "last_frame"] == analog_frame_rate * n_second - 1

    assert c3d_to_compare["header"]["events"]["size"] == 18
    assert c3d_to_compare["header"]["events"]["events_time"] == (
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
        0.0,
    )
    assert c3d_to_compare["header"]["events"]["events_label"] == (
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
    )

    # Test the parameters
    assert c3d_to_compare["parameters"]["POINT"]["USED"]["value"][0] == len(
        point_names)
    assert c3d_to_compare["parameters"]["POINT"]["SCALE"]["value"][0] == -1.0
    assert c3d_to_compare["parameters"]["POINT"]["RATE"]["value"][
        0] == point_frame_rate
    assert c3d_to_compare["parameters"]["POINT"]["FRAMES"]["value"][
        0] == point_frame_rate * n_second
    assert c3d_to_compare["parameters"]["POINT"]["LABELS"]["value"] == list(
        point_names)
    assert c3d_to_compare["parameters"]["POINT"]["DESCRIPTIONS"]["value"] == [
        "" for _ in point_names
    ]
    assert len(c3d_to_compare["parameters"]["POINT"]["UNITS"]["value"]) == 0
    assert np.all(c3d_to_compare["parameters"][point_new_param[0]][
        point_new_param[1]]["value"] == point_new_param[2])

    assert c3d_to_compare["parameters"]["ANALOG"]["USED"]["value"][0] == len(
        analog_names)
    assert c3d_to_compare["parameters"]["ANALOG"]["LABELS"]["value"] == list(
        analog_names)
    assert c3d_to_compare["parameters"]["ANALOG"]["DESCRIPTIONS"]["value"] == [
        "" for _ in analog_names
    ]
    assert c3d_to_compare["parameters"]["ANALOG"]["GEN_SCALE"]["value"][0] == 1
    assert np.all(c3d_to_compare["parameters"]["ANALOG"]["SCALE"]["value"] ==
                  tuple([1.0 for _ in analog_names]))
    assert np.all(c3d_to_compare["parameters"]["ANALOG"]["OFFSET"]["value"] ==
                  tuple([0 for _ in analog_names]))
    assert c3d_to_compare["parameters"]["ANALOG"]["UNITS"]["value"] == [
        "" for _ in analog_names
    ]
    assert c3d_to_compare["parameters"]["ANALOG"]["RATE"]["value"][
        0] == analog_frame_rate
    assert len(c3d_to_compare["parameters"]["ANALOG"]["FORMAT"]["value"]) == 0
    assert len(c3d_to_compare["parameters"]["ANALOG"]["BITS"]["value"]) == 0

    assert c3d_to_compare["parameters"]["FORCE_PLATFORM"]["USED"]["value"][
        0] == 0
    assert len(
        c3d_to_compare["parameters"]["FORCE_PLATFORM"]["TYPE"]["value"]) == 0
    assert np.all(
        c3d_to_compare["parameters"]["FORCE_PLATFORM"]["ZERO"]["value"] == (1,
                                                                            0))
    assert len(c3d_to_compare["parameters"]["FORCE_PLATFORM"]["CORNERS"]
               ["value"]) == 0
    assert len(
        c3d_to_compare["parameters"]["FORCE_PLATFORM"]["ORIGIN"]["value"]) == 0
    assert len(c3d_to_compare["parameters"]["FORCE_PLATFORM"]["CHANNEL"]
               ["value"]) == 0
    assert len(c3d_to_compare["parameters"]["FORCE_PLATFORM"]["CAL_MATRIX"]
               ["value"]) == 0

    assert c3d_to_compare["parameters"][new_group_param[0]][
        new_group_param[1]]["value"] == new_group_param[2]

    # Test the data
    assert c3d_to_compare["data"]["points"].shape == (4, len(point_names),
                                                      point_frame_rate *
                                                      n_second)
    assert c3d_to_compare["data"]["analogs"].shape == (1, len(analog_names),
                                                       analog_frame_rate *
                                                       n_second)

    # Compare the read c3d
    np.testing.assert_almost_equal(c3d_to_compare["data"]["points"][0:3, :, :],
                                   points)
    np.testing.assert_almost_equal(c3d_to_compare["data"]["analogs"], analogs)