pyomeca / ezc3d

Easy to use C3D reader/writer for C++, Python and Matlab
https://pyomeca.github.io/Documentation/ezc3d/index.html
MIT License
142 stars 45 forks source link

Better way to crop/ trim C3D? #281

Closed thejoemarsh closed 1 year ago

thejoemarsh commented 1 year ago

Hi there,

I was wondering if there was a better way to crop or trim a C3D file to a desired frame range. In my current method I created a new C3D all together, and then assign the trimmed data to c3d['data']['points'] and modify the parameters as needed.

Is there a way to do without creating an entirely new C3D file?

I was trying to get it to work with something like this (among other methods - slicing, reshaping):

c = ezc3d.c3d(os.path.join(files_location, file), extract_forceplat_data=True)

start_frame = 50
end_frame = 100

for i in range(len(c['data']['points'])):
    for j in range(len(marker_labels)): 
        c['data']['points'][i][j] = np.delete(c['data']['points'][i][j], np.s_[end_frame:])
        c['data']['points'][i][j] = np.delete(c['data']['points'][i][j], np.s_[:start_frame])

But always run into some version of the error "could not broadcast input array from shape (50,) into shape (159,)"

Thanks!

pariterre commented 1 year ago

Hi @thejoemarsh

The way c3d are created does not allow for quick edit, apart from very slight changes (for instance, changing a POINT:LABEL name but without changing the number of characters) for which you can target the changes in the binary file. This would be a pain to implement. Therefore, creating a brand new c3d is much more reliable and easy to do.

I am not aware of the delete method of numpy, but I feel that what you are trying to do can be accomplished can be done by:

c['data']['points'] = c['data']['points'][:, :, start_frame:end_frame]

Does it help?

thejoemarsh commented 1 year ago

Sweet, that worked!

And a follow up question - is it possible to do a similar operation with force platform data? The following doesn't work, as 'PlatForm object does not support item assignment'

c['data']['platform'][i]['force'] = c['data']['platform'][i]['force'][:, start_frame_fp:end_frame_fp]

Thanks!

thejoemarsh commented 1 year ago

Update - I don't think the force plate data actually matters. After just modifying the analogs it all seemed to work! No need to directly modify the force platform data I guess.

Thanks again!

pariterre commented 1 year ago

They are indeed independent :)