def test_functions(self): filename = pyCGM2.TEST_DATA_PATH + "LowLevel\\IO\\Hånnibøl_c3d\\gait1.c3d" acq = btkTools.smartReader(filename, translators=None) btkTools.GetMarkerNames(acq) btkTools.findNearestMarker(acq, 0, "LASI") btkTools.GetAnalogNames(acq) btkTools.isGap(acq, "LASI") btkTools.findMarkerGap(acq) btkTools.isPointExist(acq, "LASI") btkTools.isPointsExist(acq, ["LASI", "RASI"]) btkTools.clearPoints(acq, ["LASI", "RASI"]) btkTools.checkFirstAndLastFrame(acq, "LASI") btkTools.isGap_inAcq(acq, ["LASI", "RASI"]) btkTools.findValidFrames(acq, ["LASI", "RASI"]) btkTools.checkMultipleSubject(acq) btkTools.checkMarkers(acq, ["LASI", "RASI"]) btkTools.clearEvents(acq, ["Foot Strike"]) btkTools.modifyEventSubject(acq, "Hän") btkTools.modifySubject(acq, "Han") btkTools.getVisibleMarkersAtFrame(acq, ["LASI", "RASI"], 0) btkTools.isAnalogExist(acq, "emg-Hän") btkTools.createZeros(acq, ["LASI", "RASI"]) btkTools.constructEmptyMarker(acq, "zéros", desc="Hän") btkTools.getStartEndEvents(acq, "Left") btkTools.changeSubjectName(acq, "Hän") btkTools.smartGetMetadata(acq, "SUBJECTS", "USED") btkTools.smartSetMetadata(acq, "SUBJECTS", "USED", 0, "Hän")
def gaitTrialProgressionY_forward_lateralX(cls): """ """ MAIN_PATH = pyCGM2.TEST_DATA_PATH + "operations\\progression\\" gaitFilename = "gait_Y_forward.c3d" acq = btkTools.smartReader(str(MAIN_PATH + gaitFilename)) valSACR = (acq.GetPoint("LPSI").GetValues() + acq.GetPoint("RPSI").GetValues()) / 2.0 btkTools.smartAppendPoint(acq, "SACR", valSACR, desc="") valMidAsis = (acq.GetPoint("LASI").GetValues() + acq.GetPoint("RASI").GetValues()) / 2.0 btkTools.smartAppendPoint(acq, "midASIS", valMidAsis, desc="") validFrames, vff, vlf = btkTools.findValidFrames( acq, ["LPSI", "LASI", "RPSI"]) longitudinalAxis, forwardProgression, globalFrame = btkTools.findProgression( acq, "LASI") np.testing.assert_equal(longitudinalAxis, "Y") np.testing.assert_equal(forwardProgression, True) np.testing.assert_equal(globalFrame, "YXZ")
def detectSide(acq, left_markerLabel, right_markerLabel): flag, vff, vlf = btkTools.findValidFrames( acq, [left_markerLabel, right_markerLabel]) left = acq.GetPoint(left_markerLabel).GetValues()[vff:vlf, 2] right = acq.GetPoint(right_markerLabel).GetValues()[vff:vlf, 2] side = "Left" if np.max(left) > np.max(right) else "Right" return side
def test_FullBody_noOptions(self): DATA_PATH = MAIN_PATH = pyCGM2.TEST_DATA_PATH + "LowLevel\\uncropped data\\cgm1\\" staticFilename = "static.c3d" DATA_PATH_OUT = pyCGM2.TEST_DATA_PATH_OUT+"LowLevel\\uncropped data\\cgm1\\" files.createDir(DATA_PATH_OUT) markerDiameter=14 leftFlatFoot = True rightFlatFoot = True headStraight = True pointSuffix = "" vskFile = vskTools.getVskFiles(DATA_PATH) vsk = vskTools.Vsk(DATA_PATH + "New Subject.vsk") required_mp,optional_mp = vskTools.getFromVskSubjectMp(vsk, resetFlag=True) model,finalAcqStatic = cgm1.calibrate(DATA_PATH, staticFilename, None, required_mp, optional_mp, leftFlatFoot, rightFlatFoot, headStraight, markerDiameter, pointSuffix, displayCoordinateSystem=True) # btkTools.smartWriter(finalAcqStatic, str( staticFilename[:-4]+"-pyCGM2modelled.c3d")) # logging.info("Static Calibration -----> Done") gaitFilename="gait1.c3d" acqGait0 = btkTools.smartReader(DATA_PATH + gaitFilename) trackingMarkers = model.getTrackingMarkers(acqGait0) validFrames,vff,vlf = btkTools.findValidFrames(acqGait0,trackingMarkers) mfpa = None reconstructFilenameLabelled = gaitFilename acqGait = cgm1.fitting(model,DATA_PATH, reconstructFilenameLabelled, None, markerDiameter, pointSuffix, mfpa, enums.MomentProjection.Proximal, displayCoordinateSystem=True) btkTools.smartWriter(acqGait, DATA_PATH_OUT+"//gait1-processed.c3d")
def fitting(model,DATA_PATH, reconstructFilenameLabelled, translators,weights, ik_flag,markerDiameter, pointSuffix, mfpa, momentProjection,**kwargs): """ Fitting of the CGM2.3 :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 """ if "Fitting" in weights.keys(): weights = weights["Fitting"]["Weight"] # --------------------------ACQ WITH TRANSLATORS -------------------------------------- # --- 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" logging.info("[pyCGM2] Sacrum marker detected") acqGait = btkTools.applyTranslators(acqGait,translators) trackingMarkers = model.getTrackingMarkers(acqGait) validFrames,vff,vlf = btkTools.findValidFrames(acqGait,trackingMarkers) # 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) # section to remove : - copy motion of ProximalShank from Shank with Sodervisk modMotion=modelFilters.ModelMotionFilter(scp,acqGait,model,enums.motionMethod.Sodervisk) modMotion.compute() # /section to remove if model.getBodyPart() == enums.BodyPart.UpperLimb: ik_flag = False logging.warning("[pyCGM2] Fitting only applied for the upper limb") 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_3\\cgm2_3-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_3\\cgm2_3-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"]) osrf = opensimFilters.opensimFittingFilter(iksetupFile, scalingOsim, cgmFittingProcedure, (DATA_PATH) ) logging.info("-------INVERSE KINEMATICS IN PROGRESS----------") acqIK = osrf.run(acqGait,(DATA_PATH + reconstructFilenameLabelled )) logging.info("-------INVERSE KINEMATICS DONE-----------------") # 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) 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) # detection of traveling axis + absolute angle if model.m_bodypart != enums.BodyPart.UpperLimb: pfp = progressionFrame.PelvisProgressionFrameProcedure() else: pfp = progressionFrame.ThoraxProgressionFrameProcedure() pff = progressionFrame.ProgressionFrameFilter(finalAcqGait,pfp) pff.compute() globalFrame = pff.outputs["globalFrame"] forwardProgression = pff.outputs["forwardProgression"] if model.m_bodypart != enums.BodyPart.UpperLimb: modelFilters.ModelAbsoluteAnglesFilter(model,finalAcqGait, 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,finalAcqGait, 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,finalAcqGait, 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,finalAcqGait).compute(pointLabelSuffix=pointSuffix) # Inverse dynamics if btkTools.checkForcePlateExist(acqGait): if model.m_bodypart != enums.BodyPart.UpperLimb: # --- force plate handling---- # find foot in contact mappedForcePlate = forceplates.matchingFootSideOnForceplate(finalAcqGait,mfpa=mfpa) forceplates.addForcePlateGeneralEvents(finalAcqGait,mappedForcePlate) logging.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.applyValidFramesOnOutput(finalAcqGait,validFrames) return finalAcqGait
def calibration2Dof(model, DATA_PATH, reconstructFilenameLabelled, translators, side, beginFrame, endFrame, jointRange, **kwargs): # --- btk acquisition ---- if "forceBtkAcq" in kwargs.keys(): acqFunc = kwargs["forceBtkAcq"] else: acqFunc = btkTools.smartReader( (DATA_PATH + reconstructFilenameLabelled)) btkTools.checkMultipleSubject(acqFunc) acqFunc = btkTools.applyTranslators(acqFunc, translators) # filtering # ----------------------- if "fc_lowPass_marker" in kwargs.keys( ) and kwargs["fc_lowPass_marker"] != 0: trackingMarkers = model.getTrackingMarkers(acqFunc) fc = kwargs["fc_lowPass_marker"] order = 4 if "order_lowPass_marker" in kwargs.keys(): order = kwargs["order_lowPass_marker"] signal_processing.markerFiltering(acqFunc, trackingMarkers, order=order, fc=fc) #---get frame range of interest--- ff = acqFunc.GetFirstFrame() lf = acqFunc.GetLastFrame() # motion if side is None: side = detectSide(acqFunc, "LANK", "RANK") LOGGER.logger.info("Detected motion side : %s" % (side)) start, end = btkTools.getStartEndEvents(acqFunc, side) if start is not None: LOGGER.logger.info("Start event detected") initFrame = start else: initFrame = beginFrame if beginFrame is not None else ff if end is not None: LOGGER.logger.info("End event detected") endFrame = end else: endFrame = endFrame if endFrame is not None else lf iff = initFrame - ff ilf = endFrame - ff if model.version in ["CGM1.0", "CGM1.1", "CGM2.1", "CGM2.2"]: validFrames, vff, vlf = btkTools.findValidFrames( acqFunc, cgm.CGM1.LOWERLIMB_TRACKING_MARKERS) # --------------------------RESET OF THE STATIC File--------- # load btkAcq from static file staticFilename = model.m_staticFilename acqStatic = btkTools.smartReader((DATA_PATH + staticFilename)) btkTools.checkMultipleSubject(acqStatic) acqStatic = btkTools.applyTranslators(acqStatic, translators) # initial calibration ( i.e calibration from Calibration operation) leftFlatFoot = model.m_properties["CalibrationParameters"]["leftFlatFoot"] rightFlatFoot = model.m_properties["CalibrationParameters"][ "rightFlatFoot"] headFlat = model.m_properties["CalibrationParameters"]["headFlat"] markerDiameter = model.m_properties["CalibrationParameters"][ "markerDiameter"] if side == "Left": # remove other functional calibration model.mp_computed["LeftKneeFuncCalibrationOffset"] = 0 if side == "Right": # remove other functional calibration model.mp_computed["RightKneeFuncCalibrationOffset"] = 0 # no rotation on both thigh - re init anatonical frame scp = modelFilters.StaticCalibrationProcedure(model) modelFilters.ModelCalibrationFilter( scp, acqStatic, model, leftFlatFoot=leftFlatFoot, rightFlatFoot=rightFlatFoot, headFlat=headFlat, markerDiameter=markerDiameter).compute() 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", "CGM2.5"]: if side == "Left": thigh_markers = model.getSegment("Left Thigh").m_tracking_markers shank_markers = model.getSegment("Left Shank").m_tracking_markers elif side == "Right": thigh_markers = model.getSegment("Right Thigh").m_tracking_markers shank_markers = model.getSegment("Right Shank").m_tracking_markers validFrames, vff, vlf = btkTools.findValidFrames( acqFunc, thigh_markers + shank_markers) proximalSegmentLabel = (side + " Thigh") distalSegmentLabel = (side + " Shank") # Motion modMotion = modelFilters.ModelMotionFilter( scp, acqFunc, model, enums.motionMethod.Sodervisk) modMotion.segmentalCompute([proximalSegmentLabel, distalSegmentLabel]) # calibration decorators modelDecorator.KneeCalibrationDecorator(model).calibrate2dof( side, indexFirstFrame=iff, indexLastFrame=ilf, jointRange=jointRange) # --------------------------FINAL CALIBRATION OF THE STATIC File--------- # ---- Calibration modelFilters.ModelCalibrationFilter( scp, acqStatic, model, leftFlatFoot=leftFlatFoot, rightFlatFoot=rightFlatFoot, headFlat=headFlat, markerDiameter=markerDiameter).compute() return model, acqFunc, side
def fitting(model, DATA_PATH, reconstructFilenameLabelled, translators, markerDiameter, pointSuffix, mfpa, momentProjection, **kwargs): """ Fitting of the CGM1.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( (DATA_PATH + reconstructFilenameLabelled)) btkTools.checkMultipleSubject(acqGait) if btkTools.isPointExist(acqGait, "SACR"): translators["LPSI"] = "SACR" translators["RPSI"] = "SACR" logging.info("[pyCGM2] Sacrum marker detected") acqGait = btkTools.applyTranslators(acqGait, translators) trackingMarkers = model.getTrackingMarkers(acqGait) validFrames, vff, vlf = btkTools.findValidFrames(acqGait, trackingMarkers) # 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) 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() if "NaimKneeCorrection" in kwargs.keys() and kwargs["NaimKneeCorrection"]: # Apply Naim 2019 method if type(kwargs["NaimKneeCorrection"]) is float: nmacp = modelFilters.Naim2019ThighMisaligmentCorrectionProcedure( model, "Both", threshold=(kwargs["NaimKneeCorrection"])) else: nmacp = modelFilters.Naim2019ThighMisaligmentCorrectionProcedure( model, "Both") mmcf = modelFilters.ModelMotionCorrectionFilter(nmacp) mmcf.correct() # btkTools.smartAppendPoint(acqGait,"LNaim",mmcf.m_procedure.m_virtual["Left"]) # btkTools.smartAppendPoint(acqGait,"RNaim",mmcf.m_procedure.m_virtual["Right"]) #---- 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: pfp = progressionFrame.PelvisProgressionFrameProcedure() else: pfp = progressionFrame.ThoraxProgressionFrameProcedure() pff = progressionFrame.ProgressionFrameFilter(acqGait, pfp) pff.compute() globalFrame = pff.outputs["globalFrame"] forwardProgression = pff.outputs["forwardProgression"] 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 btkTools.checkForcePlateExist(acqGait): 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( pointLabelSuffix=pointSuffix) #---- Joint kinetics---- idp = modelFilters.CGMLowerlimbInverseDynamicProcedure() modelFilters.InverseDynamicFilter( model, acqGait, procedure=idp, projection=momentProjection, globalFrameOrientation=globalFrame, forwardProgression=forwardProgression).compute( pointLabelSuffix=pointSuffix) #---- Joint energetics---- modelFilters.JointPowerFilter( model, acqGait).compute(pointLabelSuffix=pointSuffix) #---- zero unvalid frames --- btkTools.applyValidFramesOnOutput(acqGait, validFrames) return acqGait
def sara(model, DATA_PATH, reconstructFilenameLabelled, translators, side, beginFrame, endFrame, **kwargs): # --- btk acquisition ---- if "forceBtkAcq" in kwargs.keys(): acqFunc = kwargs["forceBtkAcq"] else: acqFunc = btkTools.smartReader( str(DATA_PATH + reconstructFilenameLabelled)) btkTools.checkMultipleSubject(acqFunc) acqFunc = btkTools.applyTranslators(acqFunc, translators) #---get frame range of interest--- ff = acqFunc.GetFirstFrame() lf = acqFunc.GetLastFrame() start, end = btkTools.getStartEndEvents(acqFunc, side) if start is not None: logging.info("Start event detected") initFrame = start else: initFrame = beginFrame if beginFrame is not None else ff if end is not None: logging.info("End event detected") endFrame = end else: endFrame = endFrame if endFrame is not None else lf iff = initFrame - ff ilf = endFrame - ff #---motion side of the lower limb--- if side is None: side = detectSide(acqFunc, "LANK", "RANK") logging.info("Detected motion side : %s" % (side)) # --------------------------RESET OF THE STATIC File--------- # load btkAcq from static file staticFilename = model.m_staticFilename acqStatic = btkTools.smartReader(str(DATA_PATH + staticFilename)) btkTools.checkMultipleSubject(acqStatic) acqStatic = btkTools.applyTranslators(acqStatic, translators) # initial calibration ( i.e calibration from Calibration operation) leftFlatFoot = model.m_properties["CalibrationParameters"]["leftFlatFoot"] rightFlatFoot = model.m_properties["CalibrationParameters"][ "rightFlatFoot"] markerDiameter = model.m_properties["CalibrationParameters"][ "markerDiameter"] headFlat = model.m_properties["CalibrationParameters"]["headFlat"] if side == "Left": model.mp_computed["LeftKneeFuncCalibrationOffset"] = 0 if side == "Right": model.mp_computed["RightKneeFuncCalibrationOffset"] = 0 # initial calibration ( zero previous KneeFunc offset on considered side ) scp = modelFilters.StaticCalibrationProcedure(model) modelFilters.ModelCalibrationFilter( scp, acqStatic, model, leftFlatFoot=leftFlatFoot, rightFlatFoot=rightFlatFoot, headFlat=headFlat, markerDiameter=markerDiameter).compute() if model.version in ["CGM2.3", "CGM2.4", "CGM2.5"]: if side == "Left": thigh_markers = model.getSegment("Left Thigh").m_tracking_markers shank_markers = model.getSegment("Left Shank").m_tracking_markers elif side == "Right": thigh_markers = model.getSegment("Right Thigh").m_tracking_markers shank_markers = model.getSegment("Right Shank").m_tracking_markers validFrames, vff, vlf = btkTools.findValidFrames( acqFunc, thigh_markers + shank_markers) proximalSegmentLabel = str(side + " Thigh") distalSegmentLabel = str(side + " Shank") # segment Motion modMotion = modelFilters.ModelMotionFilter( scp, acqFunc, model, enums.motionMethod.Sodervisk) modMotion.segmentalCompute([proximalSegmentLabel, distalSegmentLabel]) # decorator modelDecorator.KneeCalibrationDecorator(model).sara( side, indexFirstFrame=iff, indexLastFrame=ilf) # --------------------------FINAL CALIBRATION OF THE STATIC File--------- modelFilters.ModelCalibrationFilter( scp, acqStatic, model, leftFlatFoot=leftFlatFoot, rightFlatFoot=rightFlatFoot, headFlat=headFlat, markerDiameter=markerDiameter).compute() return model, acqFunc, side
def calibrate(DATA_PATH,calibrateFilenameLabelled,translators,settings, required_mp,optional_mp, ik_flag,leftFlatFoot,rightFlatFoot,markerDiameter,hjcMethod, pointSuffix): # ---btk acquisition--- acqStatic = btkTools.smartReader(str(DATA_PATH+calibrateFilenameLabelled)) btkTools.checkMultipleSubject(acqStatic) acqStatic = btkTools.applyTranslators(acqStatic,translators) validFrames,vff,vlf = btkTools.findValidFrames(acqStatic,cgm2.CGM2_4LowerLimbs.TRACKING_MARKERS) # --------------------------MODEL-------------------------------------- # ---definition--- model=cgm2.CGM2_4LowerLimbs() 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.Sodervisk, 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\\cgm2_4\\cgm2_4-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\\cgm2_4\\cgm2_4-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"]) cgmFittingProcedure.updateMarkerWeight("LTHAP",settings["Fitting"]["Weight"]["LTHAP"]) cgmFittingProcedure.updateMarkerWeight("LTHAD",settings["Fitting"]["Weight"]["LTHAD"]) cgmFittingProcedure.updateMarkerWeight("LTIAP",settings["Fitting"]["Weight"]["LTIAP"]) cgmFittingProcedure.updateMarkerWeight("LTIAD",settings["Fitting"]["Weight"]["LTIAD"]) cgmFittingProcedure.updateMarkerWeight("RTHAP",settings["Fitting"]["Weight"]["RTHAP"]) cgmFittingProcedure.updateMarkerWeight("RTHAD",settings["Fitting"]["Weight"]["RTHAD"]) cgmFittingProcedure.updateMarkerWeight("RTIAP",settings["Fitting"]["Weight"]["RTIAP"]) cgmFittingProcedure.updateMarkerWeight("RTIAD",settings["Fitting"]["Weight"]["RTIAD"]) cgmFittingProcedure.updateMarkerWeight("LSMH",settings["Fitting"]["Weight"]["LSMH"]) cgmFittingProcedure.updateMarkerWeight("LFMH",settings["Fitting"]["Weight"]["LFMH"]) cgmFittingProcedure.updateMarkerWeight("LVMH",settings["Fitting"]["Weight"]["LVMH"]) cgmFittingProcedure.updateMarkerWeight("RSMH",settings["Fitting"]["Weight"]["RSMH"]) cgmFittingProcedure.updateMarkerWeight("RFMH",settings["Fitting"]["Weight"]["RFMH"]) cgmFittingProcedure.updateMarkerWeight("RVMH",settings["Fitting"]["Weight"]["RVMH"]) # cgmFittingProcedure.updateMarkerWeight("LTHL",settings["Fitting"]["Weight"]["LTHL"]) # cgmFittingProcedure.updateMarkerWeight("LTHLD",settings["Fitting"]["Weight"]["LTHLD"]) # cgmFittingProcedure.updateMarkerWeight("LPAT",settings["Fitting"]["Weight"]["LPAT"]) # cgmFittingProcedure.updateMarkerWeight("LTIBL",settings["Fitting"]["Weight"]["LTIBL"]) # cgmFittingProcedure.updateMarkerWeight("RTHL",settings["Fitting"]["Weight"]["RTHL"]) # cgmFittingProcedure.updateMarkerWeight("RTHLD",settings["Fitting"]["Weight"]["RTHLD"]) # cgmFittingProcedure.updateMarkerWeight("RPAT",settings["Fitting"]["Weight"]["RPAT"]) # cgmFittingProcedure.updateMarkerWeight("RTIBL",settings["Fitting"]["Weight"]["RTIBL"]) osrf = opensimFilters.opensimFittingFilter(iksetupFile, scalingOsim, cgmFittingProcedure, str(DATA_PATH) ) acqStaticIK = osrf.run(acqStatic,str(DATA_PATH + calibrateFilenameLabelled )) # 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() #---- 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, ik_flag,markerDiameter, pointSuffix, mfpa, momentProjection): # --- btk acquisition ---- acqGait = btkTools.smartReader(str(DATA_PATH + reconstructFilenameLabelled)) btkTools.checkMultipleSubject(acqGait) acqGait = btkTools.applyTranslators(acqGait,translators) validFrames,vff,vlf = btkTools.findValidFrames(acqGait,cgm2.CGM2_4LowerLimbs.TRACKING_MARKERS) # --- initial motion Filter --- scp=modelFilters.StaticCalibrationProcedure(model) modMotion=modelFilters.ModelMotionFilter(scp,acqGait,model,enums.motionMethod.Sodervisk) 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\\cgm2_4\\cgm2_4-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\\cgm2_4\\cgm2_4-ikSetUp_template.xml" # ik tl 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"]) cgmFittingProcedure.updateMarkerWeight("LTHAP",settings["Fitting"]["Weight"]["LTHAP"]) cgmFittingProcedure.updateMarkerWeight("LTHAD",settings["Fitting"]["Weight"]["LTHAD"]) cgmFittingProcedure.updateMarkerWeight("LTIAP",settings["Fitting"]["Weight"]["LTIAP"]) cgmFittingProcedure.updateMarkerWeight("LTIAD",settings["Fitting"]["Weight"]["LTIAD"]) cgmFittingProcedure.updateMarkerWeight("RTHAP",settings["Fitting"]["Weight"]["RTHAP"]) cgmFittingProcedure.updateMarkerWeight("RTHAD",settings["Fitting"]["Weight"]["RTHAD"]) cgmFittingProcedure.updateMarkerWeight("RTIAP",settings["Fitting"]["Weight"]["RTIAP"]) cgmFittingProcedure.updateMarkerWeight("RTIAD",settings["Fitting"]["Weight"]["RTIAD"]) cgmFittingProcedure.updateMarkerWeight("LSMH",settings["Fitting"]["Weight"]["LSMH"]) cgmFittingProcedure.updateMarkerWeight("LFMH",settings["Fitting"]["Weight"]["LFMH"]) cgmFittingProcedure.updateMarkerWeight("LVMH",settings["Fitting"]["Weight"]["LVMH"]) cgmFittingProcedure.updateMarkerWeight("RSMH",settings["Fitting"]["Weight"]["RSMH"]) cgmFittingProcedure.updateMarkerWeight("RFMH",settings["Fitting"]["Weight"]["RFMH"]) cgmFittingProcedure.updateMarkerWeight("RVMH",settings["Fitting"]["Weight"]["RVMH"]) # cgmFittingProcedure.updateMarkerWeight("LTHL",settings["Fitting"]["Weight"]["LTHL"]) # cgmFittingProcedure.updateMarkerWeight("LTHLD",settings["Fitting"]["Weight"]["LTHLD"]) # cgmFittingProcedure.updateMarkerWeight("LPAT",settings["Fitting"]["Weight"]["LPAT"]) # cgmFittingProcedure.updateMarkerWeight("LTIBL",settings["Fitting"]["Weight"]["LTIBL"]) # cgmFittingProcedure.updateMarkerWeight("RTHL",settings["Fitting"]["Weight"]["RTHL"]) # cgmFittingProcedure.updateMarkerWeight("RTHLD",settings["Fitting"]["Weight"]["RTHLD"]) # cgmFittingProcedure.updateMarkerWeight("RPAT",settings["Fitting"]["Weight"]["RPAT"]) # cgmFittingProcedure.updateMarkerWeight("RTIBL",settings["Fitting"]["Weight"]["RTIBL"]) 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-----------------") # 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) modMotionFitted.compute() #---- Joint kinematics---- # relative angles modelFilters.ModelJCSFilter(model,finalAcqGait).compute(description="vectoriel", pointLabelSuffix=pointSuffix) # detection of traveling axis longitudinalAxis,forwardProgression,globalFrame = btkTools.findProgressionAxisFromPelvicMarkers(finalAcqGait,["LASI","LPSI","RASI","RPSI"]) # absolute angles modelFilters.ModelAbsoluteAnglesFilter(model,finalAcqGait, 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(finalAcqGait) forceplates.addForcePlateGeneralEvents(finalAcqGait,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(finalAcqGait,mappedForcePlate) logging.warning("Manual Force plate assignment : %s" %mappedForcePlate) # assembly foot and force plate modelFilters.ForcePlateAssemblyFilter(model,finalAcqGait,mappedForcePlate, leftSegmentLabel="Left Foot", rightSegmentLabel="Right Foot").compute() #---- Joint kinetics---- idp = modelFilters.CGMLowerlimbInverseDynamicProcedure() modelFilters.InverseDynamicFilter(model, finalAcqGait, procedure = idp, projection = momentProjection ).compute(pointLabelSuffix=pointSuffix) #---- Joint energetics---- modelFilters.JointPowerFilter(model,finalAcqGait).compute(pointLabelSuffix=pointSuffix) #---- zero unvalid frames --- btkTools.applyValidFramesOnOutput(finalAcqGait,validFrames) return finalAcqGait
def fitting(model, DATA_PATH, reconstructFilenameLabelled, translators, 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) scp = modelFilters.StaticCalibrationProcedure(model) # ---Motion filter---- modMotion = modelFilters.ModelMotionFilter(scp, acqGait, model, enums.motionMethod.Determinist, markerDiameter=markerDiameter) modMotion.compute() #---- Joint kinematics---- # relative angles modelFilters.ModelJCSFilter(model, acqGait).compute(description="vectoriel", pointLabelSuffix=pointSuffix) # detection of traveling axis longitudinalAxis, forwardProgression, globalFrame = btkTools.findProgressionAxisFromPelvicMarkers( acqGait, ["LASI", "LPSI", "RASI", "RPSI"]) # absolute angles 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) #---- Body segment parameters---- bspModel = bodySegmentParameters.Bsp(model) bspModel.compute() # --- force plate handling---- # find foot in contact mappedForcePlate = forceplates.matchingFootSideOnForceplate(acqGait) forceplates.addForcePlateGeneralEvents(acqGait, mappedForcePlate) logging.info("Automatic 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(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 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 """ # --------------------------ACQUISITION ------------------------------------ if "forceBtkAcq" in kwargs.keys(): acqGait = kwargs["forceBtkAcq"] else: # --- btk acquisition ---- 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) # procedure # ---Motion filter---- modMotion = modelFilters.ModelMotionFilter(scp, acqGait, model, enums.motionMethod.Determinist, markerDiameter=markerDiameter, viconCGM1compatible=True) 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", "TOR"], 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() #---- CentreOfMass---- 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, viconCGM1compatible=True).compute(pointLabelSuffix=pointSuffix) #---- Joint energetics---- modelFilters.JointPowerFilter( model, acqGait).compute(pointLabelSuffix=pointSuffix) #---- zero unvalid frames --- btkTools.applyValidFramesOnOutput(acqGait, validFrames) return acqGait
def compute(self, acq): if not btkTools.isPointExist(acq, self.m_marker): raise Exception("[pyCGM2] : marker %s doesn't exist" % (self.m_marker)) # find valid frames and get the first one flag, vff, vlf = btkTools.findValidFrames(acq, [self.m_marker]) values = acq.GetPoint(utils.str(self.m_marker)).GetValues()[vff:vlf, :] MaxValues = [ values[-1, 0] - values[0, 0], values[-1, 1] - values[0, 1] ] absMaxValues = [ np.abs(values[-1, 0] - values[0, 0]), np.abs(values[-1, 1] - values[0, 1]) ] ind = np.argmax(absMaxValues) if absMaxValues[ind] > self.__threshold: logging.debug( "progression axis detected from displacement of the marker (%s)" % (self.m_marker)) diff = MaxValues[ind] if ind == 0: progressionAxis = "X" lateralAxis = "Y" else: progressionAxis = "Y" lateralAxis = "X" forwardProgression = True if diff > 0 else False globalFrame = (progressionAxis + lateralAxis + "Z") else: logging.debug( "progression axis detected from pelvis longitudinal axis") for marker in self.m_frontmarkers + self.m_backmarkers: if not btkTools.isPointExist(acq, marker): raise Exception("[pyCGM2] : marker %s doesn't exist" % (marker)) # find valid frames and get the first one flag, vff, vlf = btkTools.findValidFrames( acq, self.m_frontmarkers + self.m_backmarkers) index = vff # barycentres values = np.zeros((acq.GetPointFrameNumber(), 3)) count = 0 for marker in self.m_frontmarkers: values = values + acq.GetPoint(marker).GetValues() count += 1 frontValues = values / count values = np.zeros((acq.GetPointFrameNumber(), 3)) count = 0 for marker in self.m_backmarkers: values = values + acq.GetPoint(utils.str(marker)).GetValues() count += 1 backValues = values / count # axes back = backValues[index, :] front = frontValues[index, :] front[2] = back[ 2] # allow to avoid detecting Z axis if pelvs anterior axis point dowwnward z = np.array([0, 0, 1]) a1 = (front - back) a1 = a1 / np.linalg.norm(a1) a2 = np.cross(a1, z) a2 = a2 / np.linalg.norm(a2) globalAxes = { "X": np.array([1, 0, 0]), "Y": np.array([0, 1, 0]), "Z": np.array([0, 0, 1]) } # longitudinal axis tmp = [] for axis in globalAxes.keys(): res = np.dot(a1, globalAxes[axis]) tmp.append(res) maxIndex = np.argmax(np.abs(tmp)) progressionAxis = globalAxes.keys()[maxIndex] forwardProgression = True if tmp[maxIndex] > 0 else False # lateral axis tmp = [] for axis in globalAxes.keys(): res = np.dot(a2, globalAxes[axis]) tmp.append(res) maxIndex = np.argmax(np.abs(tmp)) lateralAxis = globalAxes.keys()[maxIndex] # global frame if "X" not in (progressionAxis + lateralAxis): globalFrame = (progressionAxis + lateralAxis + "X") if "Y" not in (progressionAxis + lateralAxis): globalFrame = (progressionAxis + lateralAxis + "Y") if "Z" not in (progressionAxis + lateralAxis): globalFrame = (progressionAxis + lateralAxis + "Z") logging.info("Progression axis : %s" % (progressionAxis)) logging.info("forwardProgression : %s" % ((forwardProgression))) logging.info("globalFrame : %s" % ((globalFrame))) return progressionAxis, forwardProgression, globalFrame
def calibration2Dof(model, DATA_PATH, reconstructFilenameLabelled, translators, side, beginFrame, endFrame, jointRange): acqFunc = btkTools.smartReader(str(DATA_PATH + reconstructFilenameLabelled)) btkTools.checkMultipleSubject(acqFunc) acqFunc = btkTools.applyTranslators(acqFunc, translators) #---get frame range of interest--- ff = acqFunc.GetFirstFrame() lf = acqFunc.GetLastFrame() initFrame = beginFrame if beginFrame is not None else ff endFrame = endFrame if endFrame is not None else lf iff = initFrame - ff ilf = endFrame - ff # motion if side is None: side = detectSide(acqFunc, "LANK", "RANK") logging.info("Detected motion side : %s" % (side)) if model.version in ["CGM1.0", "CGM1.1", "CGM2.1", "CGM2.2", "CGM2.2e"]: validFrames, vff, vlf = btkTools.findValidFrames( acqFunc, cgm.CGM1LowerLimbs.TRACKING_MARKERS) # --------------------------RESET OF THE STATIC File--------- # load btkAcq from static file staticFilename = model.m_staticFilename acqStatic = btkTools.smartReader(str(DATA_PATH + staticFilename)) btkTools.checkMultipleSubject(acqStatic) acqStatic = btkTools.applyTranslators(acqStatic, translators) # initial calibration ( i.e calibration from Calibration operation) leftFlatFoot = model.m_properties["CalibrationParameters"]["leftFlatFoot"] rightFlatFoot = model.m_properties["CalibrationParameters"][ "rightFlatFoot"] markerDiameter = model.m_properties["CalibrationParameters"][ "markerDiameter"] if side == "Left": # remove other functional calibration model.mp_computed["LeftKneeFuncCalibrationOffset"] = 0 if side == "Right": # remove other functional calibration model.mp_computed["RightKneeFuncCalibrationOffset"] = 0 # no rotation on both thigh - re init anatonical frame scp = modelFilters.StaticCalibrationProcedure(model) modelFilters.ModelCalibrationFilter( scp, acqStatic, model, leftFlatFoot=leftFlatFoot, rightFlatFoot=rightFlatFoot, markerDiameter=markerDiameter).compute() if model.version in ["CGM1.0", "CGM1.1", "CGM2.1", "CGM2.2", "CGM2.2e"]: modMotion = modelFilters.ModelMotionFilter( scp, acqFunc, model, enums.motionMethod.Determinist) modMotion.compute() elif model.version in ["CGM2.3", "CGM2.3e", "CGM2.4", "CGM2.4e"]: if side == "Left": thigh_markers = model.getSegment("Left Thigh").m_tracking_markers shank_markers = model.getSegment("Left Shank").m_tracking_markers elif side == "Right": thigh_markers = model.getSegment("Right Thigh").m_tracking_markers shank_markers = model.getSegment("Right Shank").m_tracking_markers validFrames, vff, vlf = btkTools.findValidFrames( acqFunc, thigh_markers + shank_markers) proximalSegmentLabel = str(side + " Thigh") distalSegmentLabel = str(side + " Shank") # Motion modMotion = modelFilters.ModelMotionFilter( scp, acqFunc, model, enums.motionMethod.Sodervisk) modMotion.segmentalCompute([proximalSegmentLabel, distalSegmentLabel]) # calibration decorators modelDecorator.KneeCalibrationDecorator(model).calibrate2dof( side, indexFirstFrame=iff, indexLastFrame=ilf, jointRange=jointRange) # --------------------------FINAL CALIBRATION OF THE STATIC File--------- # ---- Calibration modelFilters.ModelCalibrationFilter( scp, acqStatic, model, leftFlatFoot=leftFlatFoot, rightFlatFoot=rightFlatFoot, markerDiameter=markerDiameter).compute() return model, acqFunc, side
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