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
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
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)
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
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
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
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")
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)
'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))
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")
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])
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")
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)
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")
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")
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")
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")
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
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")
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
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
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")
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
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)
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