예제 #1
0
파일: btkapp.py 프로젝트: mkjung99/mocaplib
def get_dict_analogs(acq):
    if acq.IsEmptyAnalog(): return None
    sig_labels = []
    sig_descs = []
    sig_units = []
    sig_offset = []
    sig_scale = []
    sig_gain = []
    dict_sigs = {}
    dict_sigs.update({'DATA': {}})
    for sig in btk.Iterate(acq.GetAnalogs()):
        name = sig.GetLabel()
        offset = sig.GetOffset()
        scale = sig.GetScale()
        unit = sig.GetUnit()
        desc = sig.GetDescription()
        gain = sig.GetGain()
        sig_labels.append(name)
        sig_descs.append(desc)
        sig_units.append(unit)
        sig_offset.append(offset)
        sig_scale.append(scale)
        sig_gain.append(gain)
        val = np.asarray(sig.GetValues().flatten(), dtype=np.float32)
        dict_sigs['DATA'].update({name: val})
    dict_sigs.update({'LABELS': np.array(sig_labels, dtype=str)})
    dict_sigs.update({'DESCRIPTIONS': np.array(sig_descs, dtype=str)})
    dict_sigs.update({'UNITS': np.array(sig_units, dtype=str)})
    dict_sigs.update({'RATE': np.float32(acq.GetAnalogFrequency())})
    dict_sigs.update({'OFFSET': np.array(sig_offset, dtype=np.float32)})
    dict_sigs.update({'SCALE': np.array(sig_scale, dtype=np.float32)})
    dict_sigs.update({'GAIN': np.array(sig_gain, dtype=np.int32)})
    dict_sigs.update({'RESOLUTION': np.int32(acq.GetAnalogResolution())})
    return dict_sigs
예제 #2
0
def _GetEvents(acq):
    """
    Helper function to read and sort the event collection from an acq object
    :param acq: (btkAcquisition)
    :return: (list) List of btkEvent objects
    """
    event_list = [event for event in btk.Iterate(acq.GetEvents())]
    event_list.sort(key=lambda i:i.GetFrame())
    return  event_list
예제 #3
0
def _get_1_forceplate_data(plate):
    """Read data of a single forceplate from a c3d file.

    plate is an instance of btk.btkForcePlatform.
    """
    READ_CHS = ['Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz']
    if plate.GetType() != 2:
        # Nexus should always write forceplates as type 2
        raise GaitDataError('Only type 2 forceplates are supported for now')
    rawdata = dict()
    data = dict()
    for ch in btk.Iterate(plate.GetChannels()):
        label = ch.GetLabel()[-3:-1]  # strip descriptor and plate number
        rawdata[label] = np.squeeze(ch.GetData().GetValues())
    if not all([ch in rawdata for ch in READ_CHS]):
        logger.warning(f'could not read force/moment data for plate {plate}')
        return None
    F = np.stack([rawdata['Fx'], rawdata['Fy'], rawdata['Fz']], axis=1)
    M = np.stack([rawdata['Mx'], rawdata['My'], rawdata['Mz']], axis=1)
    # we need to calculate the center of pressure, since it's not in the C3D
    # dz is the plate thickness (from moment origin to physical origin) needed
    # for center of pressure calculations
    dz = np.abs(plate.GetOrigin()[2])
    cop = center_of_pressure(F, M, dz)  # in plate local coords
    Ftot = np.linalg.norm(F, axis=1)
    # locations of +x+y, -x+y, -x-y, +x-y plate corners in world coords
    # (in that order)
    cor = plate.GetCorners()
    wT = np.mean(cor, axis=1)  # translation vector, plate -> world
    # upper and lower bounds of forceplate
    ub = np.max(cor, axis=1)
    lb = np.min(cor, axis=1)
    # plate unit vectors in world system
    px = cor[:, 0] - cor[:, 1]
    py = cor[:, 0] - cor[:, 3]
    pz = np.array([0, 0, -1])
    P = np.stack([px, py, pz], axis=1)
    wR = P / np.linalg.norm(P, axis=0)  # rotation matrix, plate -> world
    # check whether CoP stays inside forceplate area and clip if necessary
    cop_w = _change_coords(cop, wR, wT)
    cop_wx = np.clip(cop_w[:, 0], lb[0], ub[0])
    cop_wy = np.clip(cop_w[:, 1], lb[1], ub[1])
    if not (cop_wx == cop_w[:, 0]).all() and (cop_wy == cop_w[:, 1]).all():
        logger.warning(
            'center of pressure outside forceplate bounds, clipping to plate')
        cop[:, 0] = cop_wx
        cop[:, 1] = cop_wy
    # XXX moment and force transformations may still be wrong
    data['F'] = _change_coords(-F, wR, 0)  # not sure why sign flip needed
    data['Ftot'] = Ftot
    data['M'] = _change_coords(-M, wR, 0)  # not sure why sign flip needed
    data['CoP'] = cop_w
    data['wR'] = wR
    data['wT'] = wT
    data['plate_corners'] = cor.T
    return data
예제 #4
0
def GetMarkerNames(acq):
    """Function to show point's label on acquisition.
            :parameter:
                `acq` : (btkAcquisition) a btk acquisition instance
            :return:
                `marker_names` : (list) marker names
            :todo: regex
    """
    marker_names = list()
    for it in btk.Iterate(acq.GetPoints()):
        if it.GetType() == btk.btkPoint.Marker and it.GetLabel()[0] != "*":
            marker_names.append(it.GetLabel())
    return marker_names
예제 #5
0
파일: btkapp.py 프로젝트: mkjung99/mocaplib
def get_dict_events(acq):
    if acq.IsEmptyEvent(): return None
    dict_events = {}
    for ev in btk.Iterate(acq.GetEvents()):
        name = ev.GetLabel()
        context = ev.GetContext()
        desc = ev.GetDescription()
        fr = ev.GetFrame()
        dict_events.update({fr: {}})
        dict_events[fr].update({'FRAME': fr})
        dict_events[fr].update({'LABEL': name})
        dict_events[fr].update({'CONTEXT': context})
        dict_events[fr].update({'DESCRIPTION': desc})
    return dict_events
예제 #6
0
def _get_analog_data(c3dfile, devname):
    """Read analog data from a c3d file.

    devname is matched against channel names.
    """
    acq = _get_c3dacq(c3dfile)
    data = dict()
    chnames = []
    for i in btk.Iterate(acq.GetAnalogs()):
        if i.GetDescription().find(devname) >= 0:
            if (chname := i.GetLabel()) in chnames:
                raise GaitDataError(
                    'Duplicate channel names in C3D file. Please rename your channels.'
                )
            chnames.append(chname)
            data[chname] = np.squeeze(i.GetValues())
예제 #7
0
파일: btkapp.py 프로젝트: mkjung99/mocaplib
def get_dict_points(acq, blocked_nan=False, resid=False, tgt_types=None):
    if acq.IsEmptyPoint(): return None
    pt_types = None if tgt_types is None else set()
    if tgt_types is not None:
        for type in tgt_types:
            if type == 'Angle':
                pt_types.add(btk.btkPoint.Angle)
            elif type == 'Force':
                pt_types.add(btk.btkPoint.Force)
            elif type == 'Marker':
                pt_types.add(btk.btkPoint.Marker)
            elif type == 'Moment':
                pt_types.add(btk.btkPoint.Moment)
            elif type == 'Power':
                pt_types.add(btk.btkPoint.Power)
            elif type == 'Reaction':
                pt_types.add(btk.btkPoint.Reaction)
            elif type == 'Scalar':
                pt_types.append(btk.btkPoint.Scalar)
    pt_labels = []
    pt_descs = []
    dict_pts = {}
    dict_pts.update({'DATA': {}})
    dict_pts['DATA'].update({'POS': {}})
    if resid: dict_pts['DATA'].update({'RESID': {}})
    for pt in btk.Iterate(acq.GetPoints()):
        if pt_types is not None and pt.GetType() not in pt_types: continue
        pt_name = pt.GetLabel()
        pt_pos = pt.GetValues()
        if blocked_nan or resid:
            pt_resid = pt.GetResiduals().flatten()
        if blocked_nan:
            pt_null_masks = np.where(np.isclose(pt_resid, -1), True, False)
            pt_pos[pt_null_masks,:] = np.nan
        pt_desc = pt.GetDescription()
        pt_labels.append(pt_name)
        pt_descs.append(pt_desc)
        dict_pts['DATA']['POS'].update({pt_name: np.asarray(pt_pos, dtype=np.float32)})
        if resid:
            dict_pts['DATA']['RESID'].update({pt_name: np.asarray(pt_resid, dtype=np.float32)})
    dict_pts.update({'LABELS': np.array(pt_labels, dtype=str)})    
    dict_pts.update({'DESCRIPTIONS': np.array(pt_descs, dtype=str)})
    dict_pts.update({'UNITS': acq.GetPointUnit()})    
    dict_pts.update({'RATE': np.float32(acq.GetPointFrequency())})
    dict_pts.update({'FRAME': np.linspace(acq.GetFirstFrame(), acq.GetLastFrame(), acq.GetPointFrameNumber(), dtype=np.int32)})
    return dict_pts
예제 #8
0
파일: c3d.py 프로젝트: Sanardi/gaitutils
def _get_analog_data(c3dfile, devname):
    """ Read analog data from a c3d file. devname is matched against channel
    names. """
    acq = _get_c3dacq(c3dfile)
    data = dict()
    chnames = []
    for i in btk.Iterate(acq.GetAnalogs()):
        if i.GetDescription().find(devname) >= 0:
            chname = i.GetLabel()
            chnames.append(chname)
            data[chname] = np.squeeze(i.GetValues())
    if chnames:
        return {
            't': np.arange(len(data[chname])) / acq.GetAnalogFrequency(),
            'data': data,
        }
    else:
        raise GaitDataError('No matching analog channels found in data')
예제 #9
0
def _get_forceplate_data(c3dfile):
    """Read data of all forceplates from c3d file.

    See read_data.get_forceplate_data() for details.
    """
    logger.debug(f'reading forceplate data from {c3dfile}')
    acq = _get_c3dacq(c3dfile)
    fpe = btk.btkForcePlatformsExtractor()
    fpe.SetInput(acq)
    fpe.Update()
    fpdata = list()
    for eclipse_ind, plate in enumerate(btk.Iterate(fpe.GetOutput()), 1):
        logger.debug(f'reading from plate {eclipse_ind}')
        data = _get_1_forceplate_data(plate)
        if data is not None:
            # generate the Eclipse key
            data['eclipse_key'] = f'FP{eclipse_ind}'
            fpdata.append(data)
    return fpdata
예제 #10
0
파일: btkapp.py 프로젝트: mkjung99/mocaplib
def get_point_names(acq, tgt_types=None):
    pt_names = []
    pt_types = None if tgt_types is None else set()
    if tgt_types is not None:
        for type in tgt_types:
            if type == 'Angle':
                pt_types.add(btk.btkPoint.Angle)
            elif type == 'Force':
                pt_types.add(btk.btkPoint.Force)
            elif type == 'Marker':
                pt_types.add(btk.btkPoint.Marker)
            elif type == 'Moment':
                pt_types.add(btk.btkPoint.Moment)
            elif type == 'Power':
                pt_types.add(btk.btkPoint.Power)
            elif type == 'Reaction':
                pt_types.add(btk.btkPoint.Reaction)
            elif type == 'Scalar':
                pt_types.append(btk.btkPoint.Scalar)
    for pt in btk.Iterate(acq.GetPoints()):
        if pt_types is not None and pt.GetType() not in pt_types: continue
        pt_names.append(pt.GetLabel())
    return pt_names
예제 #11
0
파일: c3d.py 프로젝트: Sanardi/gaitutils
def get_metadata(c3dfile):
    """ Read trial and subject metadata """
    trialname = os.path.basename(os.path.splitext(c3dfile)[0])
    sessionpath = os.path.dirname(c3dfile)
    acq = _get_c3dacq(c3dfile)
    # frame offset (start of trial data in frames)
    offset = acq.GetFirstFrame()
    lastfr = acq.GetLastFrame()
    length = lastfr - offset + 1  # or acq.GetPointFrameNumber()
    framerate = acq.GetPointFrequency()
    analograte = acq.GetAnalogFrequency()
    samplesperframe = acq.GetNumberAnalogSamplePerFrame()

    # count forceplates
    fpe = btk.btkForcePlatformsExtractor()
    fpe.SetInput(acq)
    fpe.Update()
    n_forceplates = len(list(btk.Iterate(fpe.GetOutput())))

    # get markers
    try:
        markers = _get_c3d_metadata_field(acq, 'POINT', 'LABELS')
    except RuntimeError:
        markers = list()
    # not sure what the '*xx' markers are, but delete them for now
    markers = [m for m in markers if m[0] != '*']

    #  get events
    rstrikes, lstrikes, rtoeoffs, ltoeoffs = [], [], [], []
    for i in btk.Iterate(acq.GetEvents()):
        if i.GetLabel() == "Foot Strike":
            if i.GetContext() == "Right":
                rstrikes.append(i.GetFrame())
            elif i.GetContext() == "Left":
                lstrikes.append(i.GetFrame())
            else:
                raise GaitDataError("Unknown context on foot strike event")
        elif i.GetLabel() == "Foot Off":
            if i.GetContext() == "Right":
                rtoeoffs.append(i.GetFrame())
            elif i.GetContext() == "Left":
                ltoeoffs.append(i.GetFrame())
            else:
                raise GaitDataError("Unknown context on foot strike event")

    # get subject info
    try:
        name = _get_c3d_metadata_field(acq, 'SUBJECTS', 'NAMES')[0]
    except RuntimeError:
        logger.warning('Cannot get subject name')
        name = u'Unknown'

    try:
        par_names = _get_c3d_metadata_subfields(acq, 'PROCESSING')
    except RuntimeError:
        raise GaitDataError('cannot read metadata from %s' % c3dfile)
    subj_params = defaultdict(lambda: None)
    subj_params.update({par: _get_c3d_subject_param(acq, par) for par in par_names})

    # sort events (may be in wrong temporal order, at least in c3d files)
    for li in [lstrikes, rstrikes, ltoeoffs, rtoeoffs]:
        li.sort()

    return {
        'trialname': trialname,
        'sessionpath': sessionpath,
        'offset': offset,
        'framerate': framerate,
        'analograte': analograte,
        'name': name,
        'subj_params': subj_params,
        'lstrikes': lstrikes,
        'rstrikes': rstrikes,
        'ltoeoffs': ltoeoffs,
        'rtoeoffs': rtoeoffs,
        'length': length,
        'samplesperframe': samplesperframe,
        'n_forceplates': n_forceplates,
        'markers': markers,
    }
예제 #12
0
def compute(leg, Filename_In):
    m = re.match(Input_Dir + "(?P<name>.+).c3d", Filename_In)
    name = m.group('name').replace(" ", "-")
    output_file = "%s/%s%s.csv" % (Output_Dir, leg, name)
    print("Trying %s" % (Filename_In))

    # Read files in .c3d and read data
    reader = btk.btkAcquisitionFileReader()
    reader.SetFilename(Filename_In)
    reader.Update()
    acq = reader.GetOutput()

    nFrames = acq.GetPointFrameNumber()
    first_frame = acq.GetFirstFrame()

    # Heel, Ankle, Hallux, Toe
    # 2 * 4 * 3 = 24 Marker Trajectories
    # 2 * 4 * 3 = 24 Velocity
    # 2 * 4 * 3 = 24 Acceleration
    markers = ["ANK", "TOE", "HLX", "HEE"]
    opposite = {'L': 'R', 'R': 'L'}

    # Check if there are any marker data in the file
    brk = True
    for point in btk.Iterate(acq.GetPoints()):
        if point.GetLabel() == "L" + markers[0]:
            brk = False
            break

    if brk:
        print("No Datain %s!" % (Filename_In, ))
        return

    # Marker Data extraction and filtering.
    traj = [None] * (len(markers) * 2)
    for i, v in enumerate(markers):
        try:
            traj[i] = acq.GetPoint(leg + v).GetValues()
            traj[len(markers) + i] = acq.GetPoint(opposite[leg] +
                                                  v).GetValues()
        except:
            return

        traj[i][:, 0] = traj[i][:, 0]  # * incrementX
        traj[len(markers) + i][:,
                               0] = traj[len(markers) + i][:,
                                                           0]  # * incrementX
        traj[i][:, 2] = traj[i][:, 2]  # * incrementX
        traj[len(markers) + i][:,
                               2] = traj[len(markers) + i][:,
                                                           2]  # * incrementXq

    # filter then getting position, velocity and accleration
    filtered_traj = [data_filter(acq, ax, nFrames) for ax in traj]
    vel = [derivative(bx, nFrames) for bx in filtered_traj]
    acc = [derivative(cx, nFrames) for cx in vel]

    curves = np.concatenate(filtered_traj + vel + acc, axis=1)

    # Add events as output using annotation on data
    outputs = np.array([[0] * nFrames, [0] * nFrames]).T
    for event in btk.Iterate(acq.GetEvents()):
        if event.GetFrame() >= nFrames:
            print("Event happened too far")
            return
        if len(event.GetContext()) == 0:
            print("No events found")
            return
        if event.GetContext()[0] == leg:
            if event.GetLabel() == "Foot Strike":
                outputs[event.GetFrame() - first_frame, 0] = 1
            elif event.GetLabel() == "Foot Off":
                outputs[event.GetFrame() - first_frame, 1] = 1

    if (np.sum(outputs) == 0):
        print("No events in %s!" % (Filename_In, ))
        return

    arr = np.concatenate((curves, outputs), axis=1)

    print("Writing %s" % Filename_In)
    np.savetxt(output_file, arr, delimiter=',')
예제 #13
0
파일: c3d.py 프로젝트: Sanardi/gaitutils
def get_forceplate_data(c3dfile):
    logger.debug('reading forceplate data from %s' % c3dfile)
    read_chs = ['Fx', 'Fy', 'Fz', 'Mx', 'My', 'Mz']
    acq = _get_c3dacq(c3dfile)
    fpe = btk.btkForcePlatformsExtractor()
    fpe.SetInput(acq)
    fpe.Update()
    fpdata = list()
    nplate = 0
    for plate in btk.Iterate(fpe.GetOutput()):
        logger.debug('reading from plate %d' % nplate)
        nplate += 1
        if plate.GetType() != 2:
            # Nexus should always write forceplates as type 2
            raise GaitDataError('Only type 2 forceplates are supported for now')
        rawdata = dict()
        data = dict()
        for ch in btk.Iterate(plate.GetChannels()):
            label = ch.GetLabel()[-3:-1]  # strip descriptor and plate number
            rawdata[label] = np.squeeze(ch.GetData().GetValues())
        if not all([ch in rawdata for ch in read_chs]):
            logger.warning('could not read force/moment data for plate %d' % nplate)
            continue
        F = np.stack([rawdata['Fx'], rawdata['Fy'], rawdata['Fz']], axis=1)
        M = np.stack([rawdata['Mx'], rawdata['My'], rawdata['Mz']], axis=1)
        # this should be the plate thickness (from moment origin to physical
        # origin) needed for center of pressure calculations
        dz = np.abs(plate.GetOrigin()[2])
        cop = center_of_pressure(F, M, dz)  # in plate local coords
        Ftot = np.linalg.norm(F, axis=1)
        # locations of +x+y, -x+y, -x-y, +x-y plate corners in world coords
        # (in that order)
        cor = plate.GetCorners()
        wT = np.mean(cor, axis=1)  # translation vector, plate -> world
        # upper and lower bounds of forceplate
        ub = np.max(cor, axis=1)
        lb = np.min(cor, axis=1)
        # plate unit vectors in world system
        px = cor[:, 0] - cor[:, 1]
        py = cor[:, 0] - cor[:, 3]
        pz = np.array([0, 0, -1])
        P = np.stack([px, py, pz], axis=1)
        wR = P / np.linalg.norm(P, axis=0)  # rotation matrix, plate -> world
        # check whether cop stays inside forceplate area and clip if necessary
        cop_w = change_coords(cop, wR, wT)
        cop_wx = np.clip(cop_w[:, 0], lb[0], ub[0])
        cop_wy = np.clip(cop_w[:, 1], lb[1], ub[1])
        if not (cop_wx == cop_w[:, 0]).all() and (cop_wy == cop_w[:, 1]).all():
            logger.warning(
                'center of pressure outside forceplate bounds, clipping to plate'
            )
            cop[:, 0] = cop_wx
            cop[:, 1] = cop_wy
        # XXX moment and force transformations may still be wrong
        data['F'] = change_coords(-F, wR, 0)  # not sure why sign flip needed
        data['Ftot'] = Ftot
        data['M'] = change_coords(-M, wR, 0)  # not sure why sign flip needed
        data['CoP'] = cop_w
        data['upperbounds'] = ub
        data['lowerbounds'] = lb
        data['wR'] = wR
        data['wT'] = wT
        data['cor_full'] = cor.T
        fpdata.append(data)
    return fpdata
예제 #14
0
def _get_metadata(c3dfile):
    """Read trial and subject metadata from c3d file.

    See read_data.get_metadata() for details.
    """
    c3dfile = Path(c3dfile)
    trialname = c3dfile.stem
    sessionpath = c3dfile.parent
    acq = _get_c3dacq(c3dfile)
    # frame offset (start of trial data in frames)
    offset = acq.GetFirstFrame()
    lastfr = acq.GetLastFrame()
    length = lastfr - offset + 1  # or acq.GetPointFrameNumber()
    framerate = acq.GetPointFrequency()
    analograte = acq.GetAnalogFrequency()
    samplesperframe = acq.GetNumberAnalogSamplePerFrame()

    # count forceplates
    fpe = btk.btkForcePlatformsExtractor()
    fpe.SetInput(acq)
    fpe.Update()
    n_forceplates = len(list(btk.Iterate(fpe.GetOutput())))

    # get markers
    try:
        markers = _get_c3d_metadata_field(acq, 'POINT', 'LABELS')
    except RuntimeError:
        markers = list()
    # XXX: not sure what the '*xx' markers are, but delete them for now
    markers = [m for m in markers if m[0] != '*']

    #  get events
    events = GaitEvents()
    for i in btk.Iterate(acq.GetEvents()):
        fr = i.GetFrame()
        context = i.GetContext()[0]
        ev_type = i.GetLabel()
        if ev_type == 'Foot Strike':
            ev_type_ours = 'strike'
        elif ev_type == 'Foot Off':
            ev_type_ours = 'toeoff'
        else:
            ev_type_ours = ev_type
        fr_offset = fr - offset
        ev = GaitEvent(fr_offset, ev_type_ours, context)
        events.append(ev)

    # get subject info
    try:
        subj_name = _get_c3d_metadata_field(acq, 'SUBJECTS', 'NAMES')[0]
    except RuntimeError:
        logger.warning('Cannot get subject name')
        subj_name = 'Unknown'
    subj_params = defaultdict(lambda: None)
    try:
        par_names = _get_c3d_metadata_subfields(acq, 'PROCESSING')
    except RuntimeError:
        logger.warning(
            f'{c3dfile} is missing the PROCESSING section that contains '
            'subject info (bodyweight etc.)')
    else:
        subj_params.update(
            {par: _get_c3d_subject_param(acq, par)
             for par in par_names})

    return {
        'trialname': trialname,
        'sessionpath': sessionpath,
        'offset': offset,
        'framerate': framerate,
        'analograte': analograte,
        'subject_name': subj_name,
        'subj_params': subj_params,
        'events': events,
        'length': length,
        'samplesperframe': samplesperframe,
        'n_forceplates': n_forceplates,
        'markers': markers,
    }
예제 #15
0
def param_spt(filename, side):
    reader = btk.btkAcquisitionFileReader()
    reader.SetFilename(filename)
    reader.Update()
    acq = reader.GetOutput()

    if side.lower() == "left":
        foot_marker = acq.GetPoint('LHEE').GetValues()
        foot_marker_ct = acq.GetPoint('RHEE').GetValues()
        side_cl = "right"
        side_letter = "L"
    elif side.lower() == "right":
        foot_marker = acq.GetPoint('RHEE').GetValues()
        foot_marker_ct = acq.GetPoint('LHEE').GetValues()
        side_cl = "left"
        side_letter = "R"
    # Initialisation des lists contenant les evenements
    FO = []
    FO_CL = []
    FS = []
    FS_CL = []

    for it in btk.Iterate(acq.GetEvents()):

        if it.GetContext().lower() == side:
            if it.GetLabel() == 'Foot Strike':
                FS.append(it.GetFrame())
            elif it.GetLabel() == 'Foot Off':
                FO.append(it.GetFrame())
        elif it.GetContext().lower() == side_cl:
            if it.GetLabel() == 'Foot Strike':
                FS_CL.append(it.GetFrame())
            elif it.GetLabel() == 'Foot Off':
                FO_CL.append(it.GetFrame())
    # Les evenements ne sont pas forcement organisé dans le bon ordre
    FO.sort()
    FO_CL.sort()
    FS.sort()
    FS_CL.sort()

    frq_point = float(acq.GetPointFrequency())
    # On enleve tout les evenements qui sont avant le premier foot strike du coté étudié
    first_event = FS[0]
    first_frame = acq.GetFirstFrame()
    last_frame = acq.GetLastFrame()
    FS = [x - first_frame for x in FS if x >= first_event]
    FS_CL = [x - first_frame for x in FS_CL if x >= first_event]
    FO = [x - first_frame for x in FO if x >= first_event]
    FO_CL = [x - first_frame for x in FO_CL if x >= first_event]
    # Extraction de la longueur de jambe
    md = acq.GetMetaData()
    leg_lenght = md.FindChild("PROCESSING").value().FindChild(
        side_letter + 'LegLength').value().GetInfo().ToDouble()[0] / 1000.0
    gravity = 9.81
    # définition de la direction de marche
    point = acq.GetPoint('LPSI').GetValues()
    direction_walk = point[last_frame - first_frame, :] - point[0, :]
    direction_walk = np.argmax(np.abs(direction_walk))
    point = acq.GetPoint('LPSI').GetValues() - acq.GetPoint('RPSI').GetValues()
    direction_width = np.argmax(np.abs(point[0, :]))
    param_spt = {
        "cycle_time": [],
        "cadence": [],
        "cadence_adm": [],
        "length_cycle": [],
        "length_cycle_adm": [],
        "walking_speed": [],
        "walking_speed_adm": [],
        "step_length": [],
        "step_length_adm": [],
        "step_sec": [],
        "step_width": [],
        "step_width_adm": [],
        "stance_phase_sec": [],
        "stance_phase_perc": [],
        "swing_phase_sec": [],
        "swing_phase_perc": [],
        "double_stance_sec": [],
        "double_stance_perc": [],
        "simple_stance_sec": [],
        "simple_stance_perc": [],
        "percentage_CTFO": [],
        "percentage_CTFS": []
    }

    for ind_cycle in range(len(FS) - 1):
        nb_frame_cycle = float(FS[ind_cycle + 1] - FS[ind_cycle])

        # Temps du cycle (s)
        cycle_time = (FS[ind_cycle + 1] - FS[ind_cycle]) / frq_point
        param_spt["cycle_time"].append(cycle_time)
        # Cadence (step/mn)
        cadence = 120.0 / cycle_time
        param_spt["cadence"].append(cadence)
        param_spt["cadence_adm"].append(cadence /
                                        np.sqrt(gravity / leg_lenght))
        # Longueur du cycle (m)
        length_cycle = np.abs(foot_marker[FS[ind_cycle + 1], direction_walk] -
                              foot_marker[FS[ind_cycle],
                                          direction_walk]) / 1000.0
        param_spt["length_cycle"].append(length_cycle)
        param_spt["length_cycle_adm"].append(length_cycle / leg_lenght)
        # Vitesse de marche (m/s)
        walking_speed = cadence * length_cycle / 120.0
        param_spt["walking_speed"].append(walking_speed)
        param_spt["walking_speed_adm"].append(walking_speed /
                                              np.sqrt(leg_lenght * gravity))
        # Longueur du pas (m)
        step_length = np.abs(foot_marker_ct[FO[ind_cycle], direction_walk] -
                             foot_marker[FS[ind_cycle],
                                         direction_walk]) / 1000.0
        param_spt["step_length"].append(step_length)
        param_spt["step_length_adm"].append(step_length / leg_lenght)
        # Temps Pas (frame, sec)
        step_frame = FS_CL[ind_cycle] - FS[ind_cycle]
        step_sec = step_frame / frq_point
        param_spt["step_sec"].append(step_sec)
        # Largeur pas (m)
        step_width = np.abs(foot_marker_ct[FO[ind_cycle], direction_width] -
                            foot_marker[FS[ind_cycle],
                                        direction_width]) / 1000.0
        param_spt["step_width"].append(step_width)
        param_spt["step_width_adm"].append(step_width / leg_lenght)
        # Phase d'appui (frame, sec, pourcentage)
        stance_phase_frame = FO[ind_cycle] - FS[ind_cycle]
        stance_phase_sec = stance_phase_frame / frq_point
        stance_phase_perc = stance_phase_frame / nb_frame_cycle * 100
        param_spt["stance_phase_sec"].append(stance_phase_sec)
        param_spt["stance_phase_perc"].append(stance_phase_perc)

        # Phase oscillante (frame, sec, pourcentage)
        swing_phase_frame = FS[ind_cycle + 1] - FO[ind_cycle]
        swing_phase_sec = swing_phase_frame / frq_point
        swing_phase_perc = swing_phase_frame / nb_frame_cycle * 100
        param_spt["swing_phase_sec"].append(swing_phase_sec)
        param_spt["swing_phase_perc"].append(swing_phase_perc)

        # Double appui (frame, sec, pourcentage)
        double_stance_frame = (FO_CL[ind_cycle] - FS[ind_cycle] +
                               FO[ind_cycle] - FS_CL[ind_cycle])
        double_stance_sec = double_stance_frame / frq_point
        double_stance_perc = double_stance_frame / nb_frame_cycle * 100
        param_spt["double_stance_sec"].append(double_stance_sec)
        param_spt["double_stance_perc"].append(double_stance_perc)

        # Simple appui (frame, sec, pourcentage)
        simple_stance_frame = FS_CL[ind_cycle] - FO_CL[ind_cycle]
        simple_stance_sec = simple_stance_frame / frq_point
        simple_stance_perc = simple_stance_frame / nb_frame_cycle * 100
        param_spt["simple_stance_sec"].append(simple_stance_sec)
        param_spt["simple_stance_perc"].append(simple_stance_perc)

        # Calcul des evenements controlateral pour affichage cinématique
        CTFS_frame = FS_CL[ind_cycle] - FS[ind_cycle]
        CTFO_frame = FO_CL[ind_cycle] - FS[ind_cycle]
        CTFS_perc = CTFS_frame / nb_frame_cycle * 100
        CTFO_perc = CTFO_frame / nb_frame_cycle * 100
        param_spt["percentage_CTFS"].append(CTFS_perc)
        param_spt["percentage_CTFO"].append(CTFO_perc)

    return param_spt
예제 #16
0
RKneeAnglesNormaliseListY = np.array([])
RKneeAnglesNormaliseListZ = np.array([])
RAnkleAnglesNormaliseListX = np.array([])
RAnkleAnglesNormaliseListY = np.array([])
RAnkleAnglesNormaliseListZ = np.array([])
RFootProgressAnglesNormaliseListX = np.array([])
RFootProgressAnglesNormaliseListY = np.array([])
RFootProgressAnglesNormaliseListZ = np.array([])

for i in range(len(list)):
  PoseTalonGauche = []
  PoseTalonDroit = []
  DecollementPiedGauche = []
  DecollementPiedDroit = []

  for it in btk.Iterate(acq[i].GetEvents()):
    if (it.GetLabel() == "Foot Strike") and (it.GetContext() == "Left"):
	  PoseTalonGauche.append(it.GetFrame())
    if (it.GetLabel() == "Foot Strike") and (it.GetContext() == "Right"):
  	PoseTalonDroit.append(it.GetFrame())
    if (it.GetLabel() == "Foot Off") and (it.GetContext() == "Left"):
  	DecollementPiedGauche.append(it.GetFrame())
    if (it.GetLabel() == "Foot Off") and (it.GetContext() == "Right"):
  	DecollementPiedDroit.append(it.GetFrame())

  PoseTalonGauche.sort()
  PoseTalonDroit.sort()
  DecollementPiedGauche.sort()
  DecollementPiedDroit.sort()
  
  nb_cycle_gauche_cinematique = len(PoseTalonGauche) - 1
def extract_kinematics(leg, filename_in, sacr=False, lstm=True, turn=False):
    # Open c3d and read data
    reader = btk.btkAcquisitionFileReader()
    reader.SetFilename(filename_in)
    reader.Update()
    acq = reader.GetOutput()
    nframes = acq.GetPointFrameNumber()
    first_frame = acq.GetFirstFrame()

    end = acq.GetLastFrame()

    # Check if there is a FOG
    for event in btk.Iterate(acq.GetEvents()):
        if event.GetLabel() == 'FOG':
            end = event.GetFrame()
            nframes = end - first_frame

    metadata = acq.GetMetaData()

    # We extract only kinematics
    kinematics = ["HipAngles", "KneeAngles", "AnkleAngles"]
    markers = ["TOE", "KNE", "HEE"]

    # Check if there are any kinematics in the file
    brk = True
    for point in btk.Iterate(acq.GetPoints()):
        if point.GetLabel() == "L" + kinematics[0]:
            brk = False
            break

    if brk:
        print("No kinematics in:" + str(filename_in))
        return

    # Add events as output
    outputs = np.array([[0] * nframes]).T
    for event in btk.Iterate(acq.GetEvents()):
        if first_frame < event.GetFrame() < end:
            if event.GetLabel() == "Foot Strike":
                if event.GetContext() == 'Left':
                    outputs[event.GetFrame() - first_frame, 0] = 1
                elif event.GetContext() == 'Right':
                    outputs[event.GetFrame() - first_frame, 0] = 2
            elif event.GetLabel() == "Foot Off":
                if event.GetContext() == 'Left':
                    outputs[event.GetFrame() - first_frame, 0] = 3
                elif event.GetContext() == 'Right':
                    outputs[event.GetFrame() - first_frame, 0] = 4

    if (np.sum(outputs) == 0):
        print("No events in:" + str(filename_in))
        return

    positives = np.where(outputs > 0.5)
    if len(positives[0]) == 0:
        return None

    first_event = positives[0][0]

    # Combine kinematics into one big array
    opposite = {'L': 'R', 'R': 'L'}
    angles = [None] * (len(kinematics) * 2)
    for i, v in enumerate(kinematics):
        point = acq.GetPoint(leg + v)
        angles[i] = point.GetValues()
        angles[i] = angles[i][:nframes]
        point = acq.GetPoint(opposite[leg] + v)
        angles[len(kinematics) + i] = point.GetValues()
        angles[len(kinematics) + i] = angles[len(kinematics) + i][:nframes]

    print(filename_in)

    # Get the pelvis (if no SACR marker)
    if sacr:
        SACR_X = acq.GetPoint("SACR").GetValues()[:, 0]
    else:
        LPSI_X = acq.GetPoint("LPSI").GetValues()[:, 0]
        RPSI_X = acq.GetPoint("RPSI").GetValues()[:, 0]
        midPSI_X = (LPSI_X + RPSI_X) / 2
        SACR_X = midPSI_X

    pos = [None] * (len(markers) * 2)

    pos_sacr_X = [None] * (len(markers) * 2)
    pos_sacr_Y = [None] * (len(markers) * 2)
    pos_sacr_Z = [None] * (len(markers) * 2)
    pos_sacr = [None] * (len(markers) * 2)
    for j, w in enumerate(markers):
        point = acq.GetPoint(leg + w)
        pos[j] = point.GetValues()
        pos_sacr_X[j] = point.GetValues()[:, 0] - SACR_X
        pos_sacr_Y[j] = point.GetValues()[:, 1]
        pos_sacr_Z[j] = point.GetValues()[:, 2]
        pos_sacr[j] = np.column_stack(
            (pos_sacr_X[j], pos_sacr_Y[j], pos_sacr_Z[j]))
        pos_sacr[j] = pos_sacr[j][:nframes]

        point = acq.GetPoint(opposite[leg] + w)
        pos[len(markers) + j] = point.GetValues()
        pos_sacr_X[len(markers) + j] = point.GetValues()[:, 0] - SACR_X
        pos_sacr_Y[len(markers) + j] = point.GetValues()[:, 1]
        pos_sacr_Z[len(markers) + j] = point.GetValues()[:, 2]
        pos_sacr[len(markers) + j] = np.column_stack(
            (pos_sacr_X[len(markers) + j], pos_sacr_Y[len(markers) + j],
             pos_sacr_Z[len(markers) + j]))
        pos_sacr[len(markers) + j] = pos_sacr[len(markers) + j][:nframes]

    # Low pass filter at 7Hz
    angles_lp = butter_lowpass_filter(np.hstack(angles), cutoff=7, fs=100)
    markers_lp = butter_lowpass_filter(np.hstack(pos_sacr), cutoff=7, fs=100)

    # Get derivatives
    angles_lp_vel = derivative(angles_lp, nframes)
    markers_lp_vel = derivative(markers_lp, nframes)

    angles = np.hstack((angles_lp, angles_lp_vel))
    markers = np.hstack((markers_lp, markers_lp_vel))

    if marker:
        curves = np.concatenate((angles, markers), axis=1)
    else:
        curves = angles

    arr = np.concatenate((curves, outputs), axis=1)

    # Remove data before and after first event minus some random int. This is for those trials that are not pre-cut.
    if sacr:
        positives = np.where(arr[:, 36] > 0.5)
        if len(positives[0]) == 0:
            return None

        first_event = positives[0][0] - random.randint(5, 15)
        last_event = positives[0][-1] + random.randint(5, 15)

        curves = curves[first_event:last_event]
        first_frame = first_event

    out = [curves, markers, angles, first_frame]
    return out
예제 #18
0
def kinematic(filename, side, extension):
    reader = btk.btkAcquisitionFileReader()
    reader.SetFilename(filename)
    reader.Update()
    acq = reader.GetOutput()

    if side.lower() == "left":
        side_letter = 'L'
        side_cl = "right"
    elif side.lower() == "right":
        side_letter = 'R'
        side_cl = "left"

    # Initialisation des lists contenant les evenements
    FO = []
    FO_CL = []
    FS = []
    FS_CL = []
    for it in btk.Iterate(acq.GetEvents()):
        if it.GetContext().lower() == side:
            if it.GetLabel() == 'Foot Strike':
                FS.append(it.GetFrame())
            elif it.GetLabel() == 'Foot Off':
                FO.append(it.GetFrame())
        elif it.GetContext().lower() == side_cl:
            if it.GetLabel() == 'Foot Strike':
                FS_CL.append(it.GetFrame())
            elif it.GetLabel() == 'Foot Off':
                FO_CL.append(it.GetFrame())
    FO.sort()
    FO_CL.sort()
    FS.sort()
    FS_CL.sort()

    # frq_point = float(acq.GetPointFrequency())
    # On enleve tout les evenements qui sont avant le premier foot strike du coté étudié
    first_event = FS[0]
    first_frame = acq.GetFirstFrame()
    # last_frame = acq.GetLastFrame()
    FS = [x - first_frame for x in FS if x >= first_event]
    FS_CL = [x - first_frame for x in FS_CL if x >= first_event]
    FO = [x - first_frame for x in FO if x >= first_event]
    FO_CL = [x - first_frame for x in FO_CL if x >= first_event]

    # Initialisation
    nb_cycle = len(FS) - 1
    kinematic = {
        "Pelvis_Fle": np.zeros((101, nb_cycle)),
        "Pelvis_Abd": np.zeros((101, nb_cycle)),
        "Pelvis_Ier": np.zeros((101, nb_cycle)),
        "Hip_Fle": np.zeros((101, nb_cycle)),
        "Hip_Abd": np.zeros((101, nb_cycle)),
        "Hip_Ier": np.zeros((101, nb_cycle)),
        "Knee_Fle": np.zeros((101, nb_cycle)),
        "Knee_Abd": np.zeros((101, nb_cycle)),
        "Knee_Ier": np.zeros((101, nb_cycle)),
        "Ankle_Fle": np.zeros((101, nb_cycle)),
        "Foot_Progression": np.zeros((101, nb_cycle)),
        "Foot_tilt": np.zeros((101, nb_cycle))
    }

    for ind_cycle in range(nb_cycle):
        nb_frame = FS[ind_cycle + 1] - FS[ind_cycle]
        # paramètre pour l'interpolation sur 100 point
        x = np.linspace(0, nb_frame, 101)
        xp = np.linspace(0, nb_frame, nb_frame)
        # Pelvis
        f_flexion = acq.GetPoint(side_letter + 'PelvisAngles' +
                                 extension).GetValues()[
                                     FS[ind_cycle]:FS[ind_cycle + 1], 0]
        f_abduction = acq.GetPoint(side_letter + 'PelvisAngles' +
                                   extension).GetValues()[
                                       FS[ind_cycle]:FS[ind_cycle + 1], 1]
        f_rotation = acq.GetPoint(side_letter + 'PelvisAngles' +
                                  extension).GetValues()[
                                      FS[ind_cycle]:FS[ind_cycle + 1], 2]
        #        if side == "left":
        #            f_abduction = -f_abduction
        #            f_rotation = -f_rotation
        kinematic["Pelvis_Fle"][:, ind_cycle] = np.interp(x, xp, f_flexion)
        kinematic["Pelvis_Abd"][:, ind_cycle] = np.interp(x, xp, f_abduction)
        kinematic["Pelvis_Ier"][:, ind_cycle] = np.interp(x, xp, f_rotation)
        # Hip
        f_flexion = acq.GetPoint(side_letter + 'HipAngles' +
                                 extension).GetValues()[
                                     FS[ind_cycle]:FS[ind_cycle + 1], 0]
        f_abduction = acq.GetPoint(side_letter + 'HipAngles' +
                                   extension).GetValues()[
                                       FS[ind_cycle]:FS[ind_cycle + 1], 1]
        f_rotation = acq.GetPoint(side_letter + 'HipAngles' +
                                  extension).GetValues()[
                                      FS[ind_cycle]:FS[ind_cycle + 1], 2]
        kinematic["Hip_Fle"][:, ind_cycle] = np.interp(x, xp, f_flexion)
        kinematic["Hip_Abd"][:, ind_cycle] = np.interp(x, xp, f_abduction)
        kinematic["Hip_Ier"][:, ind_cycle] = np.interp(x, xp, f_rotation)

        # Knee
        f_flexion = acq.GetPoint(side_letter + 'KneeAngles' +
                                 extension).GetValues()[
                                     FS[ind_cycle]:FS[ind_cycle + 1], 0]
        f_abduction = acq.GetPoint(side_letter + 'KneeAngles' +
                                   extension).GetValues()[
                                       FS[ind_cycle]:FS[ind_cycle + 1], 1]
        f_rotation = acq.GetPoint(side_letter + 'KneeAngles' +
                                  extension).GetValues()[
                                      FS[ind_cycle]:FS[ind_cycle + 1], 2]
        kinematic["Knee_Fle"][:, ind_cycle] = np.interp(x, xp, f_flexion)
        kinematic["Knee_Abd"][:, ind_cycle] = np.interp(x, xp, f_abduction)
        kinematic["Knee_Ier"][:, ind_cycle] = np.interp(x, xp, f_rotation)

        # Ankle
        f_flexion = acq.GetPoint(side_letter + 'AnkleAngles' +
                                 extension).GetValues()[
                                     FS[ind_cycle]:FS[ind_cycle + 1], 0]
        f_progression = acq.GetPoint(side_letter + 'FootProgressAngles' +
                                     extension).GetValues()[
                                         FS[ind_cycle]:FS[ind_cycle + 1], 2]
        f_tilt = acq.GetPoint(side_letter + 'FootProgressAngles' +
                              extension).GetValues()[FS[ind_cycle]:FS[ind_cycle
                                                                      + 1], 0]
        f_tilt = -f_tilt - 90
        kinematic["Ankle_Fle"][:, ind_cycle] = np.interp(x, xp, f_flexion)
        kinematic["Foot_Progression"][:, ind_cycle] = np.interp(
            x, xp, f_progression)
        kinematic["Foot_tilt"][:, ind_cycle] = np.interp(x, xp, f_tilt)

    return kinematic
예제 #19
0
def kinetic(filename, side, extension):
    [FP1, FP2] = extraction_enf(filename)

    reader = btk.btkAcquisitionFileReader()
    reader.SetFilename(filename)
    reader.Update()
    acq = reader.GetOutput()
    plateform_valid = [side == FP1, side == FP2]

    if side.lower() == "left":
        side_letter = 'L'
        side_cl = "right"
    elif side.lower() == "right":
        side_letter = 'R'
        side_cl = "left"

    # Initialisation des lists contenant les evenements
    FO = []
    FO_CL = []
    FS = []
    FS_CL = []
    for it in btk.Iterate(acq.GetEvents()):
        if it.GetContext().lower() == side:
            if it.GetLabel() == 'Foot Strike':
                FS.append(it.GetFrame())
            elif it.GetLabel() == 'Foot Off':
                FO.append(it.GetFrame())
        elif it.GetContext().lower() == side_cl:
            if it.GetLabel() == 'Foot Strike':
                FS_CL.append(it.GetFrame())
            elif it.GetLabel() == 'Foot Off':
                FO_CL.append(it.GetFrame())

    FO.sort()
    FO_CL.sort()
    FS.sort()
    FS_CL.sort()
    frq_point = float(acq.GetPointFrequency())
    frq_analog = float(acq.GetAnalogFrequency())
    factor_point_analog = frq_analog / frq_point
    # On enleve tout les evenements qui sont avant le premier foot strike du coté étudié
    first_event = FS[0]
    first_frame = acq.GetFirstFrame()
    # last_frame = acq.GetLastFrame()
    FS = [x - first_frame for x in FS if x >= first_event]
    FS_CL = [x - first_frame for x in FS_CL if x >= first_event]
    FO = [x - first_frame for x in FO if x >= first_event]
    FO_CL = [x - first_frame for x in FO_CL if x >= first_event]

    # Coefficient d'adimension pour les moments
    md = acq.GetMetaData()
    leg_lenght = md.FindChild("PROCESSING").\
        value().FindChild(side_letter + 'LegLength').\
        value().GetInfo().ToDouble()[0] / 1000.0

    body_mass = md.FindChild("PROCESSING").\
        value().FindChild('Bodymass').\
        value().GetInfo().ToDouble()[0]

    gravity = 9.81
    # In nexus the unit of the moment is Nmm / kg and in the Schwartz norm the data are
    # in N m/kg (just divided by the mass of the subject)
    # coeff_moment = leg_lenght * body_mass * gravity
    coeff_moment = 1000
    # Initialisation
    # nb_cycle = len(FS) - 1

    fz1 = acq.GetAnalog("Fz1").GetValues()
    fz2 = acq.GetAnalog("Fz2").GetValues()

    # nb_cycle = sum(plateform_valid)

    nb_cycle = len(FS) - 1
    cycle_valid = 0
    for ind_cycle in range(nb_cycle):
        init_cycle = FS[ind_cycle]
        end_cycle = FS[ind_cycle + 1]
        nb_frame = end_cycle - init_cycle

        nbr_frame_fz1 = sum(
            np.abs(fz1[int(init_cycle * factor_point_analog
                           ):int(end_cycle * factor_point_analog)]) > 5
        ) / factor_point_analog
        nbr_frame_fz2 = sum(
            np.abs(fz2[int(init_cycle * factor_point_analog
                           ):int(end_cycle * factor_point_analog)]) > 5
        ) / factor_point_analog
        condition_Plat1 = (nbr_frame_fz1 /
                           float(nb_frame)) > 0.15 and plateform_valid[0]
        condition_Plat2 = (nbr_frame_fz2 /
                           float(nb_frame)) > 0.15 and plateform_valid[1]
        if condition_Plat1 or condition_Plat2:
            cycle_valid += 1

    kinematic = {
        "Pelvis_Fle": np.zeros((101, cycle_valid)),
        "Pelvis_Abd": np.zeros((101, cycle_valid)),
        "Pelvis_Ier": np.zeros((101, cycle_valid)),
        "Hip_Fle": np.zeros((101, cycle_valid)),
        "Hip_Abd": np.zeros((101, cycle_valid)),
        "Hip_Ier": np.zeros((101, cycle_valid)),
        "Knee_Fle": np.zeros((101, cycle_valid)),
        "Knee_Abd": np.zeros((101, cycle_valid)),
        "Knee_Ier": np.zeros((101, cycle_valid)),
        "Ankle_Fle": np.zeros((101, cycle_valid)),
        "Foot_Progression": np.zeros((101, cycle_valid)),
        "Foot_tilt": np.zeros((101, cycle_valid))
    }

    kinetic = {
        "Pelvis_Abd": np.zeros((101, cycle_valid)),
        "Hip_Abd": np.zeros((101, cycle_valid)),
        "Knee_Abd": np.zeros((101, cycle_valid)),
        "Hip_Fle": np.zeros((101, cycle_valid)),
        "Knee_Fle": np.zeros((101, cycle_valid)),
        "Ankle_Fle": np.zeros((101, cycle_valid)),
        "Hip_Power": np.zeros((101, cycle_valid)),
        "Knee_Power": np.zeros((101, cycle_valid)),
        "Ankle_Power": np.zeros((101, cycle_valid)),
        "Normalised_Ground_Reaction_X": np.zeros((101, cycle_valid)),
        "Normalised_Ground_Reaction_Y": np.zeros((101, cycle_valid)),
        "Normalised_Ground_Reaction_Z": np.zeros((101, cycle_valid)),
        "Hip_Moment": np.zeros((101, cycle_valid)),
        "Knee_Moment": np.zeros((101, cycle_valid)),
        "Ankle_Moment": np.zeros((101, cycle_valid)),
        "Hip_Moment_abd": np.zeros((101, cycle_valid)),
        "Knee_Moment_abd": np.zeros((101, cycle_valid)),
        "Ankle_Moment_abd": np.zeros((101, cycle_valid))
    }

    cycle_valid = 0
    for ind_cycle in range(nb_cycle):
        init_cycle = FS[ind_cycle]
        end_cycle = FS[ind_cycle + 1]
        nb_frame = end_cycle - init_cycle

        nbr_frame_fz1 = sum(
            np.abs(fz1[int(init_cycle * factor_point_analog
                           ):int(end_cycle * factor_point_analog)]) > 5
        ) / factor_point_analog
        nbr_frame_fz2 = sum(
            np.abs(fz2[int(init_cycle * factor_point_analog
                           ):int(end_cycle * factor_point_analog)]) > 5
        ) / factor_point_analog
        condition_Plat1 = (nbr_frame_fz1 /
                           float(nb_frame)) > 0.15 and plateform_valid[0]
        condition_Plat2 = (nbr_frame_fz2 /
                           float(nb_frame)) > 0.15 and plateform_valid[1]

        if condition_Plat1 or condition_Plat2:
            # paramètre pour l'interpolation sur 100 point
            x = np.linspace(0, nb_frame, 101)
            xp = np.linspace(0, nb_frame, nb_frame)
            # Pelvis
            print side_letter + 'PelvisAngles' + extension
            f_flexion = acq.GetPoint(side_letter + 'PelvisAngles' +
                                     extension).GetValues()[
                                         FS[ind_cycle]:FS[ind_cycle + 1], 0]
            f_abduction = acq.GetPoint(side_letter + 'PelvisAngles' +
                                       extension).GetValues()[
                                           FS[ind_cycle]:FS[ind_cycle + 1], 1]
            f_rotation = acq.GetPoint(side_letter + 'PelvisAngles' +
                                      extension).GetValues()[
                                          FS[ind_cycle]:FS[ind_cycle + 1], 2]
            kinematic["Pelvis_Fle"][:,
                                    cycle_valid] = np.interp(x, xp, f_flexion)
            kinematic["Pelvis_Abd"][:, cycle_valid] = np.interp(
                x, xp, f_abduction)
            kinematic["Pelvis_Ier"][:, cycle_valid] = np.interp(
                x, xp, f_rotation)

            kinetic["Pelvis_Abd"][:,
                                  cycle_valid] = np.interp(x, xp, f_abduction)

            # Hip
            f_flexion = acq.GetPoint(side_letter + 'HipAngles' +
                                     extension).GetValues()[
                                         FS[ind_cycle]:FS[ind_cycle + 1], 0]
            f_abduction = acq.GetPoint(side_letter + 'HipAngles' +
                                       extension).GetValues()[
                                           FS[ind_cycle]:FS[ind_cycle + 1], 1]
            f_rotation = acq.GetPoint(side_letter + 'HipAngles' +
                                      extension).GetValues()[
                                          FS[ind_cycle]:FS[ind_cycle + 1], 2]
            kinematic["Hip_Fle"][:, cycle_valid] = np.interp(x, xp, f_flexion)
            kinematic["Hip_Abd"][:,
                                 cycle_valid] = np.interp(x, xp, f_abduction)
            kinematic["Hip_Ier"][:, cycle_valid] = np.interp(x, xp, f_rotation)

            kinetic["Hip_Fle"][:, cycle_valid] = np.interp(x, xp, f_flexion)
            kinetic["Hip_Abd"][:, cycle_valid] = np.interp(x, xp, f_abduction)

            # Knee
            f_flexion = acq.GetPoint(side_letter + 'KneeAngles' +
                                     extension).GetValues()[
                                         FS[ind_cycle]:FS[ind_cycle + 1], 0]
            f_abduction = acq.GetPoint(side_letter + 'KneeAngles' +
                                       extension).GetValues()[
                                           FS[ind_cycle]:FS[ind_cycle + 1], 1]
            f_rotation = acq.GetPoint(side_letter + 'KneeAngles' +
                                      extension).GetValues()[
                                          FS[ind_cycle]:FS[ind_cycle + 1], 2]

            kinematic["Knee_Fle"][:, cycle_valid] = np.interp(x, xp, f_flexion)
            kinematic["Knee_Abd"][:,
                                  cycle_valid] = np.interp(x, xp, f_abduction)
            kinematic["Knee_Ier"][:,
                                  cycle_valid] = np.interp(x, xp, f_rotation)

            kinetic["Knee_Fle"][:, cycle_valid] = np.interp(x, xp, f_flexion)
            kinetic["Knee_Abd"][:, cycle_valid] = np.interp(x, xp, f_abduction)

            # Ankle
            f_flexion = acq.GetPoint(side_letter + 'AnkleAngles' +
                                     extension).GetValues()[
                                         FS[ind_cycle]:FS[ind_cycle + 1], 0]
            f_progression = acq.GetPoint(
                side_letter + 'FootProgressAngles' +
                extension).GetValues()[FS[ind_cycle]:FS[ind_cycle + 1], 2]
            f_tilt = acq.GetPoint(side_letter + 'FootProgressAngles' +
                                  extension).GetValues()[
                                      FS[ind_cycle]:FS[ind_cycle + 1], 0]
            f_tilt = -f_tilt - 90
            kinematic["Ankle_Fle"][:,
                                   cycle_valid] = np.interp(x, xp, f_flexion)
            kinematic["Foot_Progression"][:, cycle_valid] = np.interp(
                x, xp, f_progression)
            kinematic["Foot_tilt"][:, cycle_valid] = np.interp(x, xp, f_tilt)

            kinetic["Ankle_Fle"][:, cycle_valid] = np.interp(x, xp, f_flexion)

            # kinetic
            power_hip = acq.GetPoint(side_letter + 'HipPower' +
                                     extension).GetValues()[
                                         FS[ind_cycle]:FS[ind_cycle + 1], 2]
            power_knee = acq.GetPoint(side_letter + 'KneePower' +
                                      extension).GetValues()[
                                          FS[ind_cycle]:FS[ind_cycle + 1], 2]
            power_ankle = acq.GetPoint(side_letter + 'AnklePower' +
                                       extension).GetValues()[
                                           FS[ind_cycle]:FS[ind_cycle + 1], 2]
            kinetic["Hip_Power"][:, cycle_valid] = np.interp(x, xp, power_hip)
            kinetic["Knee_Power"][:,
                                  cycle_valid] = np.interp(x, xp, power_knee)
            kinetic["Ankle_Power"][:, cycle_valid] = np.interp(
                x, xp, power_ankle)

            normal_GRF_X = acq.GetPoint(side_letter +
                                        'NormalisedGRF').GetValues()[
                                            FS[ind_cycle]:FO[ind_cycle], 0]
            normal_GRF_X = np.append(
                normal_GRF_X, np.zeros((FS[ind_cycle + 1] - FO[ind_cycle], 1)))

            normal_GRF_Y = acq.GetPoint(side_letter +
                                        'NormalisedGRF').GetValues()[
                                            FS[ind_cycle]:FO[ind_cycle], 1]
            normal_GRF_Y = np.append(
                normal_GRF_Y, np.zeros((FS[ind_cycle + 1] - FO[ind_cycle], 1)))

            normal_GRF_Z = acq.GetPoint(side_letter +
                                        'NormalisedGRF').GetValues()[
                                            FS[ind_cycle]:FO[ind_cycle], 2]
            normal_GRF_Z = np.append(
                normal_GRF_Z, np.zeros((FS[ind_cycle + 1] - FO[ind_cycle], 1)))

            kinetic["Normalised_Ground_Reaction_X"][:,
                                                    cycle_valid] = -np.interp(
                                                        x, xp, normal_GRF_X)
            kinetic["Normalised_Ground_Reaction_Y"][:,
                                                    cycle_valid] = np.interp(
                                                        x, xp, normal_GRF_Y)
            kinetic["Normalised_Ground_Reaction_Z"][:,
                                                    cycle_valid] = np.interp(
                                                        x, xp, normal_GRF_Z)

            moment_hip = acq.GetPoint(side_letter + 'HipMoment' +
                                      extension).GetValues()[
                                          FS[ind_cycle]:FS[ind_cycle + 1], 0]
            moment_knee = acq.GetPoint(side_letter + 'KneeMoment' +
                                       extension).GetValues()[
                                           FS[ind_cycle]:FS[ind_cycle + 1], 0]
            moment_ankle = acq.GetPoint(side_letter + 'AnkleMoment' +
                                        extension).GetValues()[
                                            FS[ind_cycle]:FS[ind_cycle + 1], 0]
            kinetic["Hip_Moment"][:, cycle_valid] = np.interp(
                x, xp, moment_hip) / coeff_moment
            kinetic["Knee_Moment"][:, cycle_valid] = np.interp(
                x, xp, moment_knee) / coeff_moment
            kinetic["Ankle_Moment"][:, cycle_valid] = np.interp(
                x, xp, moment_ankle) / coeff_moment

            moment_hip_abd = acq.GetPoint(
                side_letter + 'HipMoment' +
                extension).GetValues()[FS[ind_cycle]:FS[ind_cycle + 1], 1]
            moment_knee_abd = acq.GetPoint(
                side_letter + 'KneeMoment' +
                extension).GetValues()[FS[ind_cycle]:FS[ind_cycle + 1], 1]
            moment_ankle_abd = acq.GetPoint(
                side_letter + 'AnkleMoment' +
                extension).GetValues()[FS[ind_cycle]:FS[ind_cycle + 1], 1]

            kinetic["Hip_Moment_abd"][:, cycle_valid] = np.interp(
                x, xp, moment_hip_abd) / coeff_moment
            kinetic["Knee_Moment_abd"][:, cycle_valid] = np.interp(
                x, xp, moment_knee_abd) / coeff_moment
            kinetic["Ankle_Moment_abd"][:, cycle_valid] = np.interp(
                x, xp, moment_ankle_abd) / coeff_moment

            cycle_valid += 1
    return [kinematic, kinetic]
예제 #20
0
def extract_kinematics(leg, filename_in):
    print("Trying %s" % (filename_in))

    # Open c3d and read data
    reader = btk.btkAcquisitionFileReader()
    reader.SetFilename(filename_in)
    reader.Update()
    acq = reader.GetOutput()
    nframes = acq.GetPointFrameNumber()
    first_frame = acq.GetFirstFrame()

    metadata = acq.GetMetaData()

    rate = int(
        metadata.FindChild('POINT').value().FindChild(
            'RATE').value().GetInfo().ToDouble()[0])
    if rate != 120:
        return

    # We extract only kinematics
    kinematics = [
        "HipAngles", "KneeAngles", "AnkleAngles", "PelvisAngles",
        "FootProgressAngles"
    ]
    markers = ["ANK", "TOE", "KNE", "ASI", "HEE"]

    # Cols
    # 2 * 5 * 3 = 30  kinematics
    # 2 * 5 * 3 = 30  marker trajectories
    # 2 * 5 * 3 = 30  marker trajectory derivatives
    # 3 * 3 = 9       extra trajectories

    outputs = np.array([[0] * nframes, [0] * nframes]).T

    # Check if there are any kinematics in the file
    brk = True
    for point in btk.Iterate(acq.GetPoints()):
        if point.GetLabel() == "L" + kinematics[0]:
            brk = False
            break

    if brk:
        print("No kinematics in %s!" % (filename, ))
        return

    # Combine kinematics into one big array
    opposite = {'L': 'R', 'R': 'L'}
    angles = [None] * (len(kinematics) * 2)
    for i, v in enumerate(kinematics):
        point = acq.GetPoint(leg + v)
        angles[i] = point.GetValues()
        point = acq.GetPoint(opposite[leg] + v)
        angles[len(kinematics) + i] = point.GetValues()

    # Get the pelvis
    LASI = acq.GetPoint("LASI").GetValues()
    RASI = acq.GetPoint("RASI").GetValues()
    midASI = (LASI + RASI) / 2
    # incrementX = 1 if midASI[100][0] > midASI[0][0] else -1

    traj = [None] * (len(markers) * 4 + 3)
    for i, v in enumerate(markers):
        try:
            traj[i] = acq.GetPoint(leg + v).GetValues() - midASI
            traj[len(markers) +
                 i] = acq.GetPoint(opposite[leg] + v).GetValues() - midASI
        except:
            print("Error while reading marker data: %d, %s" % (i, v))
            return

        traj[i][:, 0] = traj[i][:, 0]  #* incrementX
        traj[len(markers) + i][:, 0] = traj[len(markers) + i][:,
                                                              0]  #* incrementX
        traj[i][:, 2] = traj[i][:, 2]  #* incrementX
        traj[len(markers) + i][:, 2] = traj[len(markers) + i][:,
                                                              2]  #* incrementX

    for i in range(len(markers) * 2):
        traj[len(markers) * 2 + i] = derivative(traj[i], nframes)

    midASI = midASI  #* incrementX

    midASIvel = derivative(midASI, nframes)
    midASIacc = derivative(midASIvel, nframes)

    traj[len(markers) * 4] = midASI
    traj[len(markers) * 4 + 1] = midASIvel
    traj[len(markers) * 4 + 2] = midASIacc

    curves = np.concatenate(angles + traj, axis=1)

    # Plot each component of the big array
    # for i in range(3 * len(kinematics)):
    #     plt.plot(range(nframes), curves[:,i])

    # Add events as output
    for event in btk.Iterate(acq.GetEvents()):
        if event.GetFrame() >= nframes:
            print("Event happened too far")
            return
        if len(event.GetContext()) == 0:
            print("No events")
            return
#        if event.GetContext()[0] == leg:
        if event.GetLabel() == "Foot Strike":
            outputs[event.GetFrame() - first_frame, 0] = 1
        elif event.GetLabel() == "Foot Off":
            outputs[event.GetFrame() - first_frame, 1] = 1
        print(event.GetLabel(), event.GetContext(), event.GetFrame(),
              event.GetFrame() - first_frame)

    if (np.sum(outputs) == 0):
        print("No events in %s!" % (filename, ))
        return

    arr = np.concatenate((curves, outputs), axis=1)

    return arr
예제 #21
0
파일: btkapp.py 프로젝트: mkjung99/mocaplib
def get_analog_names(acq):
    sig_names = []
    for sig in btk.Iterate(acq.GetAnalogs()):
        sig_names.append(sig.GetLabel())
    return sig_names
예제 #22
0
def _get_c3d_metadata_subfields(acq, field):
    """Return names of C3D metadata subfields for a given field"""
    meta = acq.GetMetaData()
    meta_s = meta.GetChild(field)
    return [f.GetLabel() for f in btk.Iterate(meta_s)]
예제 #23
0
파일: btkapp.py 프로젝트: mkjung99/mocaplib
def get_fp_output(acq, threshold=0.0, filt_fc=None, filt_order=2, cop_nan_to_num=True):
    pfe = btk.btkForcePlatformsExtractor()
    pfe.SetInput(acq)
    pfe.Update()
    pfc = pfe.GetOutput()
    if pfc.IsEmpty():
        return None
    point_unit = acq.GetPointUnit()
    point_scale = 1.0 if point_unit=='m' else 0.001
    analog_fps = acq.GetAnalogFrequency()
    rgx_fp = re.compile(r'\S*(\d*[FMP]\d*[XxYyZz]\d*)')
    fp_output = {}
    fp_idx = 0
    for fp in btk.Iterate(pfc):
        fp_type = fp.GetType()
        # force plate location info
        fp_org_raw = np.squeeze(fp.GetOrigin())*point_scale
        fp_z_check = -1.0 if fp_org_raw[2]>0 else 1.0
        if fp_type == 1:
            o_x = 0.0
            o_y = 0.0
            o_z = (-1.0)*fp_org_raw[2]*fp_z_check
        elif fp_type in [2, 4]:
            o_x = (-1.0)*fp_org_raw[0]*fp_z_check
            o_y = (-1.0)*fp_org_raw[1]*fp_z_check
            o_z = (-1.0)*fp_org_raw[2]*fp_z_check
        elif fp_type == 3:
            o_x = 0.0
            o_y = 0.0
            o_z = (-1.0)*fp_org_raw[2]*fp_z_check
            fp_len_a = np.abs(fp_org_raw[0])
            fp_len_b = np.abs(fp_org_raw[1])
        fp_corners = fp.GetCorners().T*point_scale
        # fp_corners[0] #(+x, +y)
        # fp_corners[1] #(-x, +y)
        # fp_corners[2] #(-x, -y)
        # fp_corners[3] #(+x, -y)        
        fp_cen = np.mean(fp_corners, axis=0)
        fp_len_x = (np.linalg.norm(fp_corners[0]-fp_corners[1])+np.linalg.norm(fp_corners[3]-fp_corners[2]))*0.5
        fp_len_y = (np.linalg.norm(fp_corners[0]-fp_corners[3])+np.linalg.norm(fp_corners[1]-fp_corners[2]))*0.5
        fp_p0 = fp_cen
        fp_p1 = 0.5*(fp_corners[0]+fp_corners[3])
        fp_p2 = 0.5*(fp_corners[0]+fp_corners[1])
        fp_v0 = fp_p1-fp_p0
        fp_v1 = fp_p2-fp_p0
        fp_v0_u = fp_v0/np.linalg.norm(fp_v0)
        fp_v1_u = fp_v1/np.linalg.norm(fp_v1)
        fp_v2 = np.cross(fp_v0_u, fp_v1_u)
        fp_v2_u = fp_v2/np.linalg.norm(fp_v2)
        fp_v_z = fp_v2_u
        fp_v_x = fp_v0_u
        fp_v_y = np.cross(fp_v_z, fp_v_x)
        fp_rot_mat = np.column_stack([fp_v_x, fp_v_y, fp_v_z])
        # force plate force/moment info
        fp_data = {}
        ch_data = {}
        ch_scale = {}
        # for ch in btk.Iterate(fp.GetChannels()):
        fp_cnt_chs = fp.GetChannelNumber()
        if filt_fc is None:
            filt_fcs = [None]*fp_cnt_chs
        elif type(filt_fc) in [int, float]:
            filt_fcs = [float(filt_fc)]*fp_cnt_chs
        elif type(filt_fc) in [list, tuple]:
            filt_fcs = list(filt_fc)
        elif type(filt_fc)==np.ndarray:
            if len(filt_fc)==1:
                filt_fcs = [filt_fc.item()]*fp_cnt_chs
            else:
                filt_fcs = filt_fc.tolist()
        for ch_idx in range(fp_cnt_chs):
            ch_name = fp.GetChannel(ch_idx).GetLabel()
            ch = acq.GetAnalog(ch_name)
            fm_name =  str.upper(rgx_fp.findall(ch.GetLabel())[0])
            # assign channel names
            if fp_type == 1:
                # assume that the order of input analog channels are as follows:
                # 'FX', 'FY', 'FZ', 'PX', 'PY', 'TZ'
                label = ['FX', 'FY', 'FZ', 'PX', 'PY', 'TZ'][ch_idx]            
            elif fp_type in [2, 4]:
                label = re.sub(r'\d', r'', fm_name)
            elif fp_type == 3:
                # assume that the order of input analog channels are as follows:
                # 'FX12', 'FX34', 'FY14', 'FY23', 'FZ1', 'FZ2', 'FZ3', 'FZ4'
                label = ['FX12', 'FX34', 'FY14', 'FY23', 'FZ1', 'FZ2', 'FZ3', 'FZ4'][ch_idx]
            # assign channel scale factors
            if fp_type == 1:
                if label.startswith('F'):
                    # assume that the force unit is 'N'
                    ch_scale[label] = 1.0
                elif label.startswith('T'):
                    # assume that the torque unit is 'Nmm'
                    ch_scale[label] = 0.001
                    if ch.GetUnit()=='Nm': ch_scale[label] = 1.0
                elif label.startswith('P'):
                    # assume that the position unit is 'mm'
                    ch_scale[label] = 0.001
                    if ch.GetUnit()=='m': ch_scale[label] = 1.0
            elif fp_type in [2, 3, 4]:
                if label.startswith('F'):
                    # assume that the force unit is 'N'
                    ch_scale[label] = 1.0
                elif label.startswith('M'):
                    # assume taht the torque unit is 'Nmm'
                    ch_scale[label] = 0.001
                    if ch.GetUnit()=='Nm': ch_scale[label] = 1.0
            # assign channel values
            lp_fc = filt_fcs[ch_idx]
            if lp_fc is None:
                ch_data[label] = np.squeeze(ch.GetData().GetValues())
            else:
                ch_data[label] = filt_bw_lp(np.squeeze(ch.GetData().GetValues()), lp_fc, analog_fps, order=filt_order)
        if fp_type == 1:
            cop_l_x_in = ch_data['PX']*ch_scale['PX']
            cop_l_y_in = ch_data['PY']*ch_scale['PY']
            t_z_in = ch_data['TZ']*ch_scale['TZ']
            fx = ch_data['FX']*ch_scale['FX']
            fy = ch_data['FY']*ch_scale['FY']
            fz = ch_data['FZ']*ch_scale['FZ']
            mx = (cop_l_y_in-o_y)*fz+o_z*fy
            my = -o_z*fx-(cop_l_x_in-o_x)*fz
            mz = (cop_l_x_in-o_x)*fy-(cop_l_y_in-o_y)*fx+t_z_in
            f_raw = np.stack([fx, fy, fz], axis=1)
            m_raw = np.stack([mx, my, mz], axis=1)
        elif fp_type == 2:
            f_raw = np.stack([ch_data['FX']*ch_scale['FX'], ch_data['FY']*ch_scale['FY'], ch_data['FZ']*ch_scale['FZ']], axis=1)
            m_raw = np.stack([ch_data['MX']*ch_scale['MX'], ch_data['MY']*ch_scale['MY'], ch_data['MZ']*ch_scale['MZ']], axis=1)
        elif fp_type == 4:
            fp_cal_mat = fp.GetCalMatrix()
            fm_local = np.stack([ch_data['FX'], ch_data['FY'], ch_data['FZ'], ch_data['MX'], ch_data['MY'], ch_data['MZ']], axis=1)
            fm_calib = np.dot(fp_cal_mat, fm_local.T).T
            f_raw = np.stack([fm_calib[:,0]*ch_scale['FX'], fm_calib[:,1]*ch_scale['FY'], fm_calib[:,2]*ch_scale['FZ']], axis=1)
            m_raw = np.stack([fm_calib[:,3]*ch_scale['MX'], fm_calib[:,4]*ch_scale['MY'], fm_calib[:,5]*ch_scale['MZ']], axis=1)
        elif fp_type == 3:
            fx12 = ch_data['FX12']*ch_scale['FX12']
            fx34 = ch_data['FX34']*ch_scale['FX34']
            fy14 = ch_data['FY14']*ch_scale['FY14']
            fy23 = ch_data['FY23']*ch_scale['FY23']
            fz1 = ch_data['FZ1']*ch_scale['FZ1']
            fz2 = ch_data['FZ2']*ch_scale['FZ2']
            fz3 = ch_data['FZ3']*ch_scale['FZ3']
            fz4 = ch_data['FZ4']*ch_scale['FZ4']
            fx = fx12+fx34
            fy = fy14+fy23
            fz = fz1+fz2+fz3+fz4
            mx = fp_len_b*(fz1+fz2-fz3-fz4)
            my = fp_len_a*(-fz1+fz2+fz3-fz4)
            mz = fp_len_b*(-fx12+fx34)+fp_len_a*(fy14-fy23)
            f_raw = np.stack([fx, fy, fz], axis=1)
            m_raw = np.stack([mx, my, mz], axis=1)
        zero_vals = np.zeros((f_raw.shape[0]), dtype=np.float32)
        fm_skip_mask = np.abs(f_raw[:,2])<=threshold
        f_sensor_local = f_raw.copy()
        m_sensor_local = m_raw.copy()
        # filter local values by threshold
        f_sensor_local[fm_skip_mask,:] = 0.0
        m_sensor_local[fm_skip_mask,:] = 0.0
        f_x = f_sensor_local[:,0]
        f_y = f_sensor_local[:,1]
        f_z = f_sensor_local[:,2]
        m_x = m_sensor_local[:,0]
        m_y = m_sensor_local[:,1]
        m_z = m_sensor_local[:,2]
        with np.errstate(invalid='ignore'):
            f_z_adj = np.where(fm_skip_mask, np.inf, f_z)          
            cop_l_x = np.where(fm_skip_mask, np.nan, np.clip((-m_y+(-o_z)*f_x)/f_z_adj+o_x, -fp_len_x*0.5, fp_len_x*0.5))
            cop_l_y = np.where(fm_skip_mask, np.nan, np.clip((m_x+(-o_z)*f_y)/f_z_adj+o_y, -fp_len_y*0.5, fp_len_y*0.5))
            cop_l_z = np.where(fm_skip_mask, np.nan, zero_vals)
            if cop_nan_to_num:
                cop_l_x = np.nan_to_num(cop_l_x)
                cop_l_y = np.nan_to_num(cop_l_y)
                cop_l_z = np.nan_to_num(cop_l_z)
        t_z = m_z-(cop_l_x-o_x)*f_y+(cop_l_y-o_y)*f_x
        # values for the force plate local output
        m_cop_local = np.stack([zero_vals, zero_vals, t_z], axis=1)
        cop_surf_local = np.stack([cop_l_x, cop_l_y, cop_l_z], axis=1)
        f_surf_local = f_sensor_local
        m_surf_local = np.cross(np.array([o_x, o_y, o_z], dtype=np.float32), f_sensor_local)+m_sensor_local
        # values for the force plate global output
        m_cop_global = np.dot(fp_rot_mat, m_cop_local.T).T
        cop_surf_global = np.dot(fp_rot_mat, cop_surf_local.T).T
        f_surf_global = np.dot(fp_rot_mat, f_surf_local.T).T
        m_surf_global = np.dot(fp_rot_mat, m_surf_local.T).T
        # values for the lab output
        m_cop_lab = m_cop_global
        cop_lab = fp_cen+cop_surf_global
        f_cop_lab = f_surf_global
        # prepare return values        
        fp_data.update({'F_SURF_LOCAL': f_surf_local})
        fp_data.update({'M_SURF_LOCAL': m_surf_local})
        fp_data.update({'COP_SURF_LOCAL': cop_surf_local})
        fp_data.update({'F_SURF_GLOBAL': f_surf_global})
        fp_data.update({'M_SURF_GLOBAL': m_surf_global})
        fp_data.update({'COP_SURF_GLOBAL': cop_surf_global})
        fp_data.update({'F_COP_LAB': f_cop_lab})            
        fp_data.update({'M_COP_LAB': m_cop_lab})
        fp_data.update({'COP_LAB': cop_lab})
        if fp_type == 1:
            fp_data.update({'COP_LOCAL_INPUT': np.stack([cop_l_x_in, cop_l_y_in, zero_vals], axis=1)})
        fp_output.update({fp_idx: fp_data})
        fp_idx += 1
    return fp_output
예제 #24
0
def plot_emg(filename, color1, color2, report_directory, title="EMG"):
    reader = btk.btkAcquisitionFileReader()
    reader.SetFilename(filename)
    reader.Update()
    acq = reader.GetOutput()
    name_emg = ["VL", "Gastroc", "RF", "IJ", "TA"]
    time_activation = {
        "VL": np.array([-10, 15, 90, 115]),
        "Gastroc": np.array([15, 52]),
        "RF": np.array([55, 65]),
        "IJ": np.array([-10, 12, 90, 110]),
        "TA": np.array([-45, 10, 55, 110])
    }

    emg_R = {}
    emg_L = {}

    for muscle_name in name_emg:
        emg_R[muscle_name] = acq.GetAnalog("R" + muscle_name).GetValues()
        emg_L[muscle_name] = acq.GetAnalog("L" + muscle_name).GetValues()

    # Initialisation des lists contenant les evenements
    L_FO = []
    R_FO = []
    L_FS = []
    R_FS = []

    for it in btk.Iterate(acq.GetEvents()):
        if it.GetContext().lower() == "left":
            if it.GetLabel() == 'Foot Strike':
                L_FS.append(it.GetFrame())
            elif it.GetLabel() == 'Foot Off':
                L_FO.append(it.GetFrame())
        elif it.GetContext().lower() == 'right':
            if it.GetLabel() == 'Foot Strike':
                R_FS.append(it.GetFrame())
            elif it.GetLabel() == 'Foot Off':
                R_FO.append(it.GetFrame())

    L_FO.sort()
    R_FO.sort()
    L_FS.sort()
    R_FS.sort()
    point2analog = acq.GetAnalogFrequency() / float(acq.GetPointFrequency())

    # On enleve tout les evenements qui sont avant le premier foot strike du coté étudié
    first_frame = acq.GetFirstFrame()

    L_FS = [(x - first_frame) * point2analog for x in L_FS]
    R_FS = [(x - first_frame) * point2analog for x in R_FS]
    L_FO = [(x - first_frame) * point2analog for x in L_FO]
    R_FO = [(x - first_frame) * point2analog for x in R_FO]

    numbre_emg = len(name_emg)
    nbr_frame = np.size(acq.GetAnalog("R" + name_emg[0]).GetValues(), 0)

    fig, axis = plt.subplots(numbre_emg * 2, 1, figsize=(8.27, 11.69), dpi=100)

    for ind_muscle, muscle_name in enumerate(name_emg):
        ax_temp_R = axis[ind_muscle * 2]
        ax_temp_L = axis[ind_muscle * 2 + 1]
        ax_temp_R.set_ylim([-0.5, 0.5])
        ax_temp_L.set_ylim([-0.5, 0.5])

        ax_temp_R.plot(emg_R[muscle_name], color=color2, linewidth=1.0)
        ax_temp_R.set_title("R " + muscle_name, fontsize=8)
        ax_temp_R.set_xlim((0, nbr_frame))
        ax_temp_R.set_xticklabels([])

        ax_temp_L.plot(emg_L[muscle_name], color=color1)
        ax_temp_L.set_title("L " + muscle_name, fontsize=8)
        ax_temp_L.set_xlim((0, nbr_frame))
        if not ind_muscle == numbre_emg:
            ax_temp_L.set_xticklabels([])

        for axis_temp in [ax_temp_R, ax_temp_L]:
            for x_event in L_FS:
                y_lim = axis_temp.get_ylim()
                axis_temp.plot([x_event, x_event], y_lim, color=color1)
                axis_temp.set_ylim(y_lim)
            for x_event in L_FO:
                y_lim = axis_temp.get_ylim()
                axis_temp.plot([x_event, x_event],
                               y_lim,
                               color=color1,
                               linestyle='--')
                axis_temp.set_ylim(y_lim)
            for x_event in R_FS:
                y_lim = axis_temp.get_ylim()
                axis_temp.plot([x_event, x_event], y_lim, color=color2)
                axis_temp.set_ylim(y_lim)
            for x_event in R_FO:
                y_lim = axis_temp.get_ylim()
                axis_temp.plot([x_event, x_event],
                               y_lim,
                               color=color2,
                               linestyle='--')
                axis_temp.set_ylim(y_lim)

        # tracer de la norme
        for ind_event in range(len(L_FS) - 1):
            nb_frame = L_FS[ind_event + 1] - L_FS[ind_event]
            frame_norm_emg = nb_frame * time_activation[
                muscle_name] / 100.0 + L_FS[ind_event]
            if ind_event == (len(L_FS) - 2):
                nb_activation = len(frame_norm_emg) / 2
            else:
                nb_activation = 1

            for ind_activation in range(nb_activation):
                ind1 = frame_norm_emg[ind_activation * 2]
                ind2 = frame_norm_emg[ind_activation * 2 + 1]

                y_lim = ax_temp_L.get_ylim()
                division = (y_lim[1] - y_lim[0]) / 8.0
                bas_y = y_lim[0] + 7 * division

                ax_temp_L.add_patch(
                    patches.Rectangle((ind1, bas_y),
                                      ind2 - ind1,
                                      division,
                                      facecolor=[0.8, 0.8, 0.8],
                                      zorder=-10))

        for ind_event in range(len(R_FS) - 1):
            nb_frame = R_FS[ind_event + 1] - R_FS[ind_event]
            frame_norm_emg = nb_frame * time_activation[
                muscle_name] / 100.0 + R_FS[ind_event]

            if ind_event == (len(R_FS) - 2):
                nb_activation = len(frame_norm_emg) / 2
            else:
                nb_activation = 1

            for ind_activation in range(nb_activation):
                ind1 = frame_norm_emg[ind_activation * 2]
                ind2 = frame_norm_emg[ind_activation * 2 + 1]
                y_lim = ax_temp_R.get_ylim()
                division = (y_lim[1] - y_lim[0]) / 8.0
                bas_y = y_lim[0] + 7 * division
                ax_temp_R.add_patch(
                    patches.Rectangle((ind1, bas_y),
                                      ind2 - ind1,
                                      division,
                                      facecolor=[0.8, 0.8, 0.8],
                                      zorder=-10))

    plt.tight_layout()

    report_directory_final = os.path.join(report_directory, 'EMG')
    if not os.path.isdir(report_directory_final):
        os.makedirs(report_directory_final)

    file_name = os.path.join(report_directory_final, title + '.png')
    print('Sauvegarde du fichier ' + title)
    fig.savefig(file_name, bbox_inches='tight')
    plt.close(fig)

    file_name_final = file_name

    return file_name_final
예제 #25
0
def extract_kinematics(leg, filename):
    m = re.match(input_dir + "(?P<name>.+).c3d", filename)
    name = m.group('name').replace(" ", "-")
    output_file = "%s/%s.csv" % (output_dir, name)
    print("Trying %s" % (filename))

    # Open c3d and read data
    reader = btk.btkAcquisitionFileReader()
    reader.SetFilename(str(filename))
    reader.Update()
    acq = reader.GetOutput()
    nframes = acq.GetPointFrameNumber()

    start = acq.GetFirstFrame()
    end = acq.GetLastFrame()

    # Check if there is a FOG
    for event in btk.Iterate(acq.GetEvents()):
        if event.GetLabel() == 'FOG':
            end = event.GetFrame()
            nframes = end - start

    if os.path.isfile(output_file):
        return

    metadata = acq.GetMetaData()

    # We extract only kinematics
    kinematics = ["HipAngles", "KneeAngles", "AnkleAngles"]
    markers = ["TOE", "KNE", "HEE"]

    # ------------ Cols
    # If marker:
    # 2 * 3 * 3 = 18  kinematics
    # 2 * 3 * 3 = 18  marker trajectories
    # 2 * 3 * 3 = 18  marker trajectory derivatives
    # 2 * 3 * 3 = 18  kinematics derivatives
    #           = 72

    # If no markers (kin):
    # 2 * 3 * 3 = 18  kinematics
    # 2 * 3 * 3 = 18  kinematics derivatives
    #           = 36

    outputs = np.array([[0] * nframes]).T

    # Check if there are any kinematics in the file
    brk = True
    for point in btk.Iterate(acq.GetPoints()):
        if point.GetLabel() == "L" + kinematics[0]:
            brk = False
            break

    if brk:
        print("No kinematics in %s!" % (filename, ))
        return

    # Combine kinematics into one big array
    opposite = {'L': 'R', 'R': 'L'}
    angles = [None] * (len(kinematics) * 2)
    for i, v in enumerate(kinematics):
        point = acq.GetPoint(leg + v)
        angles[i] = point.GetValues()
        angles[i] = angles[i][:nframes]
        point = acq.GetPoint(opposite[leg] + v)
        angles[len(kinematics) + i] = point.GetValues()
        angles[len(kinematics) + i] = angles[len(kinematics) + i][:nframes]

    # Get the pelvis
    if sacr:
        SACR_X = acq.GetPoint("SACR").GetValues()[:, 0]
    else:
        LPSI_X = acq.GetPoint("LPSI").GetValues()[:, 0]
        RPSI_X = acq.GetPoint("RPSI").GetValues()[:, 0]
        midPSI_X = (LPSI_X + RPSI_X) / 2
        SACR_X = midPSI_X
    # incrementX = 1 if midASI[100][0] > midASI[0][0] else -1

    pos = [None] * (len(markers) * 2)

    pos_sacr_X = [None] * (len(markers) * 2)
    pos_sacr_Y = [None] * (len(markers) * 2)
    pos_sacr_Z = [None] * (len(markers) * 2)
    pos_sacr = [None] * (len(markers) * 2)
    for j, w in enumerate(markers):
        try:
            point = acq.GetPoint(leg + w)
            pos[j] = point.GetValues()
            pos_sacr_X[j] = point.GetValues()[:, 0] - SACR_X
            pos_sacr_Y[j] = point.GetValues()[:, 1]
            pos_sacr_Z[j] = point.GetValues()[:, 2]
            pos_sacr[j] = np.column_stack(
                (pos_sacr_X[j], pos_sacr_Y[j], pos_sacr_Z[j]))
            pos_sacr[j] = pos_sacr[j][:nframes]

            point = acq.GetPoint(opposite[leg] + w)
            pos[len(markers) + j] = point.GetValues()
            pos_sacr_X[len(markers) + j] = point.GetValues()[:, 0] - SACR_X
            pos_sacr_Y[len(markers) + j] = point.GetValues()[:, 1]
            pos_sacr_Z[len(markers) + j] = point.GetValues()[:, 2]
            pos_sacr[len(markers) + j] = np.column_stack(
                (pos_sacr_X[len(markers) + j], pos_sacr_Y[len(markers) + j],
                 pos_sacr_Z[len(markers) + j]))
            pos_sacr[len(markers) + j] = pos_sacr[len(markers) + j][:nframes]
        except:
            return

    # Low pass filter at 7Hz
    angles_lp = butter_lowpass_filter(np.hstack(angles), cutoff=7, fs=100)
    markers_lp = butter_lowpass_filter(np.hstack(pos_sacr), cutoff=7, fs=100)

    # Get derivatives
    angles_lp_vel = derivative(angles_lp, nframes)
    markers_lp_vel = derivative(markers_lp, nframes)

    angles = np.hstack((angles_lp, angles_lp_vel))
    markers = np.hstack((markers_lp, markers_lp_vel))

    if marker:
        curves = np.concatenate((angles, markers), axis=1)
    else:
        curves = angles

    # Add events as output
    for event in btk.Iterate(acq.GetEvents()):
        if start < event.GetFrame() < end:
            if event.GetLabel() == "Foot Strike":
                if event.GetContext() == 'Left':
                    outputs[event.GetFrame() - start, 0] = 1
                elif event.GetContext() == 'Right':
                    outputs[event.GetFrame() - start, 0] = 2
            elif event.GetLabel() == "Foot Off":
                if event.GetContext() == 'Left':
                    outputs[event.GetFrame() - start, 0] = 3
                elif event.GetContext() == 'Right':
                    outputs[event.GetFrame() - start, 0] = 4

    if (np.sum(outputs) == 0):
        print("No events in %s!" % (filename, ))
        return

    arr = np.concatenate((curves, outputs), axis=1)

    # Remove data before and after first event minus some random int. This is for those trials that are not pre-cut (Spildooren).
    if sacr:
        positives = np.where(arr[:, 36] > 0.5)
        if len(positives[0]) == 0:
            return None

        first_event = positives[0][0] - random.randint(5, 15)
        last_event = positives[0][-1] + random.randint(5, 15)
        arr = arr[first_event:last_event]

    print("Writig %s" % filename)
    np.savetxt(output_file, arr, delimiter=',')