Example #1
0
def calibrate(DATA_PATH, calibrateFilenameLabelled, translators, required_mp,
              optional_mp, leftFlatFoot, rightFlatFoot, headFlat,
              markerDiameter, pointSuffix, **kwargs):
    """
    Calibration of the CGM1

    :param DATA_PATH [str]: path to your data
    :param calibrateFilenameLabelled [str]: c3d file
    :param translators [dict]:  translators to apply
    :param required_mp [dict]: required anthropometric data
    :param optional_mp [dict]: optional anthropometric data (ex: LThighOffset,...)
    :param leftFlatFoot [bool]: enable of the flat foot option for the left foot
    :param rightFlatFoot [bool]: enable of the flat foot option for the right foot
    :param headFlat [bool]: enable of the head flat  option
    :param markerDiameter [double]: marker diameter (mm)
    :param pointSuffix [str]: suffix to add to model outputs

    """

    detectAnomaly = False

    if "anomalyException" in kwargs.keys():
        anomalyException = kwargs["anomalyException"]
    else:
        anomalyException = False
    # --------------------------ACQUISITION ------------------------------------

    if "forceBtkAcq" in kwargs.keys():
        acqStatic = kwargs["forceBtkAcq"]
    else:
        # ---btk acquisition---
        acqStatic = btkTools.smartReader(
            (DATA_PATH + calibrateFilenameLabelled))

    btkTools.checkMultipleSubject(acqStatic)
    if btkTools.isPointExist(acqStatic, "SACR"):
        translators["LPSI"] = "SACR"
        translators["RPSI"] = "SACR"
        LOGGER.logger.info("[pyCGM2] Sacrum marker detected")

    acqStatic = btkTools.applyTranslators(acqStatic, translators)

    trackingMarkers = cgm.CGM1.LOWERLIMB_TRACKING_MARKERS + cgm.CGM1.THORAX_TRACKING_MARKERS + cgm.CGM1.UPPERLIMB_TRACKING_MARKERS
    actual_trackingMarkers, phatoms_trackingMarkers = btkTools.createPhantoms(
        acqStatic, trackingMarkers)

    vff = acqStatic.GetFirstFrame()
    vlf = acqStatic.GetLastFrame()
    # vff,vlf = btkTools.getFrameBoundaries(acqStatic,actual_trackingMarkers)
    flag = btkTools.getValidFrames(acqStatic,
                                   actual_trackingMarkers,
                                   frameBounds=[vff, vlf])

    gapFlag = btkTools.checkGap(acqStatic,
                                actual_trackingMarkers,
                                frameBounds=[vff, vlf])
    if gapFlag:
        raise Exception(
            "[pyCGM2] Calibration aborted. Gap find during interval [%i-%i]. Crop your c3d "
            % (vff, vlf))

    # --------------------ANOMALY------------------------------
    # --Check MP
    adap = AnomalyDetectionProcedure.AnthropoDataAnomalyProcedure(required_mp)
    adf = AnomalyFilter.AnomalyDetectionFilter(None, None, adap)
    mp_anomaly = adf.run()
    if mp_anomaly["ErrorState"]: detectAnomaly = True

    # --marker presence
    markersets = [
        cgm.CGM1.LOWERLIMB_TRACKING_MARKERS, cgm.CGM1.THORAX_TRACKING_MARKERS,
        cgm.CGM1.UPPERLIMB_TRACKING_MARKERS
    ]
    for markerset in markersets:
        ipdp = InspectorProcedure.MarkerPresenceDetectionProcedure(markerset)
        idf = InspectorFilter.InspectorFilter(acqStatic,
                                              calibrateFilenameLabelled, ipdp)
        inspector = idf.run()

        # # --marker outliers
        if inspector["In"] != []:
            madp = AnomalyDetectionProcedure.MarkerAnomalyDetectionRollingProcedure(
                inspector["In"], plot=False, window=4, threshold=3)
            adf = AnomalyFilter.AnomalyDetectionFilter(
                acqStatic, calibrateFilenameLabelled, madp)
            anomaly = adf.run()
            anomalyIndexes = anomaly["Output"]
            if anomaly["ErrorState"]: detectAnomaly = True

    if detectAnomaly and anomalyException:
        raise Exception(
            "Anomalies has been detected - Check Warning message of the log file"
        )

    # --------------------MODELLING------------------------------

    # ---check marker set used----
    dcm = cgm.CGM.detectCalibrationMethods(acqStatic)

    # ---definition---
    model = cgm.CGM1()
    model.configure(detectedCalibrationMethods=dcm)
    model.addAnthropoInputParameters(required_mp, optional=optional_mp)

    if dcm["Left Knee"] == enums.JointCalibrationMethod.KAD:
        actual_trackingMarkers.append("LKNE")
    if dcm["Right Knee"] == enums.JointCalibrationMethod.KAD:
        actual_trackingMarkers.append("RKNE")
    model.setStaticTrackingMarkers(actual_trackingMarkers)

    # --store calibration parameters--
    model.setStaticFilename(calibrateFilenameLabelled)
    model.setCalibrationProperty("leftFlatFoot", leftFlatFoot)
    model.setCalibrationProperty("rightFlatFoot", rightFlatFoot)
    model.setCalibrationProperty("headFlat", headFlat)
    model.setCalibrationProperty("markerDiameter", markerDiameter)

    # --------------------------STATIC CALBRATION--------------------------
    scp = modelFilters.StaticCalibrationProcedure(
        model)  # load calibration procedure

    # ---initial calibration filter----
    modelFilters.ModelCalibrationFilter(scp,
                                        acqStatic,
                                        model,
                                        leftFlatFoot=leftFlatFoot,
                                        rightFlatFoot=rightFlatFoot,
                                        markerDiameter=markerDiameter,
                                        headFlat=headFlat,
                                        viconCGM1compatible=True).compute()
    # ---- Decorators -----
    decorators.applyBasicDecorators(dcm,
                                    model,
                                    acqStatic,
                                    optional_mp,
                                    markerDiameter,
                                    cgm1only=True)
    pigStaticMarkers = cgm.CGM.get_markerLabelForPiGStatic(dcm)

    # ----Final Calibration filter if model previously decorated -----
    if model.decoratedModel:
        # initial static filter
        modelFilters.ModelCalibrationFilter(
            scp,
            acqStatic,
            model,
            leftFlatFoot=leftFlatFoot,
            rightFlatFoot=rightFlatFoot,
            headFlat=headFlat,
            markerDiameter=markerDiameter,
            viconCGM1compatible=True).compute()

    # ----------------------CGM MODELLING----------------------------------
    # ----motion filter----
    # notice : viconCGM1compatible option duplicate error on Construction of the foot coordinate system

    modMotion = modelFilters.ModelMotionFilter(
        scp,
        acqStatic,
        model,
        enums.motionMethod.Determinist,
        markerDiameter=markerDiameter,
        viconCGM1compatible=False,
        pigStatic=True,
        useLeftKJCmarker=pigStaticMarkers[0],
        useLeftAJCmarker=pigStaticMarkers[1],
        useRightKJCmarker=pigStaticMarkers[2],
        useRightAJCmarker=pigStaticMarkers[3],
        leftFlatFoot=leftFlatFoot,
        rightFlatFoot=rightFlatFoot)

    modMotion.compute()

    # ----progression Frame----
    progressionFlag = False
    if btkTools.isPointsExist(acqStatic, ['LASI', 'RASI', 'RPSI', 'LPSI'],
                              ignorePhantom=False):
        LOGGER.logger.info(
            "[pyCGM2] - progression axis detected from Pelvic markers ")
        pfp = progressionFrame.PelvisProgressionFrameProcedure()
        pff = progressionFrame.ProgressionFrameFilter(acqStatic, pfp)
        pff.compute()
        progressionAxis = pff.outputs["progressionAxis"]
        globalFrame = pff.outputs["globalFrame"]
        forwardProgression = pff.outputs["forwardProgression"]
        progressionFlag = True
    elif btkTools.isPointsExist(acqStatic, ['C7', 'T10', 'CLAV', 'STRN'],
                                ignorePhantom=False) and not progressionFlag:
        LOGGER.logger.info(
            "[pyCGM2] - progression axis detected from Thoracic markers ")
        pfp = progressionFrame.ThoraxProgressionFrameProcedure()
        pff = progressionFrame.ProgressionFrameFilter(acqStatic, pfp)
        pff.compute()
        progressionAxis = pff.outputs["progressionAxis"]
        globalFrame = pff.outputs["globalFrame"]
        forwardProgression = pff.outputs["forwardProgression"]

    else:
        globalFrame = "XYZ"
        progressionAxis = "X"
        forwardProgression = True
        LOGGER.logger.error(
            "[pyCGM2] - impossible to detect progression axis - neither pelvic nor thoracic markers are present. Progression set to +X by default "
        )

    if "displayCoordinateSystem" in kwargs.keys(
    ) and kwargs["displayCoordinateSystem"]:
        csp = modelFilters.ModelCoordinateSystemProcedure(model)
        csdf = modelFilters.CoordinateSystemDisplayFilter(
            csp, model, acqStatic)
        csdf.setStatic(False)
        csdf.display()

    if "noKinematicsCalculation" in kwargs.keys(
    ) and kwargs["noKinematicsCalculation"]:
        LOGGER.logger.warning(
            "[pyCGM2] No Kinematic calculation done for the static file")
        return model, acqStatic
    else:
        #---- Joint kinematics----
        # relative angles
        modelFilters.ModelJCSFilter(model, acqStatic).compute(
            description="vectoriel", pointLabelSuffix=pointSuffix)

        modelFilters.ModelAbsoluteAnglesFilter(
            model,
            acqStatic,
            segmentLabels=[
                "Left Foot", "Right Foot", "Pelvis", "Thorax", "Head"
            ],
            angleLabels=[
                "LFootProgress", "RFootProgress", "Pelvis", "Thorax", "Head"
            ],
            eulerSequences=["TOR", "TOR", "TOR", "YXZ", "TOR"],
            globalFrameOrientation=globalFrame,
            forwardProgression=forwardProgression).compute(
                pointLabelSuffix=pointSuffix)

        # BSP model
        bspModel = bodySegmentParameters.Bsp(model)
        bspModel.compute()

        modelFilters.CentreOfMassFilter(
            model, acqStatic).compute(pointLabelSuffix=pointSuffix)

        btkTools.cleanAcq(acqStatic)
        if detectAnomaly and not anomalyException:
            LOGGER.logger.error(
                "Anomalies has been detected - Check Warning messages of the log file"
            )

        return model, acqStatic, detectAnomaly
Example #2
0
def fitting(model, DATA_PATH, reconstructFilenameLabelled, translators,
            markerDiameter, pointSuffix, mfpa, momentProjection, **kwargs):
    """
    Fitting of the CGM1

    :param model [str]: pyCGM2 model previously calibrated
    :param DATA_PATH [str]: path to your data
    :param reconstructFilenameLabelled [string list]: c3d files
    :param translators [dict]:  translators to apply
    :param mfpa [str]: manual force plate assignement
    :param markerDiameter [double]: marker diameter (mm)
    :param pointSuffix [str]: suffix to add to model outputs
    :param momentProjection [str]: Coordinate system in which joint moment is expressed

    """

    detectAnomaly = False
    if "anomalyException" in kwargs.keys():
        anomalyException = kwargs["anomalyException"]
    else:
        anomalyException = False

    # --- btk acquisition ----
    if "forceBtkAcq" in kwargs.keys():
        acqGait = kwargs["forceBtkAcq"]
    else:
        acqGait = btkTools.smartReader(
            (DATA_PATH + reconstructFilenameLabelled))

    btkTools.checkMultipleSubject(acqGait)
    if btkTools.isPointExist(acqGait, "SACR"):
        translators["LPSI"] = "SACR"
        translators["RPSI"] = "SACR"
        LOGGER.logger.info("[pyCGM2] Sacrum marker detected")

    acqGait = btkTools.applyTranslators(acqGait, translators)

    trackingMarkers = cgm.CGM1.LOWERLIMB_TRACKING_MARKERS + cgm.CGM1.THORAX_TRACKING_MARKERS + cgm.CGM1.UPPERLIMB_TRACKING_MARKERS
    actual_trackingMarkers, phatoms_trackingMarkers = btkTools.createPhantoms(
        acqGait, trackingMarkers)
    vff, vlf = btkTools.getFrameBoundaries(acqGait, actual_trackingMarkers)
    if "frameInit" in kwargs.keys() and kwargs["frameInit"] is not None:
        vff = kwargs["frameInit"]
        LOGGER.logger.info("[pyCGM2]  first frame forced to frame [%s]" %
                           (vff))
    if "frameEnd" in kwargs.keys() and kwargs["frameEnd"] is not None:
        vlf = kwargs["frameEnd"]
        LOGGER.logger.info("[pyCGM2]  end frame forced to frame [%s]" % (vlf))
    flag = btkTools.getValidFrames(acqGait,
                                   actual_trackingMarkers,
                                   frameBounds=[vff, vlf])

    LOGGER.logger.info("[pyCGM2]  Computation from frame [%s] to frame [%s]" %
                       (vff, vlf))
    # --------------------ANOMALY------------------------------
    for marker in actual_trackingMarkers:
        if marker not in model.getStaticTrackingMarkers():
            LOGGER.logger.warning(
                "[pyCGM2-Anomaly]  marker [%s] - not used during static calibration - wrong kinematic for the segment attached to this marker. "
                % (marker))

    # --marker presence
    markersets = [
        cgm.CGM1.LOWERLIMB_TRACKING_MARKERS, cgm.CGM1.THORAX_TRACKING_MARKERS,
        cgm.CGM1.UPPERLIMB_TRACKING_MARKERS
    ]
    for markerset in markersets:
        ipdp = InspectorProcedure.MarkerPresenceDetectionProcedure(markerset)
        idf = InspectorFilter.InspectorFilter(acqGait,
                                              reconstructFilenameLabelled,
                                              ipdp)
        inspector = idf.run()

        # --marker outliers
        if inspector["In"] != []:
            madp = AnomalyDetectionProcedure.MarkerAnomalyDetectionRollingProcedure(
                inspector["In"], plot=False, window=5, threshold=3)
            adf = AnomalyFilter.AnomalyDetectionFilter(
                acqGait,
                reconstructFilenameLabelled,
                madp,
                frameRange=[vff, vlf])
            anomaly = adf.run()
            anomalyIndexes = anomaly["Output"]
            if anomaly["ErrorState"]: detectAnomaly = True

    if btkTools.checkForcePlateExist(acqGait):
        afpp = AnomalyDetectionProcedure.ForcePlateAnomalyProcedure()
        adf = AnomalyFilter.AnomalyDetectionFilter(acqGait,
                                                   reconstructFilenameLabelled,
                                                   afpp,
                                                   frameRange=[vff, vlf])
        anomaly = adf.run()
        if anomaly["ErrorState"]: detectAnomaly = True

    if detectAnomaly and anomalyException:
        raise Exception(
            "Anomalies has been detected - Check Warning message of the log file"
        )

# --------------------MODELLING------------------------------

# filtering
# -----------------------
    if "fc_lowPass_marker" in kwargs.keys(
    ) and kwargs["fc_lowPass_marker"] != 0:
        fc = kwargs["fc_lowPass_marker"]
        order = 4
        if "order_lowPass_marker" in kwargs.keys():
            order = kwargs["order_lowPass_marker"]
        signal_processing.markerFiltering(acqGait,
                                          trackingMarkers,
                                          order=order,
                                          fc=fc)

    if "fc_lowPass_forcePlate" in kwargs.keys(
    ) and kwargs["fc_lowPass_forcePlate"] != 0:
        fc = kwargs["fc_lowPass_forcePlate"]
        order = 4
        if "order_lowPass_forcePlate" in kwargs.keys():
            order = kwargs["order_lowPass_forcePlate"]
        signal_processing.forcePlateFiltering(acqGait, order=order, fc=fc)

    scp = modelFilters.StaticCalibrationProcedure(model)  # procedure
    # ---Motion filter----
    modMotion = modelFilters.ModelMotionFilter(scp,
                                               acqGait,
                                               model,
                                               enums.motionMethod.Determinist,
                                               markerDiameter=markerDiameter,
                                               viconCGM1compatible=True)

    modMotion.compute()

    progressionFlag = False
    if btkTools.isPointExist(acqGait, 'LHEE',
                             ignorePhantom=False) or btkTools.isPointExist(
                                 acqGait, 'RHEE', ignorePhantom=False):

        pfp = progressionFrame.PointProgressionFrameProcedure(marker="LHEE") \
            if btkTools.isPointExist(acqGait, 'LHEE',ignorePhantom=False) \
            else  progressionFrame.PointProgressionFrameProcedure(marker="RHEE")

        pff = progressionFrame.ProgressionFrameFilter(acqGait, pfp)
        pff.compute()
        progressionAxis = pff.outputs["progressionAxis"]
        globalFrame = pff.outputs["globalFrame"]
        forwardProgression = pff.outputs["forwardProgression"]
        progressionFlag = True

    elif btkTools.isPointsExist(acqGait, ['LASI', 'RASI', 'RPSI', 'LPSI'],
                                ignorePhantom=False) and not progressionFlag:
        LOGGER.logger.info(
            "[pyCGM2] - progression axis detected from Pelvic markers ")
        pfp = progressionFrame.PelvisProgressionFrameProcedure()
        pff = progressionFrame.ProgressionFrameFilter(acqGait, pfp)
        pff.compute()
        globalFrame = pff.outputs["globalFrame"]
        forwardProgression = pff.outputs["forwardProgression"]

        progressionFlag = True
    elif btkTools.isPointsExist(acqGait, ['C7', 'T10', 'CLAV', 'STRN'],
                                ignorePhantom=False) and not progressionFlag:
        LOGGER.logger.info(
            "[pyCGM2] - progression axis detected from Thoracic markers ")
        pfp = progressionFrame.ThoraxProgressionFrameProcedure()
        pff = progressionFrame.ProgressionFrameFilter(acqGait, pfp)
        pff.compute()
        progressionAxis = pff.outputs["progressionAxis"]
        globalFrame = pff.outputs["globalFrame"]
        forwardProgression = pff.outputs["forwardProgression"]

    else:
        globalFrame = "XYZ"
        progressionAxis = "X"
        forwardProgression = True
        LOGGER.logger.error(
            "[pyCGM2] - impossible to detect progression axis - neither pelvic nor thoracic markers are present. Progression set to +X by default "
        )

    if "displayCoordinateSystem" in kwargs.keys(
    ) and kwargs["displayCoordinateSystem"]:
        csp = modelFilters.ModelCoordinateSystemProcedure(model)
        csdf = modelFilters.CoordinateSystemDisplayFilter(csp, model, acqGait)
        csdf.setStatic(False)
        csdf.display()

    #---- Joint kinematics----
    # relative angles
    modelFilters.ModelJCSFilter(model,
                                acqGait).compute(description="vectoriel",
                                                 pointLabelSuffix=pointSuffix)

    modelFilters.ModelAbsoluteAnglesFilter(
        model,
        acqGait,
        segmentLabels=["Left Foot", "Right Foot", "Pelvis", "Thorax", "Head"],
        angleLabels=[
            "LFootProgress", "RFootProgress", "Pelvis", "Thorax", "Head"
        ],
        eulerSequences=["TOR", "TOR", "TOR", "YXZ", "TOR"],
        globalFrameOrientation=globalFrame,
        forwardProgression=forwardProgression).compute(
            pointLabelSuffix=pointSuffix)

    #---- Body segment parameters----
    bspModel = bodySegmentParameters.Bsp(model)
    bspModel.compute()

    #---- CentreOfMass----
    if model.m_bodypart == enums.BodyPart.FullBody:
        modelFilters.CentreOfMassFilter(
            model, acqGait).compute(pointLabelSuffix=pointSuffix)

    if btkTools.checkForcePlateExist(acqGait):
        # Inverse dynamics
        if model.m_bodypart != enums.BodyPart.UpperLimb:
            # --- force plate handling----
            # find foot  in contact
            mappedForcePlate = forceplates.matchingFootSideOnForceplate(
                acqGait, mfpa=mfpa)
            forceplates.addForcePlateGeneralEvents(acqGait, mappedForcePlate)
            LOGGER.logger.info("Manual Force plate assignment : %s" %
                               mappedForcePlate)

            # assembly foot and force plate
            modelFilters.ForcePlateAssemblyFilter(
                model,
                acqGait,
                mappedForcePlate,
                leftSegmentLabel="Left Foot",
                rightSegmentLabel="Right Foot").compute(
                    pointLabelSuffix=pointSuffix)

            #---- Joint kinetics----
            if type(momentProjection) == str:
                momentProjection = enums.enumFromtext(momentProjection,
                                                      enums.MomentProjection)
            idp = modelFilters.CGMLowerlimbInverseDynamicProcedure()
            modelFilters.InverseDynamicFilter(
                model,
                acqGait,
                procedure=idp,
                projection=momentProjection,
                viconCGM1compatible=True,
                globalFrameOrientation=globalFrame,
                forwardProgression=forwardProgression).compute(
                    pointLabelSuffix=pointSuffix)

            #---- Joint energetics----
            modelFilters.JointPowerFilter(
                model, acqGait).compute(pointLabelSuffix=pointSuffix)

    btkTools.cleanAcq(acqGait)
    btkTools.applyOnValidFrames(acqGait, flag)

    if detectAnomaly and not anomalyException:
        LOGGER.logger.error(
            "Anomalies has been detected - Check Warning messages of the log file"
        )

    return acqGait, detectAnomaly
Example #3
0
    def advancedCGM1_kadMed_manualTibialTorsion(cls):
        """
        - constraints on both tibial Torsion But application of a KAD-med calibration
        => tibial Torsion has to be udpated

        """
        MAIN_PATH = pyCGM2.TEST_DATA_PATH + "CGM1\\CGM1-TESTS\\KAD-Med\\"
        staticFilename = "MRI-US-01, 2008-08-08, 3DGA 02.c3d"

        acqStatic = btkTools.smartReader(str(MAIN_PATH + staticFilename))

        model = cgm.CGM1
        model.configure()
        markerDiameter = 14
        mp = {
            'Bodymass': 71.0,
            'LeftLegLength': 860.0,
            'RightLegLength': 865.0,
            'LeftKneeWidth': 102.0,
            'RightKneeWidth': 103.4,
            'LeftAnkleWidth': 75.3,
            'RightAnkleWidth': 72.9,
            'LeftSoleDelta': 0,
            'RightSoleDelta': 0,
        }

        optional_mp = {
            'InterAsisDistance': 0,
            'LeftAsisTrocanterDistance': 0,
            'LeftThighRotation': 0,
            'LeftShankRotation': 0,
            'LeftTibialTorsion': -10,
            'RightAsisTrocanterDistance': 0,
            'RightThighRotation': 0,
            'RightShankRotation': 0,
            'RightTibialTorsion': 15
        }

        model.addAnthropoInputParameters(mp, optional=optional_mp)

        # -----------CGM STATIC CALIBRATION--------------------
        scp = modelFilters.StaticCalibrationProcedure(model)
        modelFilters.ModelCalibrationFilter(scp, acqStatic, model).compute()

        # cgm decorator
        modelDecorator.Kad(model, acqStatic).compute()
        modelDecorator.AnkleCalibrationDecorator(model).midMaleolus(
            acqStatic, side="both")

        modelFilters.ModelCalibrationFilter(scp, acqStatic, model).compute()

        np.testing.assert_equal(model.m_useRightTibialTorsion, True)
        np.testing.assert_equal(model.m_useLeftTibialTorsion, True)
        np.testing.assert_equal(model.mp["LeftTibialTorsion"],
                                0)  # cancel by the decorator
        np.testing.assert_equal(model.mp["RightTibialTorsion"], 0)

        ltt_vicon = np.rad2deg(
            acqStatic.GetMetaData().FindChild("PROCESSING").value().FindChild(
                "LTibialTorsion").value().GetInfo().ToDouble()[0])
        rtt_vicon = np.rad2deg(
            acqStatic.GetMetaData().FindChild("PROCESSING").value().FindChild(
                "RTibialTorsion").value().GetInfo().ToDouble()[0])

        np.testing.assert_almost_equal(
            -1.0 * model.mp_computed["LeftTibialTorsionOffset"],
            ltt_vicon,
            decimal=3)
        np.testing.assert_almost_equal(
            model.mp_computed["RightTibialTorsionOffset"],
            rtt_vicon,
            decimal=3)
Example #4
0
def calibrate(DATA_PATH, calibrateFilenameLabelled, translators, settings,
              required_mp, optional_mp, ik_flag, leftFlatFoot, rightFlatFoot,
              markerDiameter, hjcMethod, pointSuffix):

    # --------------------ACQUISITION------------------------------

    # ---btk acquisition---
    acqStatic = btkTools.smartReader(str(DATA_PATH +
                                         calibrateFilenameLabelled))
    btkTools.checkMultipleSubject(acqStatic)

    acqStatic = btkTools.applyTranslators(acqStatic, translators)

    # ---definition---
    model = cgm2.CGM2_2LowerLimbs()
    model.configure()

    model.addAnthropoInputParameters(required_mp, optional=optional_mp)
    # --store calibration parameters--
    model.setStaticFilename(calibrateFilenameLabelled)
    model.setCalibrationProperty("leftFlatFoot", leftFlatFoot)
    model.setCalibrationProperty("rightFlatFoot", rightFlatFoot)
    model.setCalibrationProperty("markerDiameter", markerDiameter)

    # ---check marker set used----
    smc = cgm.CGM.checkCGM1_StaticMarkerConfig(acqStatic)

    # --------------------------STATIC CALBRATION--------------------------
    scp = modelFilters.StaticCalibrationProcedure(
        model)  # load calibration procedure

    # ---initial calibration filter----
    # use if all optional mp are zero
    modelFilters.ModelCalibrationFilter(
        scp,
        acqStatic,
        model,
        leftFlatFoot=leftFlatFoot,
        rightFlatFoot=rightFlatFoot,
        markerDiameter=markerDiameter,
    ).compute()

    # ---- Decorators -----
    decorators.applyDecorators_CGM(smc, model, acqStatic, optional_mp,
                                   markerDiameter)
    decorators.applyHJCDecorators(model, hjcMethod)

    # ----Final Calibration filter if model previously decorated -----
    if model.decoratedModel:
        # initial static filter
        modelFilters.ModelCalibrationFilter(
            scp,
            acqStatic,
            model,
            leftFlatFoot=leftFlatFoot,
            rightFlatFoot=rightFlatFoot,
            markerDiameter=markerDiameter).compute()

    # ----------------------CGM MODELLING----------------------------------
    # ----motion filter----
    modMotion = modelFilters.ModelMotionFilter(scp,
                                               acqStatic,
                                               model,
                                               enums.motionMethod.Determinist,
                                               markerDiameter=markerDiameter)

    modMotion.compute()

    if ik_flag:
        #                        ---OPENSIM IK---

        # --- opensim calibration Filter ---
        osimfile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\osim\\lowerLimb_ballsJoints.osim"  # osimfile
        markersetFile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\settings\\cgm1\\cgm1-markerset.xml"  # markerset
        cgmCalibrationprocedure = opensimFilters.CgmOpensimCalibrationProcedures(
            model)  # procedure

        oscf = opensimFilters.opensimCalibrationFilter(
            osimfile, model, cgmCalibrationprocedure, str(DATA_PATH))
        oscf.addMarkerSet(markersetFile)
        scalingOsim = oscf.build()

        # --- opensim Fitting Filter ---
        iksetupFile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\settings\\cgm1\\cgm1-ikSetUp_template.xml"  # ik tool file

        cgmFittingProcedure = opensimFilters.CgmOpensimFittingProcedure(
            model)  # procedure
        cgmFittingProcedure.updateMarkerWeight(
            "LASI", settings["Fitting"]["Weight"]["LASI"])
        cgmFittingProcedure.updateMarkerWeight(
            "RASI", settings["Fitting"]["Weight"]["RASI"])
        cgmFittingProcedure.updateMarkerWeight(
            "LPSI", settings["Fitting"]["Weight"]["LPSI"])
        cgmFittingProcedure.updateMarkerWeight(
            "RPSI", settings["Fitting"]["Weight"]["RPSI"])
        cgmFittingProcedure.updateMarkerWeight(
            "RTHI", settings["Fitting"]["Weight"]["RTHI"])
        cgmFittingProcedure.updateMarkerWeight(
            "RKNE", settings["Fitting"]["Weight"]["RKNE"])
        cgmFittingProcedure.updateMarkerWeight(
            "RTIB", settings["Fitting"]["Weight"]["RTIB"])
        cgmFittingProcedure.updateMarkerWeight(
            "RANK", settings["Fitting"]["Weight"]["RANK"])
        cgmFittingProcedure.updateMarkerWeight(
            "RHEE", settings["Fitting"]["Weight"]["RHEE"])
        cgmFittingProcedure.updateMarkerWeight(
            "RTOE", settings["Fitting"]["Weight"]["RTOE"])
        cgmFittingProcedure.updateMarkerWeight(
            "LTHI", settings["Fitting"]["Weight"]["LTHI"])
        cgmFittingProcedure.updateMarkerWeight(
            "LKNE", settings["Fitting"]["Weight"]["LKNE"])
        cgmFittingProcedure.updateMarkerWeight(
            "LTIB", settings["Fitting"]["Weight"]["LTIB"])
        cgmFittingProcedure.updateMarkerWeight(
            "LANK", settings["Fitting"]["Weight"]["LANK"])
        cgmFittingProcedure.updateMarkerWeight(
            "LHEE", settings["Fitting"]["Weight"]["LHEE"])
        cgmFittingProcedure.updateMarkerWeight(
            "LTOE", settings["Fitting"]["Weight"]["LTOE"])

        osrf = opensimFilters.opensimFittingFilter(iksetupFile, scalingOsim,
                                                   cgmFittingProcedure,
                                                   str(DATA_PATH))
        acqStaticIK = osrf.run(acqStatic,
                               str(DATA_PATH + calibrateFilenameLabelled))

        # --- final pyCGM2 model motion Filter ---
        # use fitted markers
        modMotionFitted = modelFilters.ModelMotionFilter(
            scp, acqStaticIK, model, enums.motionMethod.Determinist)

        modMotionFitted.compute()

    # eventual static acquisition to consider for joint kinematics
    finalAcqStatic = acqStaticIK if ik_flag else acqStatic

    #---- Joint kinematics----
    # relative angles
    modelFilters.ModelJCSFilter(model, finalAcqStatic).compute(
        description="vectoriel", pointLabelSuffix=pointSuffix)

    # detection of traveling axis
    longitudinalAxis, forwardProgression, globalFrame = btkTools.findProgressionAxisFromPelvicMarkers(
        finalAcqStatic, ["LASI", "RASI", "RPSI", "LPSI"])

    # absolute angles
    modelFilters.ModelAbsoluteAnglesFilter(
        model,
        finalAcqStatic,
        segmentLabels=["Left Foot", "Right Foot", "Pelvis"],
        angleLabels=["LFootProgress", "RFootProgress", "Pelvis"],
        eulerSequences=["TOR", "TOR", "ROT"],
        globalFrameOrientation=globalFrame,
        forwardProgression=forwardProgression).compute(
            pointLabelSuffix=pointSuffix)

    return model, finalAcqStatic
Example #5
0
def fitting(model, DATA_PATH, reconstructFilenameLabelled, translators,
            settings, markerDiameter, pointSuffix, mfpa, momentProjection,
            **kwargs):
    """
    Fitting of the CGM2.2

    :param model [str]: pyCGM2 model previously calibrated
    :param DATA_PATH [str]: path to your data
    :param reconstructFilenameLabelled [string list]: c3d files
    :param translators [dict]:  translators to apply
    :param mfpa [str]: manual force plate assignement
    :param markerDiameter [double]: marker diameter (mm)
    :param pointSuffix [str]: suffix to add to model outputs
    :param momentProjection [str]: Coordinate system in which joint moment is expressed
    """

    # --------------------------ACQUISITION ------------------------------------

    # --- btk acquisition ----
    if "forceBtkAcq" in kwargs.keys():
        acqGait = kwargs["forceBtkAcq"]
    else:
        acqGait = btkTools.smartReader(
            str(DATA_PATH + reconstructFilenameLabelled))

    btkTools.checkMultipleSubject(acqGait)
    acqGait = btkTools.applyTranslators(acqGait, translators)
    trackingMarkers = model.getTrackingMarkers()
    validFrames, vff, vlf = btkTools.findValidFrames(acqGait, trackingMarkers)

    # --- initial motion Filter ---
    scp = modelFilters.StaticCalibrationProcedure(model)
    modMotion = modelFilters.ModelMotionFilter(scp, acqGait, model,
                                               enums.motionMethod.Determinist)
    modMotion.compute()

    #                        ---OPENSIM IK---

    # --- opensim calibration Filter ---
    osimfile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\osim\\lowerLimb_ballsJoints.osim"  # osimfile
    markersetFile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\settings\\cgm1\\cgm1-markerset.xml"  # markerset
    cgmCalibrationprocedure = opensimFilters.CgmOpensimCalibrationProcedures(
        model)  # procedure

    oscf = opensimFilters.opensimCalibrationFilter(osimfile, model,
                                                   cgmCalibrationprocedure,
                                                   str(DATA_PATH))
    oscf.addMarkerSet(markersetFile)
    scalingOsim = oscf.build()

    # --- opensim Fitting Filter ---
    iksetupFile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\settings\\cgm1\\cgm1-ikSetUp_template.xml"  # ik tool file

    cgmFittingProcedure = opensimFilters.CgmOpensimFittingProcedure(
        model)  # procedure
    cgmFittingProcedure.updateMarkerWeight(
        "LASI", settings["Fitting"]["Weight"]["LASI"])
    cgmFittingProcedure.updateMarkerWeight(
        "RASI", settings["Fitting"]["Weight"]["RASI"])
    cgmFittingProcedure.updateMarkerWeight(
        "LPSI", settings["Fitting"]["Weight"]["LPSI"])
    cgmFittingProcedure.updateMarkerWeight(
        "RPSI", settings["Fitting"]["Weight"]["RPSI"])
    cgmFittingProcedure.updateMarkerWeight(
        "RTHI", settings["Fitting"]["Weight"]["RTHI"])
    cgmFittingProcedure.updateMarkerWeight(
        "RKNE", settings["Fitting"]["Weight"]["RKNE"])
    cgmFittingProcedure.updateMarkerWeight(
        "RTIB", settings["Fitting"]["Weight"]["RTIB"])
    cgmFittingProcedure.updateMarkerWeight(
        "RANK", settings["Fitting"]["Weight"]["RANK"])
    cgmFittingProcedure.updateMarkerWeight(
        "RHEE", settings["Fitting"]["Weight"]["RHEE"])
    cgmFittingProcedure.updateMarkerWeight(
        "RTOE", settings["Fitting"]["Weight"]["RTOE"])
    cgmFittingProcedure.updateMarkerWeight(
        "LTHI", settings["Fitting"]["Weight"]["LTHI"])
    cgmFittingProcedure.updateMarkerWeight(
        "LKNE", settings["Fitting"]["Weight"]["LKNE"])
    cgmFittingProcedure.updateMarkerWeight(
        "LTIB", settings["Fitting"]["Weight"]["LTIB"])
    cgmFittingProcedure.updateMarkerWeight(
        "LANK", settings["Fitting"]["Weight"]["LANK"])
    cgmFittingProcedure.updateMarkerWeight(
        "LHEE", settings["Fitting"]["Weight"]["LHEE"])
    cgmFittingProcedure.updateMarkerWeight(
        "LTOE", settings["Fitting"]["Weight"]["LTOE"])

    osrf = opensimFilters.opensimFittingFilter(iksetupFile, scalingOsim,
                                               cgmFittingProcedure,
                                               str(DATA_PATH))

    logging.info("-------INVERSE KINEMATICS IN PROGRESS----------")
    acqIK = osrf.run(acqGait, str(DATA_PATH + reconstructFilenameLabelled))
    logging.info("-------INVERSE KINEMATICS DONE-----------------")

    # --- final pyCGM2 model motion Filter ---
    # use fitted markers
    modMotionFitted = modelFilters.ModelMotionFilter(
        scp,
        acqIK,
        model,
        enums.motionMethod.Determinist,
        markerDiameter=markerDiameter)

    modMotionFitted.compute()

    if "displayCoordinateSystem" in kwargs.keys(
    ) and kwargs["displayCoordinateSystem"]:
        csp = modelFilters.ModelCoordinateSystemProcedure(model)
        csdf = modelFilters.CoordinateSystemDisplayFilter(csp, model, acqIK)
        csdf.setStatic(False)
        csdf.display()

    #---- Joint kinematics----
    # relative angles
    modelFilters.ModelJCSFilter(model,
                                acqIK).compute(description="vectoriel",
                                               pointLabelSuffix=pointSuffix)

    # detection of traveling axis + absolute angle
    if model.m_bodypart != enums.BodyPart.UpperLimb:
        longitudinalAxis, forwardProgression, globalFrame = btkTools.findProgressionAxisFromPelvicMarkers(
            acqIK, ["LASI", "LPSI", "RASI", "RPSI"])
    else:
        longitudinalAxis, forwardProgression, globalFrame = btkTools.findProgressionAxisFromLongAxis(
            acqIK, "C7", "CLAV")

    if model.m_bodypart != enums.BodyPart.UpperLimb:
        modelFilters.ModelAbsoluteAnglesFilter(
            model,
            acqIK,
            segmentLabels=["Left Foot", "Right Foot", "Pelvis"],
            angleLabels=["LFootProgress", "RFootProgress", "Pelvis"],
            eulerSequences=["TOR", "TOR", "ROT"],
            globalFrameOrientation=globalFrame,
            forwardProgression=forwardProgression).compute(
                pointLabelSuffix=pointSuffix)

    if model.m_bodypart == enums.BodyPart.LowerLimbTrunk:
        modelFilters.ModelAbsoluteAnglesFilter(
            model,
            acqIK,
            segmentLabels=["Thorax"],
            angleLabels=["Thorax"],
            eulerSequences=["YXZ"],
            globalFrameOrientation=globalFrame,
            forwardProgression=forwardProgression).compute(
                pointLabelSuffix=pointSuffix)

    if model.m_bodypart == enums.BodyPart.UpperLimb or model.m_bodypart == enums.BodyPart.FullBody:

        modelFilters.ModelAbsoluteAnglesFilter(
            model,
            acqIK,
            segmentLabels=["Thorax", "Head"],
            angleLabels=["Thorax", "Head"],
            eulerSequences=["YXZ", "TOR"],
            globalFrameOrientation=globalFrame,
            forwardProgression=forwardProgression).compute(
                pointLabelSuffix=pointSuffix)

    #---- Body segment parameters----
    bspModel = bodySegmentParameters.Bsp(model)
    bspModel.compute()

    if model.m_bodypart == enums.BodyPart.FullBody:
        modelFilters.CentreOfMassFilter(
            model, acqIK).compute(pointLabelSuffix=pointSuffix)

    # Inverse dynamics
    if model.m_bodypart != enums.BodyPart.UpperLimb:
        # --- force plate handling----
        # find foot  in contact
        mappedForcePlate = forceplates.matchingFootSideOnForceplate(acqIK,
                                                                    mfpa=mfpa)
        forceplates.addForcePlateGeneralEvents(acqIK, mappedForcePlate)
        logging.warning("Manual Force plate assignment : %s" %
                        mappedForcePlate)

        # assembly foot and force plate
        modelFilters.ForcePlateAssemblyFilter(
            model,
            acqIK,
            mappedForcePlate,
            leftSegmentLabel="Left Foot",
            rightSegmentLabel="Right Foot").compute()

        #---- Joint kinetics----
        idp = modelFilters.CGMLowerlimbInverseDynamicProcedure()
        modelFilters.InverseDynamicFilter(
            model,
            acqIK,
            procedure=idp,
            projection=momentProjection,
        ).compute(pointLabelSuffix=pointSuffix)

        #---- Joint energetics----
        modelFilters.JointPowerFilter(
            model, acqIK).compute(pointLabelSuffix=pointSuffix)

    #---- zero unvalid frames ---
    btkTools.applyValidFramesOnOutput(acqIK, validFrames)

    return acqIK
Example #6
0
def fitting(model,DATA_PATH, reconstructFilenameLabelled,
    translators,weights,
    ik_flag,markerDiameter,
    pointSuffix,
    mfpa,
    momentProjection,**kwargs):

    """
    Fitting of the CGM2.4

    :param model [str]: pyCGM2 model previously calibrated
    :param DATA_PATH [str]: path to your data
    :param reconstructFilenameLabelled [string list]: c3d files
    :param translators [dict]:  translators to apply
    :param ik_flag [bool]: enable the inverse kinematic solver
    :param mfpa [str]: manual force plate assignement
    :param markerDiameter [double]: marker diameter (mm)
    :param pointSuffix [str]: suffix to add to model outputs
    :param momentProjection [str]: Coordinate system in which joint moment is expressed
    """

    detectAnomaly = False
    if "anomalyException" in kwargs.keys():
        anomalyException = kwargs["anomalyException"]
    else:
        anomalyException=False


    if "forceFoot6DoF" in kwargs.keys() and kwargs["forceFoot6DoF"]:
        forceFoot6DoF_flag = True
    else:
        forceFoot6DoF_flag=False

    if "Fitting" in weights.keys():
        weights  = weights["Fitting"]["Weight"]

    if "forceBtkAcq" in kwargs.keys():
        acqGait = kwargs["forceBtkAcq"]
    else:
        acqGait = btkTools.smartReader((DATA_PATH + reconstructFilenameLabelled))

    btkTools.checkMultipleSubject(acqGait)
    if btkTools.isPointExist(acqGait,"SACR"):
        translators["LPSI"] = "SACR"
        translators["RPSI"] = "SACR"
        LOGGER.logger.info("[pyCGM2] Sacrum marker detected")

    acqGait =  btkTools.applyTranslators(acqGait,translators)
    trackingMarkers = cgm2.CGM2_4.LOWERLIMB_TRACKING_MARKERS + cgm2.CGM2_4.THORAX_TRACKING_MARKERS+ cgm2.CGM2_4.UPPERLIMB_TRACKING_MARKERS
    actual_trackingMarkers,phatoms_trackingMarkers = btkTools.createPhantoms(acqGait, trackingMarkers)
    vff,vlf = btkTools.getFrameBoundaries(acqGait,actual_trackingMarkers)
    if "frameInit" in kwargs.keys() and kwargs["frameInit"] is not None:
        vff = kwargs["frameInit"]
        LOGGER.logger.info("[pyCGM2]  first frame forced to frame [%s]"%(vff))
    if "frameEnd" in kwargs.keys() and kwargs["frameEnd"] is not None:
        vlf = kwargs["frameEnd"]
        LOGGER.logger.info("[pyCGM2]  end frame forced to frame [%s]"%(vlf))
    flag = btkTools.getValidFrames(acqGait,actual_trackingMarkers,frameBounds=[vff,vlf])

    LOGGER.logger.info("[pyCGM2]  Computation from frame [%s] to frame [%s]"%(vff,vlf))
    # --------------------ANOMALY------------------------------
    for marker in actual_trackingMarkers:
        if marker not in model.getStaticTrackingMarkers():
            LOGGER.logger.warning("[pyCGM2-Anomaly]  marker [%s] - not used during static calibration - wrong kinematic for the segment attached to this marker. "%(marker))

    # --marker presence
    markersets = [cgm2.CGM2_4.LOWERLIMB_TRACKING_MARKERS, cgm2.CGM2_4.THORAX_TRACKING_MARKERS, cgm2.CGM2_4.UPPERLIMB_TRACKING_MARKERS]
    for markerset in markersets:
        ipdp = InspectorProcedure.MarkerPresenceDetectionProcedure( markerset)
        idf = InspectorFilter.InspectorFilter(acqGait,reconstructFilenameLabelled,ipdp)
        inspector = idf.run()

        # --marker outliers
        if inspector["In"] !=[]:
            madp = AnomalyDetectionProcedure.MarkerAnomalyDetectionRollingProcedure( inspector["In"], plot=False, window=5,threshold = 3)
            adf = AnomalyFilter.AnomalyDetectionFilter(acqGait,reconstructFilenameLabelled,madp, frameRange=[vff,vlf])
            anomaly = adf.run()
            anomalyIndexes = anomaly["Output"]
            if anomaly["ErrorState"]: detectAnomaly = True


    if btkTools.checkForcePlateExist(acqGait):
        afpp = AnomalyDetectionProcedure.ForcePlateAnomalyProcedure()
        adf = AnomalyFilter.AnomalyDetectionFilter(acqGait,reconstructFilenameLabelled,afpp, frameRange=[vff,vlf])
        anomaly = adf.run()
        if anomaly["ErrorState"]: detectAnomaly = True

    if detectAnomaly and anomalyException:
        raise Exception ("Anomalies has been detected - Check Warning message of the log file")

    # --------------------MODELLING------------------------------

    # filtering
    # -----------------------
    if "fc_lowPass_marker" in kwargs.keys() and kwargs["fc_lowPass_marker"]!=0 :
        fc = kwargs["fc_lowPass_marker"]
        order = 4
        if "order_lowPass_marker" in kwargs.keys():
            order = kwargs["order_lowPass_marker"]
        signal_processing.markerFiltering(acqGait,trackingMarkers,order=order, fc =fc)

    if "fc_lowPass_forcePlate" in kwargs.keys() and kwargs["fc_lowPass_forcePlate"]!=0 :
        fc = kwargs["fc_lowPass_forcePlate"]
        order = 4
        if "order_lowPass_forcePlate" in kwargs.keys():
            order = kwargs["order_lowPass_forcePlate"]
        signal_processing.forcePlateFiltering(acqGait,order=order, fc =fc)

    # --- initial motion Filter ---
    scp=modelFilters.StaticCalibrationProcedure(model)
    modMotion=modelFilters.ModelMotionFilter(scp,acqGait,model,enums.motionMethod.Sodervisk)
    modMotion.compute()

    progressionFlag = False
    if btkTools.isPointExist(acqGait, 'LHEE',ignorePhantom=False) or btkTools.isPointExist(acqGait, 'RHEE',ignorePhantom=False):

        pfp = progressionFrame.PointProgressionFrameProcedure(marker="LHEE") \
            if btkTools.isPointExist(acqGait, 'LHEE',ignorePhantom=False) \
            else  progressionFrame.PointProgressionFrameProcedure(marker="RHEE")


        pff = progressionFrame.ProgressionFrameFilter(acqGait,pfp)
        pff.compute()
        progressionAxis = pff.outputs["progressionAxis"]
        globalFrame = pff.outputs["globalFrame"]
        forwardProgression = pff.outputs["forwardProgression"]
        progressionFlag = True

    elif btkTools.isPointsExist(acqGait, ['LASI', 'RASI', 'RPSI', 'LPSI'],ignorePhantom=False) and not progressionFlag:
        LOGGER.logger.info("[pyCGM2] - progression axis detected from Pelvic markers ")
        pfp = progressionFrame.PelvisProgressionFrameProcedure()
        pff = progressionFrame.ProgressionFrameFilter(acqGait,pfp)
        pff.compute()
        globalFrame = pff.outputs["globalFrame"]
        forwardProgression = pff.outputs["forwardProgression"]

        progressionFlag = True
    elif btkTools.isPointsExist(acqGait, ['C7', 'T10', 'CLAV', 'STRN'],ignorePhantom=False) and not progressionFlag:
        LOGGER.logger.info("[pyCGM2] - progression axis detected from Thoracic markers ")
        pfp = progressionFrame.ThoraxProgressionFrameProcedure()
        pff = progressionFrame.ProgressionFrameFilter(acqGait,pfp)
        pff.compute()
        progressionAxis = pff.outputs["progressionAxis"]
        globalFrame = pff.outputs["globalFrame"]
        forwardProgression = pff.outputs["forwardProgression"]

    else:
        globalFrame = "XYZ"
        progressionAxis = "X"
        forwardProgression = True
        LOGGER.logger.error("[pyCGM2] - impossible to detect progression axis - neither pelvic nor thoracic markers are present. Progression set to +X by default ")


    for target in weights.keys():
        if target not in actual_trackingMarkers or target not in model.getStaticIkTargets():
            weights[target] = 0
            LOGGER.logger.warning("[pyCGM2] - the IK targeted marker [%s] is not labelled in the acquisition [%s]"%(target,reconstructFilenameLabelled))

    if ik_flag:
        #                        ---OPENSIM IK---

        # --- opensim calibration Filter ---
        osimfile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\osim\\lowerLimb_ballsJoints.osim"    # osimfile
        markersetFile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\settings\\cgm2_4\\cgm2_4-markerset.xml" # markerset
        cgmCalibrationprocedure = opensimFilters.CgmOpensimCalibrationProcedures(model) # procedure

        oscf = opensimFilters.opensimCalibrationFilter(osimfile,
                                                model,
                                                cgmCalibrationprocedure,
                                                DATA_PATH )
        oscf.addMarkerSet(markersetFile)
        scalingOsim = oscf.build()


        # --- opensim Fitting Filter ---
        iksetupFile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\settings\\cgm2_4\\cgm2_4-ikSetUp_template.xml" # ik tl file

        cgmFittingProcedure = opensimFilters.CgmOpensimFittingProcedure(model) # procedure
        cgmFittingProcedure.updateMarkerWeight("LASI",weights["LASI"])
        cgmFittingProcedure.updateMarkerWeight("RASI",weights["RASI"])
        cgmFittingProcedure.updateMarkerWeight("LPSI",weights["LPSI"])
        cgmFittingProcedure.updateMarkerWeight("RPSI",weights["RPSI"])
        cgmFittingProcedure.updateMarkerWeight("RTHI",weights["RTHI"])
        cgmFittingProcedure.updateMarkerWeight("RKNE",weights["RKNE"])
        cgmFittingProcedure.updateMarkerWeight("RTIB",weights["RTIB"])
        cgmFittingProcedure.updateMarkerWeight("RANK",weights["RANK"])
        cgmFittingProcedure.updateMarkerWeight("RHEE",weights["RHEE"])
        cgmFittingProcedure.updateMarkerWeight("RTOE",weights["RTOE"])

        cgmFittingProcedure.updateMarkerWeight("LTHI",weights["LTHI"])
        cgmFittingProcedure.updateMarkerWeight("LKNE",weights["LKNE"])
        cgmFittingProcedure.updateMarkerWeight("LTIB",weights["LTIB"])
        cgmFittingProcedure.updateMarkerWeight("LANK",weights["LANK"])
        cgmFittingProcedure.updateMarkerWeight("LHEE",weights["LHEE"])
        cgmFittingProcedure.updateMarkerWeight("LTOE",weights["LTOE"])


        cgmFittingProcedure.updateMarkerWeight("LTHAP",weights["LTHAP"])
        cgmFittingProcedure.updateMarkerWeight("LTHAD",weights["LTHAD"])
        cgmFittingProcedure.updateMarkerWeight("LTIAP",weights["LTIAP"])
        cgmFittingProcedure.updateMarkerWeight("LTIAD",weights["LTIAD"])
        cgmFittingProcedure.updateMarkerWeight("RTHAP",weights["RTHAP"])
        cgmFittingProcedure.updateMarkerWeight("RTHAD",weights["RTHAD"])
        cgmFittingProcedure.updateMarkerWeight("RTIAP",weights["RTIAP"])
        cgmFittingProcedure.updateMarkerWeight("RTIAD",weights["RTIAD"])

        cgmFittingProcedure.updateMarkerWeight("LSMH",weights["LSMH"])
        cgmFittingProcedure.updateMarkerWeight("LFMH",weights["LFMH"])
        cgmFittingProcedure.updateMarkerWeight("LVMH",weights["LVMH"])

        cgmFittingProcedure.updateMarkerWeight("RSMH",weights["RSMH"])
        cgmFittingProcedure.updateMarkerWeight("RFMH",weights["RFMH"])
        cgmFittingProcedure.updateMarkerWeight("RVMH",weights["RVMH"])


#       cgmFittingProcedure.updateMarkerWeight("LTHL",weights["LTHL"])
#       cgmFittingProcedure.updateMarkerWeight("LTHLD",weights["LTHLD"])
#       cgmFittingProcedure.updateMarkerWeight("LPAT",weights["LPAT"])
#       cgmFittingProcedure.updateMarkerWeight("LTIBL",weights["LTIBL"])
#       cgmFittingProcedure.updateMarkerWeight("RTHL",weights["RTHL"])
#       cgmFittingProcedure.updateMarkerWeight("RTHLD",weights["RTHLD"])
#       cgmFittingProcedure.updateMarkerWeight("RPAT",weights["RPAT"])
#       cgmFittingProcedure.updateMarkerWeight("RTIBL",weights["RTIBL"])


        osrf = opensimFilters.opensimFittingFilter(iksetupFile,
                                                          scalingOsim,
                                                          cgmFittingProcedure,
                                                          DATA_PATH,
                                                          acqGait )
        osrf.setTimeRange(acqGait,beginFrame = vff, lastFrame=vlf)
        if "ikAccuracy" in kwargs.keys():
            osrf.setAccuracy(kwargs["ikAccuracy"])

        LOGGER.logger.info("-------INVERSE KINEMATICS IN PROGRESS----------")
        try:
            acqIK = osrf.run(DATA_PATH + reconstructFilenameLabelled,
                            progressionAxis = progressionAxis ,
                            forwardProgression = forwardProgression)
            LOGGER.logger.info("[pyCGM2] - IK solver complete")
        except:
            LOGGER.logger.error("[pyCGM2] - IK solver fails")
            acqIK = acqGait
            detectAnomaly = True
        LOGGER.logger.info("---------------------------------------------------")

    # eventual gait acquisition to consider for joint kinematics
    finalAcqGait = acqIK if ik_flag else acqGait

    # --- final pyCGM2 model motion Filter ---
    # use fitted markers
    modMotionFitted=modelFilters.ModelMotionFilter(scp,finalAcqGait,model,enums.motionMethod.Sodervisk ,
                                              markerDiameter=markerDiameter,
                                              forceFoot6DoF=forceFoot6DoF_flag)

    modMotionFitted.compute()

    if "displayCoordinateSystem" in kwargs.keys() and kwargs["displayCoordinateSystem"]:
        csp = modelFilters.ModelCoordinateSystemProcedure(model)
        csdf = modelFilters.CoordinateSystemDisplayFilter(csp,model,finalAcqGait)
        csdf.setStatic(False)
        csdf.display()

    #---- Joint kinematics----
    # relative angles
    modelFilters.ModelJCSFilter(model,finalAcqGait).compute(description="vectoriel", pointLabelSuffix=pointSuffix)

    modelFilters.ModelAbsoluteAnglesFilter(model,finalAcqGait,
                                           segmentLabels=["Left Foot","Right Foot","Pelvis","Thorax","Head"],
                                            angleLabels=["LFootProgress", "RFootProgress","Pelvis","Thorax", "Head"],
                                            eulerSequences=["TOR","TOR", "ROT","YXZ","TOR"],
                                            globalFrameOrientation = globalFrame,
                                            forwardProgression = forwardProgression).compute(pointLabelSuffix=pointSuffix)
    #---- Body segment parameters----
    bspModel = bodySegmentParameters.Bsp(model)
    bspModel.compute()

    modelFilters.CentreOfMassFilter(model,finalAcqGait).compute(pointLabelSuffix=pointSuffix)

    # Inverse dynamics
    if btkTools.checkForcePlateExist(acqGait):
        # --- force plate handling----
        # find foot  in contact
        mappedForcePlate = forceplates.matchingFootSideOnForceplate(finalAcqGait,mfpa=mfpa)
        forceplates.addForcePlateGeneralEvents(finalAcqGait,mappedForcePlate)
        LOGGER.logger.warning("Manual Force plate assignment : %s" %mappedForcePlate)

        # assembly foot and force plate
        modelFilters.ForcePlateAssemblyFilter(model,finalAcqGait,mappedForcePlate,
                                 leftSegmentLabel="Left Foot",
                                 rightSegmentLabel="Right Foot").compute(pointLabelSuffix=pointSuffix)

        #---- Joint kinetics----
        idp = modelFilters.CGMLowerlimbInverseDynamicProcedure()
        modelFilters.InverseDynamicFilter(model,
                             finalAcqGait,
                             procedure = idp,
                             projection = momentProjection,
                             globalFrameOrientation = globalFrame,
                             forwardProgression = forwardProgression
                             ).compute(pointLabelSuffix=pointSuffix)


        #---- Joint energetics----
        modelFilters.JointPowerFilter(model,finalAcqGait).compute(pointLabelSuffix=pointSuffix)

    #---- zero unvalid frames ---
    btkTools.cleanAcq(finalAcqGait)
    btkTools.applyOnValidFrames(finalAcqGait,flag)

    if detectAnomaly and not anomalyException:
        LOGGER.logger.error("Anomalies has been detected - Check Warning messages of the log file")

    return finalAcqGait,detectAnomaly
Example #7
0
    def CGM1_fullbody(cls):

        MAIN_PATH = pyCGM2.TEST_DATA_PATH + "CGM1\\CGM1-TESTS\\Full PIG - StephenL5_C7\\"
        staticFilename = "PN01NORMSTAT.c3d"

        # CALIBRATION ###############################
        acqStatic = btkTools.smartReader(str(MAIN_PATH + staticFilename))

        markerDiameter = 14

        # Lower Limb
        mp = {
            'Bodymass': 83,
            'LeftLegLength': 874,
            'RightLegLength': 876.0,
            'LeftKneeWidth': 106.0,
            'RightKneeWidth': 103.0,
            'LeftAnkleWidth': 74.0,
            'RightAnkleWidth': 72.0,
            'LeftSoleDelta': 0,
            'RightSoleDelta': 0,
            'LeftShoulderOffset': 50,
            'LeftElbowWidth': 91,
            'LeftWristWidth': 56,
            'LeftHandThickness': 28,
            'RightShoulderOffset': 45,
            'RightElbowWidth': 90,
            'RightWristWidth': 55,
            'RightHandThickness': 30
        }

        model = cgm.CGM1()
        model.configure(bodyPart=enums.BodyPart.FullBody)
        model.addAnthropoInputParameters(mp)

        scp = modelFilters.StaticCalibrationProcedure(
            model)  # load calibration procedure
        csp = modelFilters.ModelCoordinateSystemProcedure(model)

        modelFilters.ModelCalibrationFilter(
            scp,
            acqStatic,
            model,
            leftFlatFoot=False,
            rightFlatFoot=False,
            markerDiameter=14,
            viconCGM1compatible=True,
        ).compute()
        #headHorizontal=True

        # --- motion ----
        gaitFilename = "PN01NORMSS01_stephen.c3d"
        acqGait = btkTools.smartReader(str(MAIN_PATH + gaitFilename))

        modMotion = modelFilters.ModelMotionFilter(
            scp, acqGait, model, enums.motionMethod.Determinist)
        modMotion.compute()

        csdf = modelFilters.CoordinateSystemDisplayFilter(csp, model, acqGait)
        csdf.setStatic(False)
        csdf.display()

        # angles
        modelFilters.ModelJCSFilter(model, acqGait).compute(
            description="vectoriel", pointLabelSuffix="cgm1_6dof")

        longitudinalAxis, forwardProgression, globalFrame = btkTools.findProgressionAxisFromLongAxis(
            acqGait, "C7", "CLAV")
        modelFilters.ModelAbsoluteAnglesFilter(
            model,
            acqGait,
            segmentLabels=["Thorax"],
            angleLabels=[
                "Thorax",
            ],
            eulerSequences=["YXZ"],
            globalFrameOrientation=globalFrame,
            forwardProgression=forwardProgression).compute(
                pointLabelSuffix="cgm1_6dof")

        # testing
        np.testing.assert_equal(longitudinalAxis, "X")
        np.testing.assert_equal(forwardProgression, False)
        np.testing.assert_equal(globalFrame, "XYZ")

        #plot("LNeckAngles",acqGait,"cgm1_6dof")

        # relative angles
        np.testing.assert_almost_equal(
            acqGait.GetPoint("RSpineAngles").GetValues(),
            acqGait.GetPoint("RSpineAngles_cgm1_6dof").GetValues(),
            decimal=2)
        np.testing.assert_almost_equal(
            acqGait.GetPoint("LSpineAngles").GetValues(),
            acqGait.GetPoint("LSpineAngles_cgm1_6dof").GetValues(),
            decimal=2)

        np.testing.assert_almost_equal(
            acqGait.GetPoint("LShoulderAngles").GetValues(),
            acqGait.GetPoint("LShoulderAngles_cgm1_6dof").GetValues(),
            decimal=3)
        np.testing.assert_almost_equal(
            acqGait.GetPoint("RShoulderAngles").GetValues(),
            acqGait.GetPoint("RShoulderAngles_cgm1_6dof").GetValues(),
            decimal=3)

        np.testing.assert_almost_equal(
            acqGait.GetPoint("RElbowAngles").GetValues(),
            acqGait.GetPoint("RElbowAngles_cgm1_6dof").GetValues(),
            decimal=3)
        np.testing.assert_almost_equal(
            acqGait.GetPoint("LElbowAngles").GetValues(),
            acqGait.GetPoint("LElbowAngles_cgm1_6dof").GetValues(),
            decimal=3)

        # np.testing.assert_almost_equal( acqGait.GetPoint("RWristAngles").GetValues(),
        #                             acqGait.GetPoint("RWristAngles_cgm1_6dof").GetValues(), decimal =3) # fail on transverse
        # np.testing.assert_almost_equal( acqGait.GetPoint("LWristAngles").GetValues(),
        #                             acqGait.GetPoint("LWristAngles_cgm1_6dof").GetValues(), decimal =3)# fail on transverse
        #
        # np.testing.assert_almost_equal( acqGait.GetPoint("RNeckAngles").GetValues(),
        #                             acqGait.GetPoint("RNeckAngles_cgm1_6dof").GetValues(), decimal =1) # fail on coronal
        # np.testing.assert_almost_equal( acqGait.GetPoint("LNeckAngles").GetValues(),
        #                             acqGait.GetPoint("LNeckAngles_cgm1_6dof").GetValues(), decimal =1) # fail on coronal

        # absolute angles
        np.testing.assert_almost_equal(
            acqGait.GetPoint("LThoraxAngles").GetValues(),
            acqGait.GetPoint("LThoraxAngles_cgm1_6dof").GetValues(),
            decimal=3)
        np.testing.assert_almost_equal(
            acqGait.GetPoint("RThoraxAngles").GetValues(),
            acqGait.GetPoint("RThoraxAngles_cgm1_6dof").GetValues(),
            decimal=3)

        btkTools.smartWriter(acqStatic, "FullBody_Angles_CGM1_fullbody.c3d")
Example #8
0
    def basicCGM1_distal(cls):

        MAIN_PATH = pyCGM2.TEST_DATA_PATH + "CGM1\\\\basic-filtered\\"
        staticFilename = "MRI-US-01, 2008-08-08, 3DGA 02.c3d"

        acqStatic = btkTools.smartReader(str(MAIN_PATH + staticFilename))

        model = cgm.CGM1
        model.configure()

        markerDiameter = 14
        mp = {
            'Bodymass': 71.0,
            'LeftLegLength': 860.0,
            'RightLegLength': 865.0,
            'LeftKneeWidth': 102.0,
            'RightKneeWidth': 103.4,
            'LeftAnkleWidth': 75.3,
            'RightAnkleWidth': 72.9,
            'LeftSoleDelta': 0,
            'RightSoleDelta': 0,
        }
        model.addAnthropoInputParameters(mp)

        scp = modelFilters.StaticCalibrationProcedure(model)
        modelFilters.ModelCalibrationFilter(scp, acqStatic, model).compute()

        for gaitFilename in [
                "MRI-US-01, 2008-08-08, 3DGA 14.distal.c3d",
                "MRI-US-01, 2008-08-08, 3DGA 13.distal.c3d"
        ]:

            acqGait = btkTools.smartReader(str(MAIN_PATH + gaitFilename))

            # Motion FILTER
            # optimisation segmentaire et calibration fonctionnel
            modMotion = modelFilters.ModelMotionFilter(
                scp, acqGait, model, pyCGM2Enums.motionMethod.Determinist)
            modMotion.compute()

            # Joint kinematics
            modelFilters.ModelJCSFilter(model, acqGait).compute(
                description="vectoriel", pointLabelSuffix="cgm1_6dof")

            # BSP model
            bspModel = bodySegmentParameters.Bsp(model)
            bspModel.compute()

            # force plate -- construction du wrench attribue au pied
            forceplates.appendForcePlateCornerAsMarker(acqGait)
            mappedForcePlate = forceplates.matchingFootSideOnForceplate(
                acqGait)
            modelFilters.ForcePlateAssemblyFilter(
                model,
                acqGait,
                mappedForcePlate,
                leftSegmentLabel="Left Foot",
                rightSegmentLabel="Right Foot").compute()

            idp = modelFilters.CGMLowerlimbInverseDynamicProcedure()
            modelFilters.InverseDynamicFilter(
                model,
                acqGait,
                procedure=idp,
                projection=pyCGM2Enums.MomentProjection.Distal).compute(
                    pointLabelSuffix="cgm1_6dof")

            modelFilters.JointPowerFilter(
                model, acqGait).compute(pointLabelSuffix="cgm1_6dof")

            btkTools.smartWriter(acqGait,
                                 str(gaitFilename[:-4] + "_testInvDyn.c3d"))

            # TEST ------
            compareKinetics(acqGait, 5, -5, 0.2, 50.0, 0.2)
Example #9
0
        'LeftAnkleWidth': 75.3,
        'RightAnkleWidth': 72.9,
        'LeftSoleDelta': 0,
        'RightSoleDelta': 0,
    }

    # --- Calibration ---
    acqStatic = btkTools.smartReader(str(MAIN_PATH + staticFilename))

    model = cgm2.CGM2_2()
    model.configure()

    model.addAnthropoInputParameters(mp)

    # ------ calibration -------
    scp = modelFilters.StaticCalibrationProcedure(model)
    modelFilters.ModelCalibrationFilter(scp, acqStatic, model).compute()

    # cgm decorator
    modelDecorator.HipJointCenterDecorator(model).hara()
    modelDecorator.KneeCalibrationDecorator(model).midCondyles(
        acqStatic, markerDiameter=markerDiameter, side="both")
    modelDecorator.AnkleCalibrationDecorator(model).midMaleolus(
        acqStatic, markerDiameter=markerDiameter, side="both")

    # final
    modelFilters.ModelCalibrationFilter(
        scp, acqStatic, model, markerDiameter=markerDiameter).compute()

    # ------ Fitting -------
    acqGait = btkTools.smartReader(str(MAIN_PATH + gaitFilename))
Example #10
0
    def CGM1_fullbody(cls):

        MAIN_PATH = pyCGM2.TEST_DATA_PATH + "CGM1\\CGM1-TESTS\\Full PIG - StephenL5_C7\\"
        staticFilename = "PN01NORMSTAT.c3d"

        # CALIBRATION ###############################
        acqStatic = btkTools.smartReader(str(MAIN_PATH + staticFilename))

        markerDiameter = 14

        # Lower Limb
        mp = {
            'Bodymass': 83,
            'LeftLegLength': 874,
            'RightLegLength': 876.0,
            'LeftKneeWidth': 106.0,
            'RightKneeWidth': 103.0,
            'LeftAnkleWidth': 74.0,
            'RightAnkleWidth': 72.0,
            'LeftSoleDelta': 0,
            'RightSoleDelta': 0,
            'LeftShoulderOffset': 50,
            'LeftElbowWidth': 91,
            'LeftWristWidth': 56,
            'LeftHandThickness': 28,
            'RightShoulderOffset': 45,
            'RightElbowWidth': 90,
            'RightWristWidth': 55,
            'RightHandThickness': 30
        }

        model = cgm.CGM1()
        model.configure(bodyPart=enums.BodyPart.FullBody)
        model.addAnthropoInputParameters(mp)

        scp = modelFilters.StaticCalibrationProcedure(
            model)  # load calibration procedure
        csp = modelFilters.ModelCoordinateSystemProcedure(model)

        modelFilters.ModelCalibrationFilter(
            scp,
            acqStatic,
            model,
            leftFlatFoot=False,
            rightFlatFoot=False,
            markerDiameter=14,
            viconCGM1compatible=True,
        ).compute()
        #headHorizontal=True

        # --- motion ----
        gaitFilename = "PN01NORMSS01_stephen.c3d"
        acqGait = btkTools.smartReader(str(MAIN_PATH + gaitFilename))

        modMotion = modelFilters.ModelMotionFilter(
            scp, acqGait, model, enums.motionMethod.Determinist)
        modMotion.compute()

        csdf = modelFilters.CoordinateSystemDisplayFilter(csp, model, acqGait)
        csdf.setStatic(False)
        csdf.display()

        # TESTING
        #   thorax
        R_thorax = model.getSegment(
            "Thorax").anatomicalFrame.motion[10].getRotation()
        R_thorax_vicon = getViconRmatrix(10, acqGait, "TRXO", "TRXA", "TRXL",
                                         "XZY")
        np.testing.assert_almost_equal(R_thorax, R_thorax_vicon, decimal=3)

        #   head
        R_head = model.getSegment(
            "Head").anatomicalFrame.motion[10].getRotation()
        R_head_vicon = getViconRmatrix(10, acqGait, "HEDO", "HEDA", "HEDL",
                                       "XZY")

        np.testing.assert_almost_equal(R_head, R_head_vicon, decimal=2)

        btkTools.smartWriter(acqStatic, "FullBody_motion_CGM1_fullbody.c3d")
Example #11
0
    def basicCGM1(cls):
        MAIN_PATH = pyCGM2.TEST_DATA_PATH + "CGM1\\CGM1-TESTS\\basic_static_StaticVsDynamicAngles\\"

        staticFilename = "MRI-US-01, 2008-08-08, 3DGA 02.c3d"

        acqStatic = btkTools.smartReader(str(MAIN_PATH + staticFilename))

        model = cgm.CGM1
        model.configure()
        markerDiameter = 14
        mp = {
            'Bodymass': 71.0,
            'LeftLegLength': 860.0,
            'RightLegLength': 865.0,
            'LeftKneeWidth': 102.0,
            'RightKneeWidth': 103.4,
            'LeftAnkleWidth': 75.3,
            'RightAnkleWidth': 72.9,
            'LeftSoleDelta': 0,
            'RightSoleDelta': 0,
        }
        model.addAnthropoInputParameters(mp)

        # -----------CGM STATIC CALIBRATION--------------------
        scp = modelFilters.StaticCalibrationProcedure(model)
        modelFilters.ModelCalibrationFilter(scp, acqStatic, model).compute()

        spf_l, sro_l = model.getViconFootOffset("Left")
        spf_r, sro_r = model.getViconFootOffset("Right")

        # TESTS ------------------------------------------------

        np.testing.assert_equal(model.m_useRightTibialTorsion, False)
        np.testing.assert_equal(model.m_useLeftTibialTorsion, False)

        # joint centres
        np.testing.assert_almost_equal(
            acqStatic.GetPoint("LFEP").GetValues().mean(axis=0),
            acqStatic.GetPoint("LHJC").GetValues().mean(axis=0),
            decimal=3)
        np.testing.assert_almost_equal(
            acqStatic.GetPoint("RFEP").GetValues().mean(axis=0),
            acqStatic.GetPoint("RHJC").GetValues().mean(axis=0),
            decimal=3)

        np.testing.assert_almost_equal(
            acqStatic.GetPoint("LFEO").GetValues().mean(axis=0),
            acqStatic.GetPoint("LKJC").GetValues().mean(axis=0),
            decimal=3)
        np.testing.assert_almost_equal(
            acqStatic.GetPoint("RFEO").GetValues().mean(axis=0),
            acqStatic.GetPoint("RKJC").GetValues().mean(axis=0),
            decimal=3)

        np.testing.assert_almost_equal(
            acqStatic.GetPoint("LTIO").GetValues().mean(axis=0),
            acqStatic.GetPoint("LAJC").GetValues().mean(axis=0),
            decimal=3)
        np.testing.assert_almost_equal(
            acqStatic.GetPoint("RTIO").GetValues().mean(axis=0),
            acqStatic.GetPoint("RAJC").GetValues().mean(axis=0),
            decimal=3)

        # foot offsets
        vicon_spf_l = np.rad2deg(
            acqStatic.GetMetaData().FindChild("PROCESSING").value().FindChild(
                "LStaticPlantFlex").value().GetInfo().ToDouble()[0])
        vicon_spf_r = np.rad2deg(
            acqStatic.GetMetaData().FindChild("PROCESSING").value().FindChild(
                "RStaticPlantFlex").value().GetInfo().ToDouble()[0])
        vicon_sro_l = np.rad2deg(
            acqStatic.GetMetaData().FindChild("PROCESSING").value().FindChild(
                "LStaticRotOff").value().GetInfo().ToDouble()[0])
        vicon_sro_r = np.rad2deg(
            acqStatic.GetMetaData().FindChild("PROCESSING").value().FindChild(
                "RStaticRotOff").value().GetInfo().ToDouble()[0])

        logging.info(" LStaticPlantFlex : Vicon (%.6f)  Vs pyCGM2 (%.6f)" %
                     (spf_l, vicon_spf_l))
        logging.info(" RStaticPlantFlex : Vicon (%.6f)  Vs pyCGM2 (%.6f)" %
                     (spf_r, vicon_spf_r))
        logging.info(" LStaticRotOff : Vicon (%.6f)  Vs pyCGM2 (%.6f)" %
                     (sro_l, vicon_sro_l))
        logging.info(" RStaticRotOff : Vicon (%.6f)  Vs pyCGM2 (%.6f)" %
                     (sro_r, vicon_sro_r))

        np.testing.assert_almost_equal(spf_l, vicon_spf_l, decimal=3)
        np.testing.assert_almost_equal(spf_r, vicon_spf_r, decimal=3)
        np.testing.assert_almost_equal(sro_l, vicon_sro_l, decimal=3)
        np.testing.assert_almost_equal(sro_r, vicon_sro_r, decimal=3)

        # -------- CGM FITTING -------------------------------------------------

        # ---- on c3d processed vicon static-pig operation
        # Motion FILTER
        # optimisation segmentaire et calibration fonctionnel
        modMotion = modelFilters.ModelMotionFilter(
            scp,
            acqStatic,
            model,
            pyCGM2Enums.motionMethod.Determinist,
            markerDiameter=markerDiameter,
            pigStatic=True,
            viconCGM1compatible=False)
        modMotion.compute()

        # relative angles
        modelFilters.ModelJCSFilter(model, acqStatic).compute(
            description="vectoriel", pointLabelSuffix="cgm1_6dof")

        btkTools.smartWriter(acqStatic, "test_basicCGM1_staticAngles.c3d")

        # ---- on c3d processed vicon dynamic-pig operation

        gaitFilename = "MRI-US-01, 2008-08-08, 3DGA 02-dynamics.c3d"  #"staticComparisonPipelines.c3d"
        acqGait = btkTools.smartReader(str(MAIN_PATH + gaitFilename))

        #        # output and plot
        #btkTools.smartWriter(acqGait, "test_basicCGM1_staticAngles.c3d")
        plotComparison(acqGait, acqStatic, "LHipAngles")
        plotComparison(acqGait, acqStatic, "LKneeAngles")
        plotComparison(acqGait, acqStatic, "LAnkleAngles")

        plt.figure()
        plt.plot(
            acqStatic.GetPoint("LAnkleAngles").GetValues()[:, 0] -
            acqStatic.GetPoint("LAnkleAngles" + "_cgm1_6dof").GetValues()[:,
                                                                          0])
        plt.figure()
        plt.plot(
            acqStatic.GetPoint("LAnkleAngles").GetValues()[:, 2] -
            acqStatic.GetPoint("LAnkleAngles" + "_cgm1_6dof").GetValues()[:,
                                                                          2])
Example #12
0
    def kinematicFitting_oneFile_cgmProcedure(cls):

        DATA_PATH = pyCGM2.TEST_DATA_PATH + "CGM2\\LowerLimb\\subject10_S1A1_julieDataSet_noModelOutputs\\"

        config = dict()
        config["static"] = "StaticR010S1A1.c3d"
        config["dynamicTrial"] = [
            "R010S1A1Gait001.c3d", "R010S1A1Gait003.c3d",
            "R010S1A1Gait004.c3d", "R010S1A1Gait005.c3d",
            "R010S1A1Gait007.c3d", "R010S1A1Gait010.c3d"
        ]

        configMP = {
            "Bodymass": 64.0,
            "LeftLegLength": 865.0,
            "RightLegLength": 855.0,
            "LeftKneeWidth": 100.0,
            "RightKneeWidth": 101.0,
            "LeftAnkleWidth": 69.0,
            "RightAnkleWidth": 69.0
        }

        requiredMarkers = [
            "LASI", "RASI", "LPSI", "RPSI", "RTHIAP", "RTHIAD", "RTHI", "RKNE",
            "RSHN", "RTIAP", "RTIB", "RANK", "RHEE", "RTOE", "RCUN", "RD1M",
            "RD5M"
        ]

        acqStatic = btkTools.smartReader(DATA_PATH + config["static"])

        # model
        model = cgm2Julie.CGM2ModelInf()
        model.configure()
        markerDiameter = 14

        mp = {
            'Bodymass': configMP["Bodymass"],
            'LeftLegLength': configMP["LeftLegLength"],
            'RightLegLength': configMP["RightLegLength"],
            'LeftKneeWidth': configMP["LeftKneeWidth"],
            'RightKneeWidth': configMP["RightKneeWidth"],
            'LeftAnkleWidth': configMP["LeftAnkleWidth"],
            'RightAnkleWidth': configMP["RightAnkleWidth"],
        }

        #offset 2ndToe Joint
        toe = acqStatic.GetPoint("RTOE").GetValues()[:, :].mean(axis=0)
        mp["rightToeOffset"] = (toe[2] - markerDiameter / 2.0) / 2.0

        model.addAnthropoInputParameters(mp)

        # -----------CGM STATIC CALIBRATION--------------------

        #  --- Initial calibration
        scp = modelFilters.StaticCalibrationProcedure(model)
        modelFilters.ModelCalibrationFilter(
            scp, acqStatic, model,
            rightFlatHindFoot=True).compute()  # Initial calibration

        # --- decorator
        modelDecorator.KneeCalibrationDecorator(model).midCondyles(
            acqStatic, leftMedialKneeLabel="LKNM", rightMedialKneeLabel="RKNM")
        modelDecorator.AnkleCalibrationDecorator(model).midMaleolus(
            acqStatic,
            leftMedialAnkleLabel="LMMA",
            rightMedialAnkleLabel="RMMA")

        # --- Updated calibration
        modelFilters.ModelCalibrationFilter(scp,
                                            acqStatic,
                                            model,
                                            useLeftKJCnode="LKJC_mid",
                                            useRightKJCnode="RKJC_mid",
                                            useLeftAJCnode="LAJC_mid",
                                            useRightAJCnode="RAJC_mid",
                                            rightFlatHindFoot=True).compute()

        # ---- optional -update static c3d
        #btkTools.smartWriter(acqStatic, "StaticCalibrated.c3d")

        # -----------CGM MOTION  6dof--------------------

        # --- reader and checking
        acqGait = btkTools.smartReader(DATA_PATH + config["dynamicTrial"][0])
        btkTools.checkMarkers(acqGait, requiredMarkers)
        btkTools.isGap(acqGait, requiredMarkers)
        btkTools.checkFirstAndLastFrame(acqGait, "LASI")
        logging.info("dyn Acquisition ---> OK ")

        # --- filters
        modMotion = modelFilters.ModelMotionFilter(
            scp, acqGait, model, pyCGM2Enums.motionMethod.Determinist)
        modMotion.compute()

        modelFilters.ModelJCSFilter(model,
                                    acqGait).compute(description="vectoriel",
                                                     pointLabelSuffix="2_6dof")

        # --- writer
        #btkTools.smartWriter(acqGait, "motionCalibrated.c3d")

        # ------- OPENSIM IK --------------------------------------
        cgmprocedure = opensimFilters.CgmOpensimCalibrationProcedures(model)
        markersetFile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\draft-opensimPreProcessing\\cgm2-markerset.xml"

        osimfile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\draft-opensimPreProcessing\\cgm2-model.osim"

        oscf = opensimFilters.opensimCalibrationFilter(osimfile, model,
                                                       cgmprocedure)
        oscf.addMarkerSet(markersetFile)
        fittingOsim = oscf.build()

        filename = config["dynamicTrial"][0]
        cgmFittingProcedure = opensimFilters.CgmOpensimFittingProcedure(model)

        cgmFittingProcedure.updateMarkerWeight("LASI", 100)

        iksetupFile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\draft-opensimPreProcessing\\ikSetUp_template.xml"

        osrf = opensimFilters.opensimFittingFilter(iksetupFile, fittingOsim,
                                                   cgmFittingProcedure,
                                                   DATA_PATH)
        acqIK = osrf.run(acqGait, str(DATA_PATH + filename))

        # -------- NEW MOTION FILTER ON IK MARKERS ------------------

        modMotion_ik = modelFilters.ModelMotionFilter(
            scp, acqIK, model, pyCGM2Enums.motionMethod.Sodervisk)
        modMotion_ik.compute()

        finalJcs = modelFilters.ModelJCSFilter(model, acqIK)
        finalJcs.setFilterBool(False)
        finalJcs.compute(description="ik", pointLabelSuffix="2_ik")  #

        # recup du mot file
        motFilename = str(DATA_PATH + config["dynamicTrial"][0][:-4] + ".mot")

        comparisonOpensimVsCGM(motFilename, acqIK, "2_ik")
Example #13
0
    def CGM1_UpperLimb(cls):

        MAIN_PATH = pyCGM2.TEST_DATA_PATH + "CGM1\\CGM1-TESTS\\full-PiG\\"
        staticFilename = "PN01NORMSTAT.c3d"

        acqStatic = btkTools.smartReader(str(MAIN_PATH + staticFilename))

        model = cgm.CGM1
        model.configure(bodyPart=enums.BodyPart.UpperLimb)

        markerDiameter = 14
        mp = {
            'LeftShoulderOffset': 50,
            'LeftElbowWidth': 91,
            'LeftWristWidth': 56,
            'LeftHandThickness': 28,
            'RightShoulderOffset': 45,
            'RightElbowWidth': 90,
            'RightWristWidth': 55,
            'RightHandThickness': 30
        }
        model.addAnthropoInputParameters(mp)

        # -----------CGM STATIC CALIBRATION--------------------
        scp = modelFilters.StaticCalibrationProcedure(model)
        modelFilters.ModelCalibrationFilter(scp, acqStatic, model).compute()

        csp = modelFilters.ModelCoordinateSystemProcedure(model)
        csdf = modelFilters.CoordinateSystemDisplayFilter(
            csp, model, acqStatic)
        csdf.setStatic(True)
        csdf.display()

        btkTools.smartWriter(acqStatic, "upperLimb_calib.c3d")

        # joint centres
        np.testing.assert_almost_equal(
            acqStatic.GetPoint("TRXO").GetValues().mean(axis=0),
            acqStatic.GetPoint("OT").GetValues().mean(axis=0),
            decimal=3)

        np.testing.assert_almost_equal(
            acqStatic.GetPoint("LCLO").GetValues().mean(axis=0),
            acqStatic.GetPoint("LSJC").GetValues().mean(axis=0),
            decimal=3)
        np.testing.assert_almost_equal(
            acqStatic.GetPoint("LHUO").GetValues().mean(axis=0),
            acqStatic.GetPoint("LEJC").GetValues().mean(axis=0),
            decimal=3)
        np.testing.assert_almost_equal(
            acqStatic.GetPoint("LCLO").GetValues().mean(axis=0),
            acqStatic.GetPoint("LSJC").GetValues().mean(axis=0),
            decimal=3)

        np.testing.assert_almost_equal(
            acqStatic.GetPoint("RCLO").GetValues().mean(axis=0),
            acqStatic.GetPoint("RSJC").GetValues().mean(axis=0),
            decimal=3)
        np.testing.assert_almost_equal(
            acqStatic.GetPoint("RHUO").GetValues().mean(axis=0),
            acqStatic.GetPoint("REJC").GetValues().mean(axis=0),
            decimal=3)
        np.testing.assert_almost_equal(
            acqStatic.GetPoint("RCLO").GetValues().mean(axis=0),
            acqStatic.GetPoint("RSJC").GetValues().mean(axis=0),
            decimal=3)
Example #14
0
def main():

    parser = argparse.ArgumentParser(description='2Dof Knee Calibration')
    parser.add_argument('-s','--side', type=str, help="Side : Left or Right")
    parser.add_argument('-b','--beginFrame', type=int, help="begin frame")
    parser.add_argument('-e','--endFrame', type=int, help="end frame")

    args = parser.parse_args()
    NEXUS = ViconNexus.ViconNexus()
    NEXUS_PYTHON_CONNECTED = NEXUS.Client.IsConnected()


    if NEXUS_PYTHON_CONNECTED: # run Operation

        DATA_PATH, reconstructedFilenameLabelledNoExt = NEXUS.GetTrialName()

        reconstructFilenameLabelled = reconstructedFilenameLabelledNoExt+".c3d"

        LOGGER.logger.info( "data Path: "+ DATA_PATH )
        LOGGER.logger.info( "reconstructed file: "+ reconstructFilenameLabelled)

        # --------------------------SUBJECT -----------------------------------
        # Notice : Work with ONE subject by session
        subjects = NEXUS.GetSubjectNames()
        subject = nexusTools.getActiveSubject(NEXUS)
        LOGGER.logger.info(  "Subject name : " + subject  )

        # --------------------pyCGM2 MODEL - INIT ------------------------------
        model = files.loadModel(DATA_PATH,subject)
        LOGGER.logger.info("loaded model : %s" %(model.version ))


        if model.version == "CGM1.0":
            if os.path.isfile(pyCGM2.PYCGM2_APPDATA_PATH + "CGM1-pyCGM2.settings"):
                settings = files.openFile(pyCGM2.PYCGM2_APPDATA_PATH,"CGM1-pyCGM2.settings")
            else:
                settings = files.openFile(pyCGM2.PYCGM2_SETTINGS_FOLDER,"CGM1-pyCGM2.settings")

        elif model.version == "CGM1.1":
            if os.path.isfile(pyCGM2.PYCGM2_APPDATA_PATH + "CGM1_1-pyCGM2.settings"):
                settings = files.openFile(pyCGM2.PYCGM2_APPDATA_PATH,"CGM1_1-pyCGM2.settings")
            else:
                settings = files.openFile(pyCGM2.PYCGM2_SETTINGS_FOLDER,"CGM1_1-pyCGM2.settings")

        elif model.version == "CGM2.1":
            if os.path.isfile(pyCGM2.PYCGM2_APPDATA_PATH + "CGM2_1-pyCGM2.settings"):
                settings = files.openFile(pyCGM2.PYCGM2_APPDATA_PATH,"CGM2_1-pyCGM2.settings")
            else:
                settings = files.openFile(pyCGM2.PYCGM2_SETTINGS_FOLDER,"CGM2_1-pyCGM2.settings")

        elif model.version == "CGM2.2":
            if os.path.isfile(pyCGM2.PYCGM2_APPDATA_PATH + "CGM2_2-pyCGM2.settings"):
                settings = files.openFile(pyCGM2.PYCGM2_APPDATA_PATH,"CGM2_2-pyCGM2.settings")
            else:
                settings = files.openFile(pyCGM2.PYCGM2_SETTINGS_FOLDER,"CGM2_2-pyCGM2.settings")
        elif model.version == "CGM2.3":
            if os.path.isfile(pyCGM2.PYCGM2_APPDATA_PATH + "CGM2_3-pyCGM2.settings"):
                settings = files.openFile(pyCGM2.PYCGM2_APPDATA_PATH,"CGM2_3-pyCGM2.settings")
            else:
                settings = files.openFile(pyCGM2.PYCGM2_SETTINGS_FOLDER,"CGM2_3-pyCGM2.settings")
        elif model.version in  ["CGM2.4"]:
            if os.path.isfile(pyCGM2.PYCGM2_APPDATA_PATH + "CGM2_4-pyCGM2.settings"):
                settings = files.openFile(pyCGM2.PYCGM2_APPDATA_PATH,"CGM2_4-pyCGM2.settings")
            else:
                settings = files.openFile(pyCGM2.PYCGM2_SETTINGS_FOLDER,"CGM2_4-pyCGM2.settings")

        elif model.version in  ["CGM2.5"]:
            if os.path.isfile(pyCGM2.PYCGM2_APPDATA_PATH + "CGM2_5-pyCGM2.settings"):
                settings = files.openFile(pyCGM2.PYCGM2_APPDATA_PATH,"CGM2_5-pyCGM2.settings")
            else:
                settings = files.openFile(pyCGM2.PYCGM2_SETTINGS_FOLDER,"CGM2_5-pyCGM2.settings")

        else:
            raise Exception ("model version not found [contact admin]")

        # --------------------------SESSION INFOS ------------------------------------
        mpInfo,mpFilename = files.getMpFileContent(DATA_PATH,"mp.pyCGM2",subject)

        #  translators management
        if model.version in  ["CGM1.0"]:
            translators = files.getTranslators(DATA_PATH,"CGM1.translators")
        elif model.version in  ["CGM1.1"]:
            translators = files.getTranslators(DATA_PATH,"CGM1_1.translators")
        elif model.version in  ["CGM2.1"]:
            translators = files.getTranslators(DATA_PATH,"CGM2_1.translators")
        elif model.version in  ["CGM2.2"]:
            translators = files.getTranslators(DATA_PATH,"CGM2_2.translators")
        elif model.version in  ["CGM2.3"]:
            translators = files.getTranslators(DATA_PATH,"CGM2_3.translators")
        elif model.version in  ["CGM2.4"]:
            translators = files.getTranslators(DATA_PATH,"CGM2_4.translators")
        elif model.version in  ["CGM2.5"]:
            translators = files.getTranslators(DATA_PATH,"CGM2_5.translators")

        if not translators:
           translators = settings["Translators"]

        # btkAcq builder
        nacf = nexusFilters.NexusConstructAcquisitionFilter(DATA_PATH,reconstructedFilenameLabelledNoExt,subject)
        acq = nacf.build()

        # --------------------------MODEL PROCESSING----------------------------
        model,acqFunc,side = kneeCalibration.calibration2Dof(model,
            DATA_PATH,reconstructFilenameLabelled,translators,
            args.side,args.beginFrame,args.endFrame,None,forceBtkAcq=acq)

        # ----------------------SAVE-------------------------------------------
        files.saveModel(model,DATA_PATH,subject)
        LOGGER.logger.warning("model updated with a  %s knee calibrated with 2Dof method" %(side))

        # save mp
        files.saveMp(mpInfo,model,DATA_PATH,mpFilename)

        # ----------------------VICON INTERFACE-------------------------------------------
        #--- update mp
        nexusUtils.updateNexusSubjectMp(NEXUS,model,subject)

        if side == "Left":
            nexusTools.appendBones(NEXUS,subject,acqFunc,"LFE0", model.getSegment("Left Thigh"),OriginValues = acqFunc.GetPoint("LKJC").GetValues() )
        elif side == "Right":
            nexusTools.appendBones(NEXUS,subject,acqFunc,"RFE0", model.getSegment("Right Thigh"),OriginValues = acqFunc.GetPoint("RKJC").GetValues() )

        # --------------------------NEW MOTION FILTER - DISPLAY BONES---------
        scp=modelFilters.StaticCalibrationProcedure(model)
        if model.version in  ["CGM1.0","CGM1.1","CGM2.1","CGM2.2"]:
            modMotion=modelFilters.ModelMotionFilter(scp,acqFunc,model,enums.motionMethod.Determinist)
            modMotion.compute()

        elif model.version in  ["CGM2.3","CGM2.4"]:

            proximalSegmentLabel=str(side+" Thigh")
            distalSegmentLabel=str(side+" Shank")
            # Motion
            modMotion=modelFilters.ModelMotionFilter(scp,acqFunc,model,enums.motionMethod.Sodervisk)
            modMotion.segmentalCompute([proximalSegmentLabel,distalSegmentLabel])


        # -- add nexus Bones
        if side == "Left":
            nexusTools.appendBones(NEXUS,subject,acqFunc,"LFE1", model.getSegment("Left Thigh"),OriginValues = acqFunc.GetPoint("LKJC").GetValues() )
            LOGGER.logger.warning("offset %s" %(str(model.mp_computed["LeftKneeFuncCalibrationOffset"] )))
        elif side == "Right":
            nexusTools.appendBones(NEXUS,subject,acqFunc,"RFE1", model.getSegment("Right Thigh"),OriginValues = acqFunc.GetPoint("RKJC").GetValues() )
            LOGGER.logger.warning("offset %s" %(str(model.mp_computed["RightKneeFuncCalibrationOffset"] )))

    else:
        raise Exception("NO Nexus connection. Turn on Nexus")
Example #15
0
    def CGM1_fullbody(cls):

        MAIN_PATH = pyCGM2.TEST_DATA_PATH + "CGM1\\CGM1-TESTS\\Full PIG - StephenL5_C7\\"
        staticFilename = "PN01NORMSTAT.c3d"

        # CALIBRATION ###############################
        acqStatic = btkTools.smartReader(str(MAIN_PATH + staticFilename))

        markerDiameter = 14

        # Lower Limb
        mp = {
            'Bodymass': 83,
            'LeftLegLength': 874,
            'RightLegLength': 876.0,
            'LeftKneeWidth': 106.0,
            'RightKneeWidth': 103.0,
            'LeftAnkleWidth': 74.0,
            'RightAnkleWidth': 72.0,
            'LeftSoleDelta': 0,
            'RightSoleDelta': 0,
            'LeftShoulderOffset': 50,
            'LeftElbowWidth': 91,
            'LeftWristWidth': 56,
            'LeftHandThickness': 28,
            'RightShoulderOffset': 45,
            'RightElbowWidth': 90,
            'RightWristWidth': 55,
            'RightHandThickness': 30
        }

        model = cgm.CGM1()
        model.configure(bodyPart=enums.BodyPart.FullBody)
        model.addAnthropoInputParameters(mp)

        scp = modelFilters.StaticCalibrationProcedure(
            model)  # load calibration procedure

        modelFilters.ModelCalibrationFilter(
            scp,
            acqStatic,
            model,
            leftFlatFoot=False,
            rightFlatFoot=False,
            markerDiameter=14,
            viconCGM1compatible=True,
        ).compute()
        #headHorizontal=True

        csp = modelFilters.ModelCoordinateSystemProcedure(model)
        csdf = modelFilters.CoordinateSystemDisplayFilter(
            csp, model, acqStatic)
        csdf.setStatic(True)
        csdf.display()

        # joint centres
        np.testing.assert_almost_equal(
            acqStatic.GetPoint("TRXO").GetValues().mean(axis=0),
            acqStatic.GetPoint("OT").GetValues().mean(axis=0),
            decimal=3)

        np.testing.assert_almost_equal(
            acqStatic.GetPoint("LCLO").GetValues().mean(axis=0),
            acqStatic.GetPoint("LSJC").GetValues().mean(axis=0),
            decimal=3)
        np.testing.assert_almost_equal(
            acqStatic.GetPoint("LHUO").GetValues().mean(axis=0),
            acqStatic.GetPoint("LEJC").GetValues().mean(axis=0),
            decimal=3)
        np.testing.assert_almost_equal(
            acqStatic.GetPoint("LCLO").GetValues().mean(axis=0),
            acqStatic.GetPoint("LSJC").GetValues().mean(axis=0),
            decimal=3)

        np.testing.assert_almost_equal(
            acqStatic.GetPoint("RCLO").GetValues().mean(axis=0),
            acqStatic.GetPoint("RSJC").GetValues().mean(axis=0),
            decimal=3)
        np.testing.assert_almost_equal(
            acqStatic.GetPoint("RHUO").GetValues().mean(axis=0),
            acqStatic.GetPoint("REJC").GetValues().mean(axis=0),
            decimal=3)
        np.testing.assert_almost_equal(
            acqStatic.GetPoint("RCLO").GetValues().mean(axis=0),
            acqStatic.GetPoint("RSJC").GetValues().mean(axis=0),
            decimal=3)

        btkTools.smartWriter(acqStatic, "FullBody_Static_CGM1_fullbody.c3d")
Example #16
0
    def basicCGM1_JCS_Dual(cls, plotFlag=False):

        MAIN_PATH = pyCGM2.TEST_DATA_PATH + "CGM1\\\\basic-filtered\\"
        staticFilename = "MRI-US-01, 2008-08-08, 3DGA 02.c3d"

        acqStatic = btkTools.smartReader(str(MAIN_PATH + staticFilename))

        model = cgm.CGM1
        model.configure()

        markerDiameter = 14
        mp = {
            'Bodymass': 71.0,
            'LeftLegLength': 860.0,
            'RightLegLength': 865.0,
            'LeftKneeWidth': 102.0,
            'RightKneeWidth': 103.4,
            'LeftAnkleWidth': 75.3,
            'RightAnkleWidth': 72.9,
        }
        model.addAnthropoInputParameters(mp)

        scp = modelFilters.StaticCalibrationProcedure(model)
        modelFilters.ModelCalibrationFilter(scp, acqStatic, model).compute()

        # ------ Test 1 Motion Axe X -------
        gaitFilename = "MRI-US-01, 2008-08-08, 3DGA 14.distal.c3d"
        acqGait = btkTools.smartReader(str(MAIN_PATH + gaitFilename))

        # Motion FILTER
        # optimisation segmentaire et calibration fonctionnel
        modMotion = modelFilters.ModelMotionFilter(
            scp,
            acqGait,
            model,
            pyCGM2Enums.motionMethod.Determinist,
            usePyCGM2_coordinateSystem=True)
        modMotion.compute()

        # Joint kinematics
        modelFilters.ModelJCSFilter(model, acqGait).compute(
            description="vectoriel", pointLabelSuffix="cgm1_6dof")

        # BSP model
        bspModel = bodySegmentParameters.Bsp(model)
        bspModel.compute()

        # force plate -- construction du wrench attribue au pied
        forceplates.appendForcePlateCornerAsMarker(acqGait)
        mappedForcePlate = forceplates.matchingFootSideOnForceplate(acqGait)
        modelFilters.ForcePlateAssemblyFilter(
            model,
            acqGait,
            "RL",
            leftSegmentLabel="Left Foot",
            rightSegmentLabel="Right Foot").compute()

        idp = modelFilters.CGMLowerlimbInverseDynamicProcedure()
        modelFilters.InverseDynamicFilter(
            model,
            acqGait,
            procedure=idp,
            projection=pyCGM2Enums.MomentProjection.JCS_Dual,
            viconCGM1compatible=True).compute(pointLabelSuffix="cgm1_6dof")

        modelFilters.JointPowerFilter(
            model, acqGait).compute(pointLabelSuffix="cgm1_6dof")

        #btkTools.smartWriter(acqGait,"testInvDyn.c3d")
        if plotFlag:
            plotMoment(acqGait, "LAnkleMoment", "LAnkleMoment_cgm1_6dof",
                       "LAnkle")
            plotMoment(acqGait, "LKneeMoment", "LKneeMoment_cgm1_6dof",
                       "LKnee")
            plotMoment(acqGait, "LHipMoment", "LHipMoment_cgm1_6dof", "LHip")
            #
            plotMoment(acqGait, "RAnkleMoment", "RAnkleMoment_cgm1_6dof",
                       "RAnkle")
            plotMoment(acqGait, "RKneeMoment", "RKneeMoment_cgm1_6dof",
                       "RKnee")
            plotMoment(acqGait, "RHipMoment", "RHipMoment_cgm1_6dof", "RHip")
            plt.show()

        btkTools.smartWriter(acqGait, "basicCGM1_JCS_Dual-test.c3d")
Example #17
0
    def CGM1_fullbody_onStatic(cls):

        MAIN_PATH = pyCGM2.TEST_DATA_PATH + "CGM1\\CGM1-TESTS\\Full PIG - StephenL5_C7\\"
        staticFilename = "PN01NORMSTAT.c3d"

        # CALIBRATION ###############################
        acqStatic = btkTools.smartReader(str(MAIN_PATH + staticFilename))

        markerDiameter = 14

        # Lower Limb
        mp = {
            'Bodymass': 83,
            'LeftLegLength': 874,
            'RightLegLength': 876.0,
            'LeftKneeWidth': 106.0,
            'RightKneeWidth': 103.0,
            'LeftAnkleWidth': 74.0,
            'RightAnkleWidth': 72.0,
            'LeftSoleDelta': 0,
            'RightSoleDelta': 0,
            'LeftShoulderOffset': 50,
            'LeftElbowWidth': 91,
            'LeftWristWidth': 56,
            'LeftHandThickness': 28,
            'RightShoulderOffset': 45,
            'RightElbowWidth': 90,
            'RightWristWidth': 55,
            'RightHandThickness': 30
        }

        model = cgm.CGM1()
        model.configure(bodyPart=enums.BodyPart.FullBody)
        model.addAnthropoInputParameters(mp)

        scp = modelFilters.StaticCalibrationProcedure(
            model)  # load calibration procedure
        csp = modelFilters.ModelCoordinateSystemProcedure(model)

        modelFilters.ModelCalibrationFilter(
            scp,
            acqStatic,
            model,
            leftFlatFoot=False,
            rightFlatFoot=False,
            markerDiameter=14,
            viconCGM1compatible=True,
        ).compute()
        #headHorizontal=True

        # --- motion ----
        gaitFilename = "PN01NORMSTAT_stephen.c3d"
        acqGait = btkTools.smartReader(str(MAIN_PATH + gaitFilename))

        modMotion = modelFilters.ModelMotionFilter(
            scp, acqGait, model, enums.motionMethod.Determinist)
        modMotion.compute()

        csdf = modelFilters.CoordinateSystemDisplayFilter(csp, model, acqGait)
        csdf.setStatic(False)
        csdf.display()

        # angles
        modelFilters.ModelJCSFilter(model, acqGait).compute(
            description="vectoriel", pointLabelSuffix="cgm1_6dof")

        longitudinalAxis, forwardProgression, globalFrame = btkTools.findProgressionAxisFromLongAxis(
            acqGait, "C7", "CLAV")
        modelFilters.ModelAbsoluteAnglesFilter(
            model,
            acqGait,
            segmentLabels=["Thorax"],
            angleLabels=[
                "Thorax",
            ],
            eulerSequences=["YXZ"],
            globalFrameOrientation=globalFrame,
            forwardProgression=forwardProgression).compute(
                pointLabelSuffix="cgm1_6dof")

        # testing
        np.testing.assert_equal(longitudinalAxis, "X")
        np.testing.assert_equal(forwardProgression, True)
        np.testing.assert_equal(globalFrame, "XYZ")

        # BSP model
        bspModel = bodySegmentParameters.Bsp(model)
        bspModel.compute()

        btkTools.smartAppendPoint(
            acqGait, "pelvisCOM_py",
            model.getSegment("Pelvis").getComTrajectory())
        btkTools.smartAppendPoint(acqGait, "headCOM_py",
                                  model.getSegment("Head").getComTrajectory())
        btkTools.smartAppendPoint(
            acqGait, "ThoraxCOM_py",
            model.getSegment("Thorax").getComTrajectory())
        btkTools.smartAppendPoint(
            acqGait, "LhumCOM_py",
            model.getSegment("Left UpperArm").getComTrajectory())
        btkTools.smartAppendPoint(
            acqGait, "LforeCom_py",
            model.getSegment("Left ForeArm").getComTrajectory())
        btkTools.smartAppendPoint(
            acqGait, "LhandCom_py",
            model.getSegment("Left Hand").getComTrajectory())
        btkTools.smartAppendPoint(
            acqGait, "RhumCOM_py",
            model.getSegment("Right UpperArm").getComTrajectory())
        btkTools.smartAppendPoint(
            acqGait, "RforeCom_py",
            model.getSegment("Right ForeArm").getComTrajectory())
        btkTools.smartAppendPoint(
            acqGait, "RhandCom_py",
            model.getSegment("Right Hand").getComTrajectory())

        modelFilters.CentreOfMassFilter(
            model, acqGait).compute(pointLabelSuffix="py2")

        TL5_pelvis = model.getSegment(
            "Pelvis").anatomicalFrame.getNodeTrajectory("TL5")
        TL5_thorax = model.getSegment(
            "Thorax").anatomicalFrame.getNodeTrajectory("TL5")
        C7o_thorax = model.getSegment(
            "Thorax").anatomicalFrame.getNodeTrajectory("C7o")
        C7_thorax = model.getSegment(
            "Thorax").anatomicalFrame.getNodeTrajectory("C7")
        C7_head = model.getSegment("Head").anatomicalFrame.getNodeTrajectory(
            "C7")
        btkTools.smartAppendPoint(acqGait, "TL5_pelvis", TL5_pelvis, desc="")
        btkTools.smartAppendPoint(acqGait, "TL5_thorax", TL5_thorax, desc="")
        btkTools.smartAppendPoint(acqGait, "C7o_thorax", C7o_thorax, desc="")
        btkTools.smartAppendPoint(acqGait, "C7_thorax", C7_thorax, desc="")
        btkTools.smartAppendPoint(acqGait, "C7_head", C7_thorax, desc="")

        btkTools.smartWriter(acqGait,
                             "FullBody_COM_CGM1_fullbody_onStatic.c3d")
Example #18
0
def calibrate(DATA_PATH, calibrateFilenameLabelled, translators, settings,
              required_mp, optional_mp, ik_flag, leftFlatFoot, rightFlatFoot,
              headFlat, markerDiameter, hjcMethod, pointSuffix, **kwargs):
    """
    Calibration of the CGM2.2

    :param DATA_PATH [str]: path to your data
    :param calibrateFilenameLabelled [str]: c3d file
    :param translators [dict]:  translators to apply
    :param required_mp [dict]: required anthropometric data
    :param optional_mp [dict]: optional anthropometric data (ex: LThighOffset,...)
    :param ik_flag [bool]: enable the inverse kinematic solver
    :param leftFlatFoot [bool]: enable of the flat foot option for the left foot
    :param rightFlatFoot [bool]: enable of the flat foot option for the right foot
    :param headFlat [bool]: enable of the head flat  option
    :param markerDiameter [double]: marker diameter (mm)
    :param hjcMethod [str or list of 3 float]: method for locating the hip joint centre
    :param pointSuffix [str]: suffix to add to model outputs

    """
    # --------------------ACQUISITION------------------------------

    # ---btk acquisition---

    if "forceBtkAcq" in kwargs.keys():
        acqStatic = kwargs["forceBtkAcq"]
    else:
        acqStatic = btkTools.smartReader(
            str(DATA_PATH + calibrateFilenameLabelled))

    btkTools.checkMultipleSubject(acqStatic)

    acqStatic = btkTools.applyTranslators(acqStatic, translators)

    # ---check marker set used----
    dcm = cgm.CGM.detectCalibrationMethods(acqStatic)

    # ---definition---
    model = cgm2.CGM2_2()
    model.configure(acq=acqStatic, detectedCalibrationMethods=dcm)

    model.addAnthropoInputParameters(required_mp, optional=optional_mp)
    # --store calibration parameters--
    model.setStaticFilename(calibrateFilenameLabelled)
    model.setCalibrationProperty("leftFlatFoot", leftFlatFoot)
    model.setCalibrationProperty("rightFlatFoot", rightFlatFoot)
    model.setCalibrationProperty("headFlat", headFlat)
    model.setCalibrationProperty("markerDiameter", markerDiameter)

    # --------------------------STATIC CALBRATION--------------------------
    scp = modelFilters.StaticCalibrationProcedure(
        model)  # load calibration procedure

    # ---initial calibration filter----
    # use if all optional mp are zero
    modelFilters.ModelCalibrationFilter(
        scp,
        acqStatic,
        model,
        leftFlatFoot=leftFlatFoot,
        rightFlatFoot=rightFlatFoot,
        headFlat=headFlat,
        markerDiameter=markerDiameter,
    ).compute()

    # ---- Decorators -----
    decorators.applyBasicDecorators(dcm, model, acqStatic, optional_mp,
                                    markerDiameter)
    decorators.applyHJCDecorators(model, hjcMethod)

    # ----Final Calibration filter if model previously decorated -----
    if model.decoratedModel:
        # initial static filter
        modelFilters.ModelCalibrationFilter(
            scp,
            acqStatic,
            model,
            leftFlatFoot=leftFlatFoot,
            rightFlatFoot=rightFlatFoot,
            headFlat=headFlat,
            markerDiameter=markerDiameter).compute()

    # ----------------------CGM MODELLING----------------------------------
    # ----motion filter----
    modMotion = modelFilters.ModelMotionFilter(scp,
                                               acqStatic,
                                               model,
                                               enums.motionMethod.Determinist,
                                               markerDiameter=markerDiameter)

    modMotion.compute()

    if ik_flag:
        #                        ---OPENSIM IK---

        # --- opensim calibration Filter ---
        osimfile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\osim\\lowerLimb_ballsJoints.osim"  # osimfile
        markersetFile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\settings\\cgm1\\cgm1-markerset.xml"  # markerset
        cgmCalibrationprocedure = opensimFilters.CgmOpensimCalibrationProcedures(
            model)  # procedure

        oscf = opensimFilters.opensimCalibrationFilter(
            osimfile, model, cgmCalibrationprocedure, str(DATA_PATH))
        oscf.addMarkerSet(markersetFile)
        scalingOsim = oscf.build()

        # --- opensim Fitting Filter ---
        iksetupFile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\settings\\cgm1\\cgm1-ikSetUp_template.xml"  # ik tool file

        cgmFittingProcedure = opensimFilters.CgmOpensimFittingProcedure(
            model)  # procedure
        cgmFittingProcedure.updateMarkerWeight(
            "LASI", settings["Fitting"]["Weight"]["LASI"])
        cgmFittingProcedure.updateMarkerWeight(
            "RASI", settings["Fitting"]["Weight"]["RASI"])
        cgmFittingProcedure.updateMarkerWeight(
            "LPSI", settings["Fitting"]["Weight"]["LPSI"])
        cgmFittingProcedure.updateMarkerWeight(
            "RPSI", settings["Fitting"]["Weight"]["RPSI"])
        cgmFittingProcedure.updateMarkerWeight(
            "RTHI", settings["Fitting"]["Weight"]["RTHI"])
        cgmFittingProcedure.updateMarkerWeight(
            "RKNE", settings["Fitting"]["Weight"]["RKNE"])
        cgmFittingProcedure.updateMarkerWeight(
            "RTIB", settings["Fitting"]["Weight"]["RTIB"])
        cgmFittingProcedure.updateMarkerWeight(
            "RANK", settings["Fitting"]["Weight"]["RANK"])
        cgmFittingProcedure.updateMarkerWeight(
            "RHEE", settings["Fitting"]["Weight"]["RHEE"])
        cgmFittingProcedure.updateMarkerWeight(
            "RTOE", settings["Fitting"]["Weight"]["RTOE"])
        cgmFittingProcedure.updateMarkerWeight(
            "LTHI", settings["Fitting"]["Weight"]["LTHI"])
        cgmFittingProcedure.updateMarkerWeight(
            "LKNE", settings["Fitting"]["Weight"]["LKNE"])
        cgmFittingProcedure.updateMarkerWeight(
            "LTIB", settings["Fitting"]["Weight"]["LTIB"])
        cgmFittingProcedure.updateMarkerWeight(
            "LANK", settings["Fitting"]["Weight"]["LANK"])
        cgmFittingProcedure.updateMarkerWeight(
            "LHEE", settings["Fitting"]["Weight"]["LHEE"])
        cgmFittingProcedure.updateMarkerWeight(
            "LTOE", settings["Fitting"]["Weight"]["LTOE"])

        osrf = opensimFilters.opensimFittingFilter(iksetupFile, scalingOsim,
                                                   cgmFittingProcedure,
                                                   str(DATA_PATH))
        acqStaticIK = osrf.run(acqStatic,
                               str(DATA_PATH + calibrateFilenameLabelled))

        # --- final pyCGM2 model motion Filter ---
        # use fitted markers
        modMotionFitted = modelFilters.ModelMotionFilter(
            scp, acqStaticIK, model, enums.motionMethod.Determinist)

        modMotionFitted.compute()

    # eventual static acquisition to consider for joint kinematics
    finalAcqStatic = acqStaticIK if ik_flag else acqStatic

    if "displayCoordinateSystem" in kwargs.keys(
    ) and kwargs["displayCoordinateSystem"]:
        csp = modelFilters.ModelCoordinateSystemProcedure(model)
        csdf = modelFilters.CoordinateSystemDisplayFilter(
            csp, model, finalAcqStatic)
        csdf.setStatic(False)
        csdf.display()

    #---- Joint kinematics----
    # relative angles
    modelFilters.ModelJCSFilter(model, finalAcqStatic).compute(
        description="vectoriel", pointLabelSuffix=pointSuffix)

    # detection of traveling axis + absolute angle
    if model.m_bodypart != enums.BodyPart.UpperLimb:
        longitudinalAxis, forwardProgression, globalFrame = btkTools.findProgressionAxisFromPelvicMarkers(
            finalAcqStatic, ["LASI", "LPSI", "RASI", "RPSI"])
    else:
        longitudinalAxis, forwardProgression, globalFrame = btkTools.findProgressionAxisFromLongAxis(
            finalAcqStatic, "C7", "CLAV")

    if model.m_bodypart != enums.BodyPart.UpperLimb:
        modelFilters.ModelAbsoluteAnglesFilter(
            model,
            finalAcqStatic,
            segmentLabels=["Left Foot", "Right Foot", "Pelvis"],
            angleLabels=["LFootProgress", "RFootProgress", "Pelvis"],
            eulerSequences=["TOR", "TOR", "ROT"],
            globalFrameOrientation=globalFrame,
            forwardProgression=forwardProgression).compute(
                pointLabelSuffix=pointSuffix)

    if model.m_bodypart == enums.BodyPart.LowerLimbTrunk:
        modelFilters.ModelAbsoluteAnglesFilter(
            model,
            finalAcqStatic,
            segmentLabels=["Thorax"],
            angleLabels=["Thorax"],
            eulerSequences=["YXZ"],
            globalFrameOrientation=globalFrame,
            forwardProgression=forwardProgression).compute(
                pointLabelSuffix=pointSuffix)

    if model.m_bodypart == enums.BodyPart.UpperLimb or model.m_bodypart == enums.BodyPart.FullBody:

        modelFilters.ModelAbsoluteAnglesFilter(
            model,
            finalAcqStatic,
            segmentLabels=["Thorax", "Head"],
            angleLabels=["Thorax", "Head"],
            eulerSequences=["YXZ", "TOR"],
            globalFrameOrientation=globalFrame,
            forwardProgression=forwardProgression).compute(
                pointLabelSuffix=pointSuffix)
    # BSP model
    bspModel = bodySegmentParameters.Bsp(model)
    bspModel.compute()

    if model.m_bodypart == enums.BodyPart.FullBody:
        modelFilters.CentreOfMassFilter(
            model, finalAcqStatic).compute(pointLabelSuffix=pointSuffix)

    return model, finalAcqStatic
Example #19
0
    def CGM23_SARA_test(cls):
        MAIN_PATH = pyCGM2.TEST_DATA_PATH + "CGM2\\cgm2.3\\Knee Calibration\\"
        staticFilename = "Static.c3d"

        leftKneeFilename = "Left Knee.c3d"
        rightKneeFilename = "Right Knee.c3d"
        gaitFilename = "gait trial 01.c3d"

        markerDiameter = 14
        mp = {
            'Bodymass': 71.0,
            'LeftLegLength': 860.0,
            'RightLegLength': 865.0,
            'LeftKneeWidth': 102.0,
            'RightKneeWidth': 103.4,
            'LeftAnkleWidth': 75.3,
            'RightAnkleWidth': 72.9,
            'LeftSoleDelta': 0,
            'RightSoleDelta': 0,
        }

        acqStatic = btkTools.smartReader(str(MAIN_PATH + staticFilename))

        model = cgm2.CGM2_3()
        model.configure()

        model.addAnthropoInputParameters(mp)

        # --- INITIAL  CALIBRATION ---
        scp = modelFilters.StaticCalibrationProcedure(model)
        modelFilters.ModelCalibrationFilter(scp, acqStatic, model).compute()

        # cgm decorator
        modelDecorator.HipJointCenterDecorator(model).hara()
        modelDecorator.KneeCalibrationDecorator(model).midCondyles(
            acqStatic, markerDiameter=markerDiameter, side="both")
        modelDecorator.AnkleCalibrationDecorator(model).midMaleolus(
            acqStatic, markerDiameter=markerDiameter, side="both")

        # final
        modelFilters.ModelCalibrationFilter(
            scp,
            acqStatic,
            model,
            seLeftHJCnode="LHJC_Hara",
            useRightHJCnode="RHJC_Hara",
            useLeftKJCnode="LKJC_mid",
            useLeftAJCnode="LAJC_mid",
            useRightKJCnode="RKJC_mid",
            useRightAJCnode="RAJC_mid",
            markerDiameter=markerDiameter).compute()

        # ------ LEFT KNEE CALIBRATION -------
        acqLeftKnee = btkTools.smartReader(str(MAIN_PATH + leftKneeFilename))

        # Motion of only left
        modMotionLeftKnee = modelFilters.ModelMotionFilter(
            scp, acqLeftKnee, model, enums.motionMethod.Sodervisk)
        modMotionLeftKnee.segmentalCompute(["Left Thigh", "Left Shank"])

        # decorator
        modelDecorator.KneeCalibrationDecorator(model).sara(
            "Left", indexFirstFrame=489, indexLastFrame=1451)

        # ----add Point into the c3d----
        Or_inThigh = model.getSegment("Left Thigh").getReferential(
            "TF").getNodeTrajectory("KneeFlexionOri")
        axis_inThigh = model.getSegment("Left Thigh").getReferential(
            "TF").getNodeTrajectory("KneeFlexionAxis")
        btkTools.smartAppendPoint(acqLeftKnee, "Left" + "_KneeFlexionOri",
                                  Or_inThigh)
        btkTools.smartAppendPoint(acqLeftKnee, "Left" + "_KneeFlexionAxis",
                                  axis_inThigh)
        btkTools.smartWriter(acqLeftKnee, "Left Knee-Sara.c3d")

        # ------ RIGHT KNEE CALIBRATION -------
        acqRightKnee = btkTools.smartReader(str(MAIN_PATH + rightKneeFilename))

        # Motion of only left
        modMotionRightKnee = modelFilters.ModelMotionFilter(
            scp, acqRightKnee, model, enums.motionMethod.Sodervisk)
        modMotionRightKnee.segmentalCompute(["Right Thigh", "Right Shank"])

        # decorator
        modelDecorator.KneeCalibrationDecorator(model).sara(
            "Right", indexFirstFrame=25, indexLastFrame=1060)

        # ----add Point into the c3d----
        Or_inThigh = model.getSegment("Right Thigh").getReferential(
            "TF").getNodeTrajectory("KneeFlexionOri")
        axis_inThigh = model.getSegment("Right Thigh").getReferential(
            "TF").getNodeTrajectory("KneeFlexionAxis")
        btkTools.smartAppendPoint(acqRightKnee, "Right" + "_KneeFlexionOri",
                                  Or_inThigh)
        btkTools.smartAppendPoint(acqRightKnee, "Right" + "_KneeFlexionAxis",
                                  axis_inThigh)
        btkTools.smartWriter(acqRightKnee, "Right Knee-Sara.c3d")

        #--- FINAL  CALIBRATION ---
        modelFilters.ModelCalibrationFilter(
            scp,
            acqStatic,
            model,
            useLeftHJCnode="LHJC_Hara",
            useRightHJCnode="RHJC_Hara",
            useLeftKJCnode="KJC_Sara",
            useLeftAJCnode="LAJC_mid",
            useRightKJCnode="KJC_Sara",
            useRightAJCnode="RAJC_mid",
            markerDiameter=markerDiameter).compute()

        #  save static c3d with update KJC
        btkTools.smartWriter(acqStatic, "Static-SARA.c3d")
Example #20
0
def calibrate(DATA_PATH,calibrateFilenameLabelled,translators,weights,
              required_mp,optional_mp,
              ik_flag,leftFlatFoot,rightFlatFoot,headFlat,
              markerDiameter,hjcMethod,
              pointSuffix,**kwargs):
    """
    Calibration of the CGM2.4

    :param DATA_PATH [str]: path to your data
    :param calibrateFilenameLabelled [str]: c3d file
    :param translators [dict]:  translators to apply
    :param required_mp [dict]: required anthropometric data
    :param optional_mp [dict]: optional anthropometric data (ex: LThighOffset,...)
    :param ik_flag [bool]: enable the inverse kinematic solver
    :param leftFlatFoot [bool]: enable of the flat foot option for the left foot
    :param rightFlatFoot [bool]: enable of the flat foot option for the right foot
    :param headFlat [bool]: enable of the head flat  option
    :param markerDiameter [double]: marker diameter (mm)
    :param hjcMethod [str or list of 3 float]: method for locating the hip joint centre
    :param pointSuffix [str]: suffix to add to model outputs

    """

    detectAnomaly = False


    if "anomalyException" in kwargs.keys():
        anomalyException = kwargs["anomalyException"]
    else:
        anomalyException=False


    # ---btk acquisition---


    if "Fitting" in weights.keys():
        weights  = weights["Fitting"]["Weight"]

    if "forceBtkAcq" in kwargs.keys():
        acqStatic = kwargs["forceBtkAcq"]
    else:
        acqStatic = btkTools.smartReader((DATA_PATH+calibrateFilenameLabelled))

    btkTools.checkMultipleSubject(acqStatic)
    if btkTools.isPointExist(acqStatic,"SACR"):
        translators["LPSI"] = "SACR"
        translators["RPSI"] = "SACR"
        LOGGER.logger.info("[pyCGM2] Sacrum marker detected")

    acqStatic =  btkTools.applyTranslators(acqStatic,translators)

    trackingMarkers = cgm2.CGM2_4.LOWERLIMB_TRACKING_MARKERS + cgm2.CGM2_4.THORAX_TRACKING_MARKERS+ cgm2.CGM2_4.UPPERLIMB_TRACKING_MARKERS
    actual_trackingMarkers,phatoms_trackingMarkers = btkTools.createPhantoms(acqStatic, trackingMarkers)

    vff = acqStatic.GetFirstFrame()
    vlf = acqStatic.GetLastFrame()
    # vff,vlf = btkTools.getFrameBoundaries(acqStatic,actual_trackingMarkers)
    flag = btkTools.getValidFrames(acqStatic,actual_trackingMarkers,frameBounds=[vff,vlf])

    gapFlag = btkTools.checkGap(acqStatic,actual_trackingMarkers,frameBounds=[vff,vlf])
    if gapFlag:
        raise Exception("[pyCGM2] Calibration aborted. Gap find during interval [%i-%i]. Crop your c3d " %(vff,vlf))

    # --------------------ANOMALY------------------------------
    # --Check MP
    adap = AnomalyDetectionProcedure.AnthropoDataAnomalyProcedure( required_mp)
    adf = AnomalyFilter.AnomalyDetectionFilter(None,None,adap)
    mp_anomaly = adf.run()
    if mp_anomaly["ErrorState"]: detectAnomaly = True

    # --marker presence
    markersets = [cgm2.CGM2_4.LOWERLIMB_TRACKING_MARKERS, cgm2.CGM2_4.THORAX_TRACKING_MARKERS, cgm2.CGM2_4.UPPERLIMB_TRACKING_MARKERS]
    for markerset in markersets:
        ipdp = InspectorProcedure.MarkerPresenceDetectionProcedure( markerset)
        idf = InspectorFilter.InspectorFilter(acqStatic,calibrateFilenameLabelled,ipdp)
        inspector = idf.run()

        # # --marker outliers
        if inspector["In"] !=[]:
            madp = AnomalyDetectionProcedure.MarkerAnomalyDetectionRollingProcedure(inspector["In"], plot=False, window=4,threshold = 3)
            adf = AnomalyFilter.AnomalyDetectionFilter(acqStatic,calibrateFilenameLabelled,madp)
            anomaly = adf.run()
            anomalyIndexes = anomaly["Output"]
            if anomaly["ErrorState"]: detectAnomaly = True


    if detectAnomaly and anomalyException:
        raise Exception ("Anomalies has been detected - Check Warning message of the log file")

    # --------------------MODELLING------------------------------

    # ---check marker set used----
    dcm = cgm.CGM.detectCalibrationMethods(acqStatic)

    # --------------------------MODEL--------------------------------------
    # ---definition---
    model=cgm2.CGM2_4()
    model.configure(detectedCalibrationMethods=dcm)
    model.addAnthropoInputParameters(required_mp,optional=optional_mp)

    if dcm["Left Knee"] == enums.JointCalibrationMethod.KAD: actual_trackingMarkers.append("LKNE")
    if dcm["Right Knee"] == enums.JointCalibrationMethod.KAD: actual_trackingMarkers.append("RKNE")
    model.setStaticTrackingMarkers(actual_trackingMarkers)

    # --store calibration parameters--
    model.setStaticFilename(calibrateFilenameLabelled)
    model.setCalibrationProperty("leftFlatFoot",leftFlatFoot)
    model.setCalibrationProperty("rightFlatFoot",rightFlatFoot)
    model.setCalibrationProperty("headFlat",headFlat)
    model.setCalibrationProperty("markerDiameter",markerDiameter)



    # --------------------------STATIC CALBRATION--------------------------
    scp=modelFilters.StaticCalibrationProcedure(model) # load calibration procedure

    # ---initial calibration filter----
    # use if all optional mp are zero
    modelFilters.ModelCalibrationFilter(scp,acqStatic,model,
                                        leftFlatFoot = leftFlatFoot, rightFlatFoot = rightFlatFoot,
                                        headFlat= headFlat,
                                        markerDiameter=markerDiameter,
                                        ).compute()

    # ---- Decorators -----
    decorators.applyBasicDecorators(dcm, model,acqStatic,optional_mp,markerDiameter)
    decorators.applyHJCDecorators(model,hjcMethod)

    # ----Final Calibration filter if model previously decorated -----
    if model.decoratedModel:
        # initial static filter
        modelFilters.ModelCalibrationFilter(scp,acqStatic,model,
                           leftFlatFoot = leftFlatFoot, rightFlatFoot = rightFlatFoot,
                           headFlat= headFlat,
                           markerDiameter=markerDiameter).compute()


    # ----------------------CGM MODELLING----------------------------------
    # ----motion filter----
    modMotion=modelFilters.ModelMotionFilter(scp,acqStatic,model,enums.motionMethod.Sodervisk,
                                              markerDiameter=markerDiameter)

    modMotion.compute()


    # ----progression Frame----
    progressionFlag = False
    if btkTools.isPointsExist(acqStatic, ['LASI', 'RASI', 'RPSI', 'LPSI'],ignorePhantom=False):
        LOGGER.logger.info("[pyCGM2] - progression axis detected from Pelvic markers ")
        pfp = progressionFrame.PelvisProgressionFrameProcedure()
        pff = progressionFrame.ProgressionFrameFilter(acqStatic,pfp)
        pff.compute()
        progressionAxis = pff.outputs["progressionAxis"]
        globalFrame = pff.outputs["globalFrame"]
        forwardProgression = pff.outputs["forwardProgression"]
        progressionFlag = True
    elif btkTools.isPointsExist(acqStatic, ['C7', 'T10', 'CLAV', 'STRN'],ignorePhantom=False) and not progressionFlag:
        LOGGER.logger.info("[pyCGM2] - progression axis detected from Thoracic markers ")
        pfp = progressionFrame.ThoraxProgressionFrameProcedure()
        pff = progressionFrame.ProgressionFrameFilter(acqStatic,pfp)
        pff.compute()
        progressionAxis = pff.outputs["progressionAxis"]
        globalFrame = pff.outputs["globalFrame"]
        forwardProgression = pff.outputs["forwardProgression"]

    else:
        globalFrame = "XYZ"
        progressionAxis = "X"
        forwardProgression = True
        LOGGER.logger.error("[pyCGM2] - impossible to detect progression axis - neither pelvic nor thoracic markers are present. Progression set to +X by default ")

    # ----manage IK Targets----
    ikTargets = list()
    for target in weights.keys():
        if target not in actual_trackingMarkers:
            weights[target] = 0
            LOGGER.logger.warning("[pyCGM2] - the IK targeted marker [%s] is not labelled in the acquisition [%s]"%(target,calibrateFilenameLabelled))
        else:
            ikTargets.append(target)
    model.setStaticIkTargets(ikTargets)

    if "noKinematicsCalculation" in kwargs.keys() and kwargs["noKinematicsCalculation"]:
        LOGGER.logger.warning("[pyCGM2] No Kinematic calculation done for the static file")
        return model, acqStatic,detectAnomaly
    else:
        if ik_flag:
            #                        ---OPENSIM IK---

            # --- opensim calibration Filter ---
            osimfile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\osim\\lowerLimb_ballsJoints.osim"    # osimfile
            markersetFile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\settings\\cgm2_4\\cgm2_4-markerset.xml" # markerset
            cgmCalibrationprocedure = opensimFilters.CgmOpensimCalibrationProcedures(model) # procedure

            oscf = opensimFilters.opensimCalibrationFilter(osimfile,
                                                    model,
                                                    cgmCalibrationprocedure,
                                                    DATA_PATH )
            oscf.addMarkerSet(markersetFile)
            scalingOsim = oscf.build()


            # --- opensim Fitting Filter ---
            iksetupFile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\settings\\cgm2_4\\cgm2_4-ikSetUp_template.xml" # ik tool file

            cgmFittingProcedure = opensimFilters.CgmOpensimFittingProcedure(model) # procedure
            cgmFittingProcedure.updateMarkerWeight("LASI",weights["LASI"])
            cgmFittingProcedure.updateMarkerWeight("RASI",weights["RASI"])
            cgmFittingProcedure.updateMarkerWeight("LPSI",weights["LPSI"])
            cgmFittingProcedure.updateMarkerWeight("RPSI",weights["RPSI"])
            cgmFittingProcedure.updateMarkerWeight("RTHI",weights["RTHI"])
            cgmFittingProcedure.updateMarkerWeight("RKNE",weights["RKNE"])
            cgmFittingProcedure.updateMarkerWeight("RTIB",weights["RTIB"])
            cgmFittingProcedure.updateMarkerWeight("RANK",weights["RANK"])
            cgmFittingProcedure.updateMarkerWeight("RHEE",weights["RHEE"])
            cgmFittingProcedure.updateMarkerWeight("RTOE",weights["RTOE"])

            cgmFittingProcedure.updateMarkerWeight("LTHI",weights["LTHI"])
            cgmFittingProcedure.updateMarkerWeight("LKNE",weights["LKNE"])
            cgmFittingProcedure.updateMarkerWeight("LTIB",weights["LTIB"])
            cgmFittingProcedure.updateMarkerWeight("LANK",weights["LANK"])
            cgmFittingProcedure.updateMarkerWeight("LHEE",weights["LHEE"])
            cgmFittingProcedure.updateMarkerWeight("LTOE",weights["LTOE"])

            cgmFittingProcedure.updateMarkerWeight("LTHAP",weights["LTHAP"])
            cgmFittingProcedure.updateMarkerWeight("LTHAD",weights["LTHAD"])
            cgmFittingProcedure.updateMarkerWeight("LTIAP",weights["LTIAP"])
            cgmFittingProcedure.updateMarkerWeight("LTIAD",weights["LTIAD"])
            cgmFittingProcedure.updateMarkerWeight("RTHAP",weights["RTHAP"])
            cgmFittingProcedure.updateMarkerWeight("RTHAD",weights["RTHAD"])
            cgmFittingProcedure.updateMarkerWeight("RTIAP",weights["RTIAP"])
            cgmFittingProcedure.updateMarkerWeight("RTIAD",weights["RTIAD"])

            cgmFittingProcedure.updateMarkerWeight("LSMH",weights["LSMH"])
            cgmFittingProcedure.updateMarkerWeight("LFMH",weights["LFMH"])
            cgmFittingProcedure.updateMarkerWeight("LVMH",weights["LVMH"])

            cgmFittingProcedure.updateMarkerWeight("RSMH",weights["RSMH"])
            cgmFittingProcedure.updateMarkerWeight("RFMH",weights["RFMH"])
            cgmFittingProcedure.updateMarkerWeight("RVMH",weights["RVMH"])

    #            cgmFittingProcedure.updateMarkerWeight("LTHL",weights["LTHL"])
    #            cgmFittingProcedure.updateMarkerWeight("LTHLD",weights["LTHLD"])
    #            cgmFittingProcedure.updateMarkerWeight("LPAT",weights["LPAT"])
    #            cgmFittingProcedure.updateMarkerWeight("LTIBL",weights["LTIBL"])
    #            cgmFittingProcedure.updateMarkerWeight("RTHL",weights["RTHL"])
    #            cgmFittingProcedure.updateMarkerWeight("RTHLD",weights["RTHLD"])
    #            cgmFittingProcedure.updateMarkerWeight("RPAT",weights["RPAT"])
    #            cgmFittingProcedure.updateMarkerWeight("RTIBL",weights["RTIBL"])


            osrf = opensimFilters.opensimFittingFilter(iksetupFile,
                                                              scalingOsim,
                                                              cgmFittingProcedure,
                                                              DATA_PATH,
                                                              acqStatic,
                                                             accuracy = 1e-5)
            osrf.setTimeRange(acqStatic,beginFrame = vff, lastFrame=vlf)
            LOGGER.logger.info("-------INVERSE KINEMATICS IN PROGRESS----------")
            try:
                acqStaticIK = osrf.run(DATA_PATH + calibrateFilenameLabelled,
                             progressionAxis = progressionAxis ,
                             forwardProgression = forwardProgression)
                LOGGER.logger.info("[pyCGM2] - IK solver complete")
            except:
                LOGGER.logger.error("[pyCGM2] - IK solver fails")
                acqStaticIK = acqStatic
                detectAnomaly = True
            LOGGER.logger.info("-----------------------------------------------")



        # eventual static acquisition to consider for joint kinematics
        finalAcqStatic = acqStaticIK if ik_flag else acqStatic

        # --- final pyCGM2 model motion Filter ---
        # use fitted markers
        modMotionFitted=modelFilters.ModelMotionFilter(scp,finalAcqStatic,model,enums.motionMethod.Sodervisk)
        modMotionFitted.compute()

        if "displayCoordinateSystem" in kwargs.keys() and kwargs["displayCoordinateSystem"]:
            csp = modelFilters.ModelCoordinateSystemProcedure(model)
            csdf = modelFilters.CoordinateSystemDisplayFilter(csp,model,finalAcqStatic)
            csdf.setStatic(False)
            csdf.display()

        #---- Joint kinematics----
        # relative angles
        modelFilters.ModelJCSFilter(model,finalAcqStatic).compute(description="vectoriel", pointLabelSuffix=pointSuffix)

        modelFilters.ModelAbsoluteAnglesFilter(model,finalAcqStatic,
                                               segmentLabels=["Left Foot","Right Foot","Pelvis","Thorax","Head"],
                                                angleLabels=["LFootProgress", "RFootProgress","Pelvis","Thorax", "Head"],
                                                eulerSequences=["TOR","TOR", "ROT","YXZ","TOR"],
                                                globalFrameOrientation = globalFrame,
                                                forwardProgression = forwardProgression).compute(pointLabelSuffix=pointSuffix)

        bspModel = bodySegmentParameters.Bsp(model)
        bspModel.compute()


        modelFilters.CentreOfMassFilter(model,finalAcqStatic).compute(pointLabelSuffix=pointSuffix)

        btkTools.cleanAcq(finalAcqStatic)
        if detectAnomaly and not anomalyException:
            LOGGER.logger.error("Anomalies has been detected - Check Warning messages of the log file")

        return model, finalAcqStatic,detectAnomaly
Example #21
0
def fitting(model, DATA_PATH, reconstructFilenameLabelled, translators,
            markerDiameter, pointSuffix, mfpa, momentProjection, **kwargs):
    """
    Fitting of the CGM2.1

    :param model [str]: pyCGM2 model previously calibrated
    :param DATA_PATH [str]: path to your data
    :param reconstructFilenameLabelled [string list]: c3d files
    :param translators [dict]:  translators to apply
    :param mfpa [str]: manual force plate assignement
    :param markerDiameter [double]: marker diameter (mm)
    :param pointSuffix [str]: suffix to add to model outputs
    :param momentProjection [str]: Coordinate system in which joint moment is expressed
    """
    # --------------------------ACQUISITION ------------------------------------

    # --- btk acquisition ----
    if "forceBtkAcq" in kwargs.keys():
        acqGait = kwargs["forceBtkAcq"]
    else:
        acqGait = btkTools.smartReader(
            str(DATA_PATH + reconstructFilenameLabelled))

    btkTools.checkMultipleSubject(acqGait)
    acqGait = btkTools.applyTranslators(acqGait, translators)
    trackingMarkers = model.getTrackingMarkers()
    validFrames, vff, vlf = btkTools.findValidFrames(acqGait, trackingMarkers)

    scp = modelFilters.StaticCalibrationProcedure(model)
    # ---Motion filter----
    modMotion = modelFilters.ModelMotionFilter(scp,
                                               acqGait,
                                               model,
                                               enums.motionMethod.Determinist,
                                               markerDiameter=markerDiameter)

    modMotion.compute()

    if "displayCoordinateSystem" in kwargs.keys(
    ) and kwargs["displayCoordinateSystem"]:
        csp = modelFilters.ModelCoordinateSystemProcedure(model)
        csdf = modelFilters.CoordinateSystemDisplayFilter(csp, model, acqGait)
        csdf.setStatic(False)
        csdf.display()

    #---- Joint kinematics----
    # relative angles
    modelFilters.ModelJCSFilter(model,
                                acqGait).compute(description="vectoriel",
                                                 pointLabelSuffix=pointSuffix)

    # detection of traveling axis + absolute angle
    if model.m_bodypart != enums.BodyPart.UpperLimb:
        longitudinalAxis, forwardProgression, globalFrame = btkTools.findProgressionAxisFromPelvicMarkers(
            acqGait, ["LASI", "LPSI", "RASI", "RPSI"])
    else:
        longitudinalAxis, forwardProgression, globalFrame = btkTools.findProgressionAxisFromLongAxis(
            acqGait, "C7", "CLAV")

    if model.m_bodypart != enums.BodyPart.UpperLimb:
        modelFilters.ModelAbsoluteAnglesFilter(
            model,
            acqGait,
            segmentLabels=["Left Foot", "Right Foot", "Pelvis"],
            angleLabels=["LFootProgress", "RFootProgress", "Pelvis"],
            eulerSequences=["TOR", "TOR", "ROT"],
            globalFrameOrientation=globalFrame,
            forwardProgression=forwardProgression).compute(
                pointLabelSuffix=pointSuffix)

    if model.m_bodypart == enums.BodyPart.LowerLimbTrunk:
        modelFilters.ModelAbsoluteAnglesFilter(
            model,
            acqGait,
            segmentLabels=["Thorax"],
            angleLabels=["Thorax"],
            eulerSequences=["YXZ"],
            globalFrameOrientation=globalFrame,
            forwardProgression=forwardProgression).compute(
                pointLabelSuffix=pointSuffix)

    if model.m_bodypart == enums.BodyPart.UpperLimb or model.m_bodypart == enums.BodyPart.FullBody:

        modelFilters.ModelAbsoluteAnglesFilter(
            model,
            acqGait,
            segmentLabels=["Thorax", "Head"],
            angleLabels=["Thorax", "Head"],
            eulerSequences=["YXZ", "TOR"],
            globalFrameOrientation=globalFrame,
            forwardProgression=forwardProgression).compute(
                pointLabelSuffix=pointSuffix)

    #---- Body segment parameters----
    bspModel = bodySegmentParameters.Bsp(model)
    bspModel.compute()

    if model.m_bodypart == enums.BodyPart.FullBody:
        modelFilters.CentreOfMassFilter(
            model, acqGait).compute(pointLabelSuffix=pointSuffix)

    # Inverse dynamics
    if model.m_bodypart != enums.BodyPart.UpperLimb:
        # --- force plate handling----
        # find foot  in contact
        mappedForcePlate = forceplates.matchingFootSideOnForceplate(acqGait,
                                                                    mfpa=mfpa)
        forceplates.addForcePlateGeneralEvents(acqGait, mappedForcePlate)
        logging.warning("Manual Force plate assignment : %s" %
                        mappedForcePlate)

        # assembly foot and force plate
        modelFilters.ForcePlateAssemblyFilter(
            model,
            acqGait,
            mappedForcePlate,
            leftSegmentLabel="Left Foot",
            rightSegmentLabel="Right Foot").compute()

        #---- Joint kinetics----
        idp = modelFilters.CGMLowerlimbInverseDynamicProcedure()
        modelFilters.InverseDynamicFilter(
            model,
            acqGait,
            procedure=idp,
            projection=momentProjection,
        ).compute(pointLabelSuffix=pointSuffix)

        #---- Joint energetics----
        modelFilters.JointPowerFilter(
            model, acqGait).compute(pointLabelSuffix=pointSuffix)

    #---- zero unvalid frames ---
    btkTools.applyValidFramesOnOutput(acqGait, validFrames)

    return acqGait
Example #22
0
    def test_lowLevel(self):
        DATA_PATH = pyCGM2.TEST_DATA_PATH + "GaitModels\CGM2.3\\Hannibal-medial\\"

        staticFilename = "static.c3d"
        gaitFilename= "gait1.c3d"

        markerDiameter=14
        required_mp={
        'Bodymass'   : 71.0,
        'LeftLegLength' : 860.0,
        'RightLegLength' : 865.0 ,
        'LeftKneeWidth' : 102.0,
        'RightKneeWidth' : 103.4,
        'LeftAnkleWidth' : 75.3,
        'RightAnkleWidth' : 72.9,
        'LeftSoleDelta' : 0,
        'RightSoleDelta' : 0,
        'LeftShoulderOffset' : 0,
        'RightShoulderOffset' : 0,
        'LeftElbowWidth' : 0,
        'LeftWristWidth' : 0,
        'LeftHandThickness' : 0,
        'RightElbowWidth' : 0,
        'RightWristWidth' : 0,
        'RightHandThickness' : 0
        }
        optional_mp = {
            'LeftTibialTorsion' : 0,
            'LeftThighRotation' : 0,
            'LeftShankRotation' : 0,
            'RightTibialTorsion' : 0,
            'RightThighRotation' : 0,
            'RightShankRotation' : 0
            }

        # --- Calibration ---
        # ---check marker set used----
        acqStatic = btkTools.smartReader(DATA_PATH +  staticFilename)

        dcm = cgm.CGM.detectCalibrationMethods(acqStatic)
        model=cgm2.CGM2_3()
        model.configure(detectedCalibrationMethods=dcm)
        model.addAnthropoInputParameters(required_mp,optional=optional_mp)

        # ---- Calibration ----

        scp=modelFilters.StaticCalibrationProcedure(model)
        modelFilters.ModelCalibrationFilter(scp,acqStatic,model).compute()

        # cgm decorator
        modelDecorator.HipJointCenterDecorator(model).hara()
        modelDecorator.KneeCalibrationDecorator(model).midCondyles(acqStatic, markerDiameter=markerDiameter, side="both")
        modelDecorator.AnkleCalibrationDecorator(model).midMaleolus(acqStatic, markerDiameter=markerDiameter, side="both")

        # final
        modelFilters.ModelCalibrationFilter(scp,acqStatic,model,
                           markerDiameter=markerDiameter).compute()


        # ------ Fitting -------
        acqGait = btkTools.smartReader(DATA_PATH +  gaitFilename)


        # Motion FILTER
        modMotion=modelFilters.ModelMotionFilter(scp,acqGait,model,enums.motionMethod.Sodervisk)
        modMotion.compute()



        # ------- OPENSIM IK --------------------------------------
        # --- osim builder ---
        cgmCalibrationprocedure = opensimFilters.CgmOpensimCalibrationProcedures(model)
        markersetFile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\settings\\cgm2_3\\cgm2_3-markerset.xml"

        osimfile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\osim\\lowerLimb_ballsJoints.osim"


        oscf = opensimFilters.opensimCalibrationFilter(osimfile,
                                                model,
                                                cgmCalibrationprocedure,
                                                DATA_PATH)
        oscf.addMarkerSet(markersetFile)
        scalingOsim = oscf.build(exportOsim=False)


        # --- fitting ---
        #procedure
        cgmFittingProcedure = opensimFilters.CgmOpensimFittingProcedure(model)

        iksetupFile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\settings\\cgm2_3\\cgm2_3-ikSetUp_template.xml"

        osrf = opensimFilters.opensimFittingFilter(iksetupFile,
                                                          scalingOsim,
                                                          cgmFittingProcedure,
                                                          DATA_PATH,
                                                          acqGait )


        acqIK = osrf.run(str(DATA_PATH + gaitFilename ),exportSetUp=False)

        # -------- NEW MOTION FILTER ON IK MARKERS ------------------

        modMotion_ik=modelFilters.ModelMotionFilter(scp,acqIK,model,enums.motionMethod.Sodervisk,
                                                    useForMotionTest=True)
        modMotion_ik.compute()

        finalJcs =modelFilters.ModelJCSFilter(model,acqIK)
        finalJcs.compute(description="ik", pointLabelSuffix = "2_ik")#

        btkTools.smartWriter(acqIK,"cgm23_fullIK_Motion.c3d")
Example #23
0
def calibrate(DATA_PATH, calibrateFilenameLabelled, translators, required_mp,
              optional_mp, leftFlatFoot, rightFlatFoot, headFlat,
              markerDiameter, hjcMethod, pointSuffix, **kwargs):
    """
    Calibration of the CGM2.1

    :param DATA_PATH [str]: path to your data
    :param calibrateFilenameLabelled [str]: c3d file
    :param translators [dict]:  translators to apply
    :param required_mp [dict]: required anthropometric data
    :param optional_mp [dict]: optional anthropometric data (ex: LThighOffset,...)
    :param leftFlatFoot [bool]: enable of the flat foot option for the left foot
    :param rightFlatFoot [bool]: enable of the flat foot option for the right foot
    :param headFlat [bool]: enable of the head flat  option
    :param markerDiameter [double]: marker diameter (mm)
    :param hjcMethod [str or list of 3 float]: method for locating the hip joint centre
    :param pointSuffix [str]: suffix to add to model outputs

    """

    # --------------------------ACQUISITION ------------------------------------

    # ---btk acquisition---
    if "forceBtkAcq" in kwargs.keys():
        acqStatic = kwargs["forceBtkAcq"]
    else:
        acqStatic = btkTools.smartReader(
            str(DATA_PATH + calibrateFilenameLabelled))

    btkTools.checkMultipleSubject(acqStatic)

    acqStatic = btkTools.applyTranslators(acqStatic, translators)

    # ---check marker set used----
    dcm = cgm.CGM.detectCalibrationMethods(acqStatic)

    # ---definition---
    model = cgm2.CGM2_1()
    model.configure(acq=acqStatic, detectedCalibrationMethods=dcm)

    model.addAnthropoInputParameters(required_mp, optional=optional_mp)

    # --store calibration parameters--
    model.setStaticFilename(calibrateFilenameLabelled)
    model.setCalibrationProperty("leftFlatFoot", leftFlatFoot)
    model.setCalibrationProperty("rightFlatFoot", rightFlatFoot)
    model.setCalibrationProperty("headFlat", headFlat)
    model.setCalibrationProperty("markerDiameter", markerDiameter)

    # --------------------------STATIC CALBRATION--------------------------
    scp = modelFilters.StaticCalibrationProcedure(
        model)  # load calibration procedure

    # ---initial calibration filter----
    # use if all optional mp are zero
    modelFilters.ModelCalibrationFilter(
        scp,
        acqStatic,
        model,
        leftFlatFoot=leftFlatFoot,
        rightFlatFoot=rightFlatFoot,
        headFlat=headFlat,
        markerDiameter=markerDiameter,
    ).compute()

    # ---- Decorators -----
    decorators.applyBasicDecorators(dcm, model, acqStatic, optional_mp,
                                    markerDiameter)
    decorators.applyHJCDecorators(model, hjcMethod)

    # ----Final Calibration filter if model previously decorated -----
    if model.decoratedModel:
        # initial static filter
        modelFilters.ModelCalibrationFilter(
            scp,
            acqStatic,
            model,
            leftFlatFoot=leftFlatFoot,
            rightFlatFoot=rightFlatFoot,
            markerDiameter=markerDiameter,
            headFlat=headFlat,
        ).compute()

    # ----------------------CGM MODELLING----------------------------------
    # ----motion filter----
    # notice : viconCGM1compatible option duplicate error on Construction of the foot coordinate system

    modMotion = modelFilters.ModelMotionFilter(scp,
                                               acqStatic,
                                               model,
                                               enums.motionMethod.Determinist,
                                               markerDiameter=markerDiameter)

    modMotion.compute()

    if "displayCoordinateSystem" in kwargs.keys(
    ) and kwargs["displayCoordinateSystem"]:
        csp = modelFilters.ModelCoordinateSystemProcedure(model)
        csdf = modelFilters.CoordinateSystemDisplayFilter(
            csp, model, acqStatic)
        csdf.setStatic(False)
        csdf.display()

    #---- Joint kinematics----
    # relative angles
    modelFilters.ModelJCSFilter(model, acqStatic).compute(
        description="vectoriel", pointLabelSuffix=pointSuffix)

    # detection of traveling axis + absolute angle
    if model.m_bodypart != enums.BodyPart.UpperLimb:
        longitudinalAxis, forwardProgression, globalFrame = btkTools.findProgressionAxisFromPelvicMarkers(
            acqStatic, ["LASI", "LPSI", "RASI", "RPSI"])
    else:
        longitudinalAxis, forwardProgression, globalFrame = btkTools.findProgressionAxisFromLongAxis(
            acqStatic, "C7", "CLAV")

    if model.m_bodypart != enums.BodyPart.UpperLimb:
        modelFilters.ModelAbsoluteAnglesFilter(
            model,
            acqStatic,
            segmentLabels=["Left Foot", "Right Foot", "Pelvis"],
            angleLabels=["LFootProgress", "RFootProgress", "Pelvis"],
            eulerSequences=["TOR", "TOR", "ROT"],
            globalFrameOrientation=globalFrame,
            forwardProgression=forwardProgression).compute(
                pointLabelSuffix=pointSuffix)

    if model.m_bodypart == enums.BodyPart.LowerLimbTrunk:
        modelFilters.ModelAbsoluteAnglesFilter(
            model,
            acqStatic,
            segmentLabels=["Thorax"],
            angleLabels=["Thorax"],
            eulerSequences=["YXZ"],
            globalFrameOrientation=globalFrame,
            forwardProgression=forwardProgression).compute(
                pointLabelSuffix=pointSuffix)

    if model.m_bodypart == enums.BodyPart.UpperLimb or model.m_bodypart == enums.BodyPart.FullBody:

        modelFilters.ModelAbsoluteAnglesFilter(
            model,
            acqStatic,
            segmentLabels=["Thorax", "Head"],
            angleLabels=["Thorax", "Head"],
            eulerSequences=["YXZ", "TOR"],
            globalFrameOrientation=globalFrame,
            forwardProgression=forwardProgression).compute(
                pointLabelSuffix=pointSuffix)
    # BSP model
    bspModel = bodySegmentParameters.Bsp(model)
    bspModel.compute()

    if model.m_bodypart == enums.BodyPart.FullBody:
        modelFilters.CentreOfMassFilter(
            model, acqStatic).compute(pointLabelSuffix=pointSuffix)

    return model, acqStatic
Example #24
0
    def basicCGM1_manualOffsets(cls):

        MAIN_PATH = pyCGM2.TEST_DATA_PATH + "CGM1\\CGM1-TESTS\\KAD-basic\\"
        staticFilename = "MRI-US-01, 2008-08-08, 3DGA 02.c3d"

        acqStatic = btkTools.smartReader(str(MAIN_PATH + staticFilename))

        model = cgm.CGM1
        model.configure()
        markerDiameter = 14
        mp = {
            'Bodymass': 71.0,
            'LeftLegLength': 860.0,
            'RightLegLength': 865.0,
            'LeftKneeWidth': 102.0,
            'RightKneeWidth': 103.4,
            'LeftAnkleWidth': 75.3,
            'RightAnkleWidth': 72.9,
            'LeftSoleDelta': 0,
            'RightSoleDelta': 0,
        }

        optional_mp = {
            'InterAsisDistance': 0,
            'LeftAsisTrocanterDistance': 0,
            'LeftThighRotation': 8.95843387169,
            'LeftShankRotation': 13.8726086688,
            'LeftTibialTorsion': 5,
            'RightAsisTrocanterDistance': 0,
            'RightThighRotation': -10.0483956768,
            'RightShankRotation': 15.3638957089,
            'RightTibialTorsion': 5
        }

        model.addAnthropoInputParameters(mp, optional=optional_mp)

        # -----------CGM STATIC CALIBRATION--------------------
        scp = modelFilters.StaticCalibrationProcedure(model)
        modelFilters.ModelCalibrationFilter(scp, acqStatic, model).compute()

        # TESTS
        np.testing.assert_equal(model.m_useRightTibialTorsion, True)
        np.testing.assert_equal(model.m_useLeftTibialTorsion, True)

        #        np.testing.assert_almost_equal(model.mp["InterAsisDistance"],model.mp_computed["InterAsisDistance"] , decimal = 3)
        #        np.testing.assert_almost_equal(model.mp["LeftAsisTrocanterDistance"],model.mp_computed["LeftAsisTrocanterDistance"] , decimal = 3)

        np.testing.assert_almost_equal(
            model.mp["LeftThighRotation"],
            -1.0 * model.mp_computed["LeftThighRotationOffset"],
            decimal=3)
        np.testing.assert_almost_equal(
            model.mp["LeftShankRotation"],
            -1.0 * model.mp_computed["LeftShankRotationOffset"],
            decimal=3)
        np.testing.assert_almost_equal(
            model.mp["LeftTibialTorsion"],
            -1.0 * model.mp_computed["LeftTibialTorsionOffset"],
            decimal=3)

        #        np.testing.assert_almost_equal(model.mp["RightAsisTrocanterDistance"],model.mp_computed["RightAsisTrocanterDistance"] , decimal = 3)
        np.testing.assert_almost_equal(
            model.mp["RightThighRotation"],
            model.mp_computed["RightThighRotationOffset"],
            decimal=3)
        np.testing.assert_almost_equal(
            model.mp["RightShankRotation"],
            model.mp_computed["RightShankRotationOffset"],
            decimal=3)
        np.testing.assert_almost_equal(
            model.mp["RightTibialTorsion"],
            model.mp_computed["RightTibialTorsionOffset"],
            decimal=3)
Example #25
0
def fitting(model, DATA_PATH, reconstructFilenameLabelled, translators,
            settings, markerDiameter, pointSuffix, mfpa, momentProjection):

    # --------------------------ACQUISITION ------------------------------------

    # --- btk acquisition ----
    acqGait = btkTools.smartReader(str(DATA_PATH +
                                       reconstructFilenameLabelled))

    btkTools.checkMultipleSubject(acqGait)
    acqGait = btkTools.applyTranslators(acqGait, translators)
    validFrames, vff, vlf = btkTools.findValidFrames(
        acqGait, cgm.CGM1LowerLimbs.TRACKING_MARKERS)

    # --- initial motion Filter ---
    scp = modelFilters.StaticCalibrationProcedure(model)
    modMotion = modelFilters.ModelMotionFilter(scp, acqGait, model,
                                               enums.motionMethod.Determinist)
    modMotion.compute()

    #                        ---OPENSIM IK---

    # --- opensim calibration Filter ---
    osimfile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\osim\\lowerLimb_ballsJoints.osim"  # osimfile
    markersetFile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\settings\\cgm1\\cgm1-markerset.xml"  # markerset
    cgmCalibrationprocedure = opensimFilters.CgmOpensimCalibrationProcedures(
        model)  # procedure

    oscf = opensimFilters.opensimCalibrationFilter(osimfile, model,
                                                   cgmCalibrationprocedure,
                                                   str(DATA_PATH))
    oscf.addMarkerSet(markersetFile)
    scalingOsim = oscf.build()

    # --- opensim Fitting Filter ---
    iksetupFile = pyCGM2.OPENSIM_PREBUILD_MODEL_PATH + "models\\settings\\cgm1\\cgm1-ikSetUp_template.xml"  # ik tool file

    cgmFittingProcedure = opensimFilters.CgmOpensimFittingProcedure(
        model)  # procedure
    cgmFittingProcedure.updateMarkerWeight(
        "LASI", settings["Fitting"]["Weight"]["LASI"])
    cgmFittingProcedure.updateMarkerWeight(
        "RASI", settings["Fitting"]["Weight"]["RASI"])
    cgmFittingProcedure.updateMarkerWeight(
        "LPSI", settings["Fitting"]["Weight"]["LPSI"])
    cgmFittingProcedure.updateMarkerWeight(
        "RPSI", settings["Fitting"]["Weight"]["RPSI"])
    cgmFittingProcedure.updateMarkerWeight(
        "RTHI", settings["Fitting"]["Weight"]["RTHI"])
    cgmFittingProcedure.updateMarkerWeight(
        "RKNE", settings["Fitting"]["Weight"]["RKNE"])
    cgmFittingProcedure.updateMarkerWeight(
        "RTIB", settings["Fitting"]["Weight"]["RTIB"])
    cgmFittingProcedure.updateMarkerWeight(
        "RANK", settings["Fitting"]["Weight"]["RANK"])
    cgmFittingProcedure.updateMarkerWeight(
        "RHEE", settings["Fitting"]["Weight"]["RHEE"])
    cgmFittingProcedure.updateMarkerWeight(
        "RTOE", settings["Fitting"]["Weight"]["RTOE"])
    cgmFittingProcedure.updateMarkerWeight(
        "LTHI", settings["Fitting"]["Weight"]["LTHI"])
    cgmFittingProcedure.updateMarkerWeight(
        "LKNE", settings["Fitting"]["Weight"]["LKNE"])
    cgmFittingProcedure.updateMarkerWeight(
        "LTIB", settings["Fitting"]["Weight"]["LTIB"])
    cgmFittingProcedure.updateMarkerWeight(
        "LANK", settings["Fitting"]["Weight"]["LANK"])
    cgmFittingProcedure.updateMarkerWeight(
        "LHEE", settings["Fitting"]["Weight"]["LHEE"])
    cgmFittingProcedure.updateMarkerWeight(
        "LTOE", settings["Fitting"]["Weight"]["LTOE"])

    osrf = opensimFilters.opensimFittingFilter(iksetupFile, scalingOsim,
                                               cgmFittingProcedure,
                                               str(DATA_PATH))

    logging.info("-------INVERSE KINEMATICS IN PROGRESS----------")
    acqIK = osrf.run(acqGait, str(DATA_PATH + reconstructFilenameLabelled))
    logging.info("-------INVERSE KINEMATICS DONE-----------------")

    # --- final pyCGM2 model motion Filter ---
    # use fitted markers
    modMotionFitted = modelFilters.ModelMotionFilter(
        scp,
        acqIK,
        model,
        enums.motionMethod.Determinist,
        markerDiameter=markerDiameter)

    modMotionFitted.compute()

    #---- Joint kinematics----
    # relative angles
    modelFilters.ModelJCSFilter(model,
                                acqIK).compute(description="vectoriel",
                                               pointLabelSuffix=pointSuffix)

    # detection of traveling axis
    longitudinalAxis, forwardProgression, globalFrame = btkTools.findProgressionAxisFromPelvicMarkers(
        acqIK, ["LASI", "LPSI", "RASI", "RPSI"])

    # absolute angles
    modelFilters.ModelAbsoluteAnglesFilter(
        model,
        acqIK,
        segmentLabels=["Left Foot", "Right Foot", "Pelvis"],
        angleLabels=["LFootProgress", "RFootProgress", "Pelvis"],
        eulerSequences=["TOR", "TOR", "ROT"],
        globalFrameOrientation=globalFrame,
        forwardProgression=forwardProgression).compute(
            pointLabelSuffix=pointSuffix)

    #---- Body segment parameters----
    bspModel = bodySegmentParameters.Bsp(model)
    bspModel.compute()

    # --- force plate handling----
    # find foot  in contact
    mappedForcePlate = forceplates.matchingFootSideOnForceplate(acqIK)
    forceplates.addForcePlateGeneralEvents(acqIK, mappedForcePlate)
    logging.info("Force plate assignment : %s" % mappedForcePlate)

    if mfpa is not None:
        if len(mfpa) != len(mappedForcePlate):
            raise Exception(
                "[pyCGM2] manual force plate assignment badly sets. Wrong force plate number. %s force plate require"
                % (str(len(mappedForcePlate))))
        else:
            mappedForcePlate = mfpa
            forceplates.addForcePlateGeneralEvents(acqIK, mappedForcePlate)
            logging.warning("Manual Force plate assignment : %s" %
                            mappedForcePlate)

    # assembly foot and force plate
    modelFilters.ForcePlateAssemblyFilter(
        model,
        acqIK,
        mappedForcePlate,
        leftSegmentLabel="Left Foot",
        rightSegmentLabel="Right Foot").compute()

    #---- Joint kinetics----
    idp = modelFilters.CGMLowerlimbInverseDynamicProcedure()
    modelFilters.InverseDynamicFilter(
        model, acqIK, procedure=idp,
        projection=momentProjection).compute(pointLabelSuffix=pointSuffix)

    #---- Joint energetics----
    modelFilters.JointPowerFilter(model,
                                  acqIK).compute(pointLabelSuffix=pointSuffix)

    #---- zero unvalid frames ---
    btkTools.applyValidFramesOnOutput(acqIK, validFrames)

    return acqIK