ezc3d icon indicating copy to clipboard operation
ezc3d copied to clipboard

Signals EMG

Open monsitacatalina opened this issue 2 years ago • 5 comments

Hello! I have some EMG signals saved in a .c3d file obtained from VICON, I wanted to know how I can extract these signals to process them. Thank you

monsitacatalina avatar Jun 28 '22 17:06 monsitacatalina

Hi there! This really depends on which platform you work on.. Are you working in C++, matlab or Python? If you are interested in the Raw signals, you can have a look at the readme in the relevent section, it shows how to extract analogs for all the platforms.

If you are interested in filtered data and you are in Python, may I suggest to have a look a https://github.com/pyomeca/pyomeca which is a library that offers preselected filters for analysing biomechanics data, including EMG.

pariterre avatar Jun 29 '22 13:06 pariterre

Hi @pariterre, there's some interest in getting EMG data from .c3d files in OpenSim as well, which means we need to extend/modify our interface to ezc3d in C++ to make available in Python, Matlab. Some specific questions:

  1. Does c3d format support querying for the list of available quantities? So we change interface once and get all quantities rather than once for EMG, then later for IMU ....etc.
  2. Are there analogous calibration parameters for various quantities (e.g. EMG range/max/filtering/....) that get applied to the raw data, or we get the raw data as is?

Thanks

aymanhab avatar Oct 28 '22 19:10 aymanhab

Hi @aymanhab There is no standardized way to store EMG in a C3D file, as far as the format is concerned, it stores analog data, no matter what these data are. Obviously, each software has their own "standardized" way of doing so (so they themselves know which type of data are stored where). This means that we must gather the analog data and parse them by name according to manufactor (probably mostly Vicon and Qualisys) either directly in ezc3d or in opensim interface.

The second question self-answers (Since there is no standard way to store EMG, there is no pre-analyzed data, this is solely up the each manufactor)

For completeness, your query data structure (which interfaces ezc3d and BTK) can be used to properly parse the data, but again, it will have to be done for each manufactor (assuming they have a stardard way to store the emg data)

pariterre avatar Oct 28 '22 19:10 pariterre

Following up on this issue: Loading .c3d files with EMG from Vicon and Qualysis and I see the data extracted into the c3d structure. How do we tell if this is EMG or anything else? Also if the "labels" in the header are different for different manufacturers, does it make sense to have a separate C3DParser for each manufacturer, or should we use EZC3D as abstracting this out and have one C3DFileReader that handles the differences internally? Thank you @pariterre

aymanhab avatar Nov 23 '22 22:11 aymanhab

Hi @aymanhab

How do we tell if this is EMG or anything else?

You can't. There is no out-of-the-box EMG data structure. It only "analog" data mashed together. The only way to differentiate them is by the labels IF the manufacturor add something to the labels (for instance a prefix EMG:emgX). I did not have a look myself neither at a Vicon nor Qualisys c3d, so I don't know if they do. My worries is that they don't.

Also if the "labels" in the header are different for different manufacturers, does it make sense to have a separate C3DParser for each manufacturer, or should we use EZC3D as abstracting this out and have one C3DFileReader that handles the differences internally?

If you have examples of C3D from Vicon and from Qualisys which are representative of the way they mark EMG data (assuming they do), I could add an EMG module to ezc3d allowing you to simply request the values as already parsed in the module. That would therefore benefit both Opensim and ezc3d users :)

But again, if I recall well, Vicon at least does not mark emg data in a standardize way. If I am correct, then I would suggest that you guys write a parser for the analog data based on some Opensim naming standardization that your users should follow.

Hope this answers your questions!

pariterre avatar Nov 24 '22 14:11 pariterre

Hello, I got notified that the issue was closed as completed, can you point to a pr or release notes describing how to use so we can decide whether we should upgrade on our side or how the interfaces may change? Thank you

aymanhab avatar Jan 17 '23 17:01 aymanhab

Hi @aymanhab As this issue was staled, I closed it, but I did not do anything particular related to this issue. As stated in my previous comment, there is no out-of-the-box solution for this. Hence, I would to create specific solution for each of the platforms (Vicon, Qualisys, others?) and versions (Nexus.1.x, Nexus 2.x, etc.) you plan to support on OpenSim, meaning I need a c3d example file for each of them. If OpenSim can provide a test suite, I could make this work!

pariterre avatar Jan 17 '23 20:01 pariterre

Hello @pariterre and @aymanhab !

I am in the midst of exporting C3D data from Cortex Motion Analysis. The built in utility for converting C3D to .trc and .mot files works great - but I would also like to get access to my EMG analogue data so I can then process it is myself... I have attached a few C3D files which should contain markers, forces and EMGs... please let me know if I can be of assistance or if there is a quick way to already access this data.

Best wishes,

Nicos Haralabidis
c3d_share.zip

nicos1993 avatar Feb 24 '23 00:02 nicos1993

Dear @nicos1993 Could you specify if you are passing through the OpenSim flow, or you are calling ezc3d directly? If it the latter, are you using it from Matlab, Python or C++?

The short answer for your question is it can be done by hand if you are not using the OpenSim flow.

The long answer is unfortunately, in a C3D, there is no canonical way to target the EMG data in the file. C3D was not created with that in mind. When they expanded it to inlcude EMG data, they did not try to separate the data by types, nor that they standardized the labels (as it is the case for POINTS for instance). Thus, you have to find the columns of EMG, based on the ANALOGS:LABEL (the naming will depend on the implementation the company made) and then you can simply slice these data from the analog data

pariterre avatar Feb 27 '23 13:02 pariterre

@pariterre thanks for the reply!

Currently I am passing it through the OpenSim flow (specifically C3Dexport.m), but if for what I want to do I need to run it through ezc3d that isn't a problem - in which case preferably Matlab or Python but via C++ is fine.

Based on your response it appears as though I should use the ezc3d workflow directly... I will try and spend some time extracting the data in that fashion to begin with I guess... but I'm glad to hear it is possible to extract the EMGs - albeit perhaps not in a nice neat fashion!

Thanks!

nicos1993 avatar Feb 27 '23 18:02 nicos1993

The greatest problem you may face is to install ezc3d on matlab. Currently (and I don't see it in an upcoming future), there is no previously built binaries for Matlab. This means you have to compile it by yourself (there is one for Python though). While it is not complicated to compile per se, if you've never compiled C++ code before, it may be a bit of a ramp. I've made a video on youtube helping a bit for the Windows user (you can find it by typing pariterre in youtube, if needed)

pariterre avatar Feb 27 '23 18:02 pariterre

Considering this is likely useful for other users, can we expand the OpenSim interface to provide other or analog data to mirror ezc3d and let the clients do the interpretation? Then users can get both python and matlab and a uniform interface through one workflow. Just thinking aloud!

aymanhab avatar Feb 27 '23 19:02 aymanhab

@aymanhab I think it is an excellent idea, and would probably not be too hard to implement (it would simply be a structure that mirrors force platforms, but does not perform any interpretation of the data, with a table header). Having this implemented in the GUI may be a bit harder though

pariterre avatar Feb 27 '23 19:02 pariterre

Hey @aymanhab, let me know if you wanna chat this through. I am happy to get involved with it!

nicos1993 avatar Feb 28 '23 17:02 nicos1993

@nicos1993 Definitely will stop by before or after the lab meeting. Thanks for volunteering 🥇

aymanhab avatar Feb 28 '23 17:02 aymanhab

If at some point you need that we discuss by voices, I am available as well :)

pariterre avatar Feb 28 '23 18:02 pariterre

Thanks for all your help @pariterre 👍

@nicos1993 and I had a chat and we'd like to suggest beefing up the C3DFileAdapter interface to account for Analog data by adding a method along the lines of std::shared_ptr<TimeSeriesTable> getAnalogDataTable(DataAdapter::OutputTables& tables)

so in essence the method C3DFileAdapter::extendRead() here https://github.com/opensim-org/opensim-core/blob/d427d777e2f5591e20bebc9d15f20e3abe6ce47b/OpenSim/Common/C3DFileAdapter.cpp#L68 will also populate a TimeSeriesTable with Analog data and clients will have to handle it on their own (could be EMG or anything else depending on convention/user-knowledge.

Follow up questions:

  1. Does that sound doable?
  2. Could there be more analog data? what types? Maybe getAnalogScalarData and getAnalogVec3Data?
  3. Is it correct to assume there're labels associated with these Analog data, that will be embedded in the table(s)?
  4. I understand different manufacturers use different schemes, can they all be addressed using this proposed mechanism?

I would love to have an in-person/zoom discussion with you and @nicos1993 to plan the next steps once we have a viable proposal or if you have other mechanisms in mind that you want to discuss. Thanks again for all your help.

aymanhab avatar Feb 28 '23 23:02 aymanhab

Hi @aymanhab As I said, I am available for a zoom discussion (as in-person, from Quebec, is a bit hard haha!). You guys can write me at [email protected] to setup something when you are ready!

Quick answers to your questions:

  1. It is exactly how I see it, i.e. from the stand point of ezc3d, all the (untreated) analogs are fairly easily accessible in a manner highly similar to POINTS (the skin marker data), which we already sorted.
  2. There are basically as many analog data that there exist. If I had to give a definition of "Analog" in the C3D file standard, it is every piece of data which is not POINT. Unfortunately, in a c3d file, these data are all mashed up in a single large matrix, instead of being neatly separated by matrices of different data type. getAnalogVec3Data sounds right to me.
  3. This is not correct to assume that. While it is supposed to be the case (and for most of the implementation I've seen it is the case), there is nothing enforcing it. For instance, it may be the case that ANALOG:LABELS is empty even though analog data are present. That said, we can give dummy names to the data.
  4. It is not different schemes per se, since c3d is standardized. But it is only standardized in the format, not individual elements in the format. For instance, you could find a Nexus' file that prefixes EMG: the labels of the emg if they used the autoconnect emg, but nothing otherwise, or another software which would add a suffix, or another doing some other stuff (or nothing). Obviously when I say software, I also mean that different versions of the same software can also label the analog different. The main take away here is that LABELS are fundamentally unreliable while being at the same time the only information we have regarding the nature of the data in the matrix of analog data.

See you!

pariterre avatar Mar 01 '23 14:03 pariterre

How about we schedule a Zoom call for next week? What are your availabilities? @aymanhab @pariterre

Thanks!

nicos1993 avatar Mar 01 '23 23:03 nicos1993

Sounds good I am from Québec (East US and Canada Time zone), I have a pretty weird week next week... If you are available on Thursday morning (here), that would be perfect for me. Otherwise, I can try to find some time

pariterre avatar Mar 02 '23 16:03 pariterre

How about 11.30am Québec time? Does 8.30am Pacific time work for you both? @aymanhab @pariterre

Nicos

nicos1993 avatar Mar 02 '23 16:03 nicos1993

Can we do any other day before Thursday? I'm out Thu-Fri

aymanhab avatar Mar 02 '23 19:03 aymanhab

I am doing a 24h hours of work from Tuesday to Wednesday... So I'll be quite exhausted haha! Can this be the week after then? I am available on Monday, Wednesday and Thursday the next week

pariterre avatar Mar 02 '23 19:03 pariterre

Monday 12th March - what time works for you both? @aymanhab @pariterre

Thanks,

Nicos

nicos1993 avatar Mar 05 '23 04:03 nicos1993

I hate to stand in the way of progress when high level plans are mostly in place, I'd suggest you find the earliest time that fits you both @pariterre and @nicos1993, let me know the date/time and I'll try to join even if I'm off. If I can't I will follow up on github if there're questions that need my input so we don't delay. Thoughts?

aymanhab avatar Mar 06 '23 04:03 aymanhab

Hi @nicos1993 !

I assume you meant Monday 13th? If so, I now have a meeting at 9 to 10, so from that point on. I am partially available on Tuesday and the full on Wednesday :)

pariterre avatar Mar 06 '23 13:03 pariterre

@pariterre Hey! Does this coming Thursday still work for you? (March 9th) 11.30am Québec time? (8.30 PDT)

nicos1993 avatar Mar 06 '23 16:03 nicos1993

Do you mean on 9th or 16th? I am available on both ;)

pariterre avatar Mar 06 '23 16:03 pariterre

The 9th! We can try and tackle the problem to begin with and then update @aymanhab

Thanks,

Nicos

nicos1993 avatar Mar 06 '23 16:03 nicos1993

This is good, see you on the 9th!

pariterre avatar Mar 06 '23 19:03 pariterre