def test_offset(value, acq, viconLabel, decimal=3): np.testing.assert_almost_equal( value, np.rad2deg(acq.GetMetaData().FindChild( utils.str("PROCESSING")).value().FindChild( utils.str(viconLabel)).value().GetInfo().ToDouble()[0]), decimal=decimal)
def test_progressionFrameIssue(self): """ """ MAIN_PATH = pyCGM2.TEST_DATA_PATH + "\\Issues\\BrianH\\progressionFrame Issue\\" gaitFilename = "walk09.c3d" acq = btkTools.smartReader(MAIN_PATH + gaitFilename) valSACR = acq.GetPoint(utils.str("SACR")).GetValues() btkTools.smartAppendPoint(acq, "RPSI", valSACR, desc="") btkTools.smartAppendPoint(acq, "LPSI", valSACR, desc="") pfp = progressionFrame.PelvisProgressionFrameProcedure() pff = progressionFrame.ProgressionFrameFilter(acq, pfp) pff.compute() np.testing.assert_equal(pff.outputs["progressionAxis"], "X") np.testing.assert_equal(pff.outputs["forwardProgression"], True) gaitFilename = "walk11.c3d" acq = btkTools.smartReader(str(MAIN_PATH + gaitFilename)) valSACR = acq.GetPoint(utils.str("SACR")).GetValues() btkTools.smartAppendPoint(acq, "RPSI", valSACR, desc="") btkTools.smartAppendPoint(acq, "LPSI", valSACR, desc="") pfp = progressionFrame.PelvisProgressionFrameProcedure() pff = progressionFrame.ProgressionFrameFilter(acq, pfp) pff.compute() np.testing.assert_equal(pff.outputs["progressionAxis"], "X") np.testing.assert_equal(pff.outputs["forwardProgression"], True)
def sortedEvents(trial): """ Sort out events of a trial :Parameters: - `trial` (openma.trial) - an openma trial instance """ evs = trial.findChildren(ma.T_Event) contextLst = [] # recuperation de tous les contextes for it in evs: if it.context() not in contextLst: contextLst.append(it.context()) valueTime = [] # recuperation de toutes les frames SANS doublons for it in evs: if it.time() not in valueTime: valueTime.append(it.time()) valueTime.sort() # trie events = ma.Node(utils.str("SortedEvents")) #events =list() for contextLst_it in contextLst: for timeSort in valueTime: for it in evs: if it.time() == timeSort and it.context() == contextLst_it: ev = ma.Event(it.name(), it.time(), contextLst_it, utils.str("")) ev.addParent(events) events.addParent(trial.child(0))
def print_offset(value, acq, viconLabel, decimal=3): logging.info( " offset [%s] => %f ( my value) = %f ( reference)" % (viconLabel, value, np.rad2deg(acq.GetMetaData().FindChild( utils.str("PROCESSING")).value().FindChild( utils.str(viconLabel)).value().GetInfo().ToDouble()[0])))
def findValidFrames(trial, markerLabels): flag = list() pfn = trial.findChild( ma.T_TimeSequence, utils.str(""), [[utils.str("type"), ma.TimeSequence.Type_Marker]]).samples() for i in range(0, pfn): pointFlag = list() for marker in markerLabels: residue = trial.findChild(ma.T_TimeSequence, utils.str(marker)).data()[i, 3] if residue >= 0: pointFlag.append(1) else: pointFlag.append(0) if all(pointFlag) == 1: flag.append(1) else: flag.append(0) firstValidFrame = flag.index(1) lastValidFrame = len(flag) - flag[::-1].index(1) - 1 return flag, firstValidFrame, lastValidFrame
def test_gaitTrialProgressionY_forward_lateralX(self): """ """ MAIN_PATH = pyCGM2.TEST_DATA_PATH + "LowLevel\\ProgressionFrame\\sample 1\\" gaitFilename = "gait_Y_forward.c3d" acq = btkTools.smartReader(MAIN_PATH + gaitFilename) pfp = progressionFrame.PelvisProgressionFrameProcedure() pff = progressionFrame.ProgressionFrameFilter(acq, pfp) pff.compute() np.testing.assert_equal(pff.outputs["progressionAxis"], "Y") np.testing.assert_equal(pff.outputs["forwardProgression"], True) np.testing.assert_equal(pff.outputs["globalFrame"], "YXZ") valSACR = (acq.GetPoint(utils.str("LPSI")).GetValues() + acq.GetPoint(utils.str("RPSI")).GetValues()) / 2.0 btkTools.smartAppendPoint(acq, "SACR", valSACR, desc="") pfp = progressionFrame.PelvisProgressionFrameProcedure( backMarkers=["SACR"]) pff = progressionFrame.ProgressionFrameFilter(acq, pfp) pff.compute() np.testing.assert_equal(pff.outputs["progressionAxis"], "Y") np.testing.assert_equal(pff.outputs["forwardProgression"], True) np.testing.assert_equal(pff.outputs["globalFrame"], "YXZ")
def modifySubject(acq,newSubjectlabel): """ update the subject name inside c3d metadata :Parameters: - `acq` (btkAcquisition) - a btk acquisition inctance - `newSubjectlabel` (str) - desired subject name """ acq.GetMetaData().FindChild(utils.str("SUBJECTS") ).value().FindChild(utils.str("NAMES")).value().GetInfo().SetValue(0,(utils.str(newSubjectlabel)))
def exportC3d(self, filenameNoExt=None): if filenameNoExt is None: ma.io.write( self.m_root, utils.str(self.m_dataPath + self.m_filenameNoExt + ".c3d")) else: ma.io.write(self.m_root, utils.str(self.m_dataPath + filenameNoExt + ".c3d"))
def smartTrialReader(dataPath, trialfilename): if dataPath is None: fileNode = ma.io.read(utils.str((trialfilename))) else: fileNode = ma.io.read(utils.str(dataPath + trialfilename)) trial = fileNode.findChild(ma.T_Trial) sortedEvents(trial) return trial
def smartAppendAnalog(acq,label,values,desc="" ): if isAnalogExist(acq,label): acq.GetAnalog(utils.str(label)).SetValues(values) acq.GetAnalog(utils.str(label)).SetDescription(utils.str(desc)) #acq.GetAnalog(label).SetType(PointType) else: newAnalog=btk.btkAnalog(acq.GetAnalogFrameNumber()) newAnalog.SetValues(values) newAnalog.SetLabel(utils.str(label)) acq.AppendAnalog(newAnalog)
def checkMetadata(btkAcq,firstLevel,secondLevel): md = btkAcq.GetMetaData() flag = False if secondLevel is not None: if utils.str(firstLevel) in _getSectionFromMd(md): firstMd = btkAcq.GetMetaData().FindChild(utils.str(firstLevel)).value() if utils.str(secondLevel) in _getSectionFromMd(firstMd): flag = True else: if utils.str(firstLevel) in _getSectionFromMd(md): flag = True return flag
def checkFirstAndLastFrame (acq, markerLabel): """ Check if extremity frames are correct :Parameters: - `acq` (btkAcquisition) - a btk acquisition inctance - `markerLabel` (str) - marker label """ if acq.GetPoint(utils.str(markerLabel)).GetValues()[0,0] == 0: raise Exception ("[pyCGM2] no marker on first frame") if acq.GetPoint(utils.str(markerLabel)).GetValues()[-1,0] == 0: raise Exception ("[pyCGM2] no marker on last frame")
def changeSubjectName(btkAcq,subjectName): # change subject name in the metadata md = btkAcq.GetMetaData() if "SUBJECTS" in _getSectionFromMd(md): subjectMd = btkAcq.GetMetaData().FindChild(utils.str("SUBJECTS")).value() if "NAMES" in _getSectionFromMd(subjectMd): subjectMd.FindChild(utils.str("NAMES")).value().GetInfo().SetValue(0,utils.str(subjectName)) if "USES_PREFIXES" not in _getSectionFromMd(subjectMd): btk.btkMetaDataCreateChild(subjectMd, utils.str("USES_PREFIXES"), 0) if "ANALYSIS" in _getSectionFromMd(md): analysisMd = btkAcq.GetMetaData().FindChild(utils.str("ANALYSIS")).value() if "SUBJECTS" in _getSectionFromMd(analysisMd): anaSubMdi = analysisMd.FindChild(utils.str("SUBJECTS")).value().GetInfo() for i in range(0,anaSubMdi.GetDimension(1) ): anaSubMdi.SetValue(i,utils.str(subjectName)) events = btkAcq.GetEvents() for ev in btk.Iterate(events): ev.SetSubject(utils.str(subjectName)) # Do not work # eventMd = btkAcq.GetMetaData().FindChild("EVENT").value() # eventMdi = eventMd.FindChild("SUBJECTS").value().GetInfo() # for i in range(0,eventMdi.GetDimension(1) ): # eventMdi.SetValue(i,"TEST") return btkAcq
def appendAnalogs(self): for nexusAnalogDevice in self.m_nexusAnalogDevices: channels = nexusAnalogDevice.getChannels() for channel in channels: start = self.m_firstFrame - 1 end = self.m_lastFrame - 1 data = channel.getValues()[ (start) * self.m_numberAnalogSamplePerFrame:(end + 1) * self.m_numberAnalogSamplePerFrame] if self.m_firstFrame == 1: time_init = 0.0 else: time_init = self.m_firstFrame / self.m_analogFrameRate ts = ma.TimeSequence(utils.str(channel.getLabel()), 1, data.shape[0], self.m_analogFrameRate, time_init, ma.TimeSequence.Type_Analog, "V", 1.0, 0.0, [-10.0, 10.0], self.m_trial.timeSequences()) ts.setData(data.reshape((data.shape[0], 1))) ts.setDescription(channel.getDescription())
def renameOpenMAtoVicon(analysis, suffix=""): """ Convenient function renaming openma standard point label to vicon CGM point label :Parameters: - `analysis` (openMA node) - openma node containing time sequences of model outputs - `suffix` (str) - point label suffix """ tss = analysis.child(0).findChildren(ma.T_TimeSequence) for ts in tss: name = ts.name() if "Angle" in name: newName = name.replace(".", "") newName = newName + "s" + suffix if ("Pelvis" in name): newName = newName.replace("Progress", "") + suffix if "Force" in name: newName = name.replace(".", "") newName = newName[0:newName.rfind("Force") + 5] + suffix if "Moment" in name: newName = name.replace(".", "") newName = newName[0:newName.rfind("Moment") + 6] + suffix if "Power" in name: newName = name.replace(".", "") newName = newName[0:newName.rfind("Power") + 5] + suffix ts.setName(utils.str(newName))
def findProgression(trial, pointLabel): if not isTimeSequenceExist(trial, pointLabel): raise Exception("[pyCGM2] : origin point doesnt exist") f, ff, lf = findValidFrames(trial, [pointLabel]) values = trial.findChild(ma.T_TimeSequence, utils.str(pointLabel)).data()[ff:lf, 0:3] 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) 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") logging.debug("Progression axis : %s" % (progressionAxis)) logging.debug("forwardProgression : %s" % (str(forwardProgression))) logging.debug("globalFrame : %s" % (str(globalFrame))) return progressionAxis, forwardProgression, globalFrame
def __init__(self, ikToolFile, calibratedOsim, ikTagProcedure, dataDir, accuracy=1e-8): """ :Parameters: - `ikToolFile` (str) - full filename of the opensim inverse kinematic tool file - `calibratedOsim` (osim file) - calibrated opensim file - `ikTagProcedure` (pyCGM2.opensim.procedure) - fitting procedure - `dataDir` (str) - path to opensim result directory - `accuracy` (double) - accuracy of the kinematic fitter """ self.m_calibratedOsim = calibratedOsim self.m_ikToolFile = ikToolFile self.m_procedure = ikTagProcedure self.accuracy = accuracy self.opensimOutputDir = dataDir if dataDir[-1:] == "\\" else utils.str( dataDir + "\\") self._osimIK = osimProcessing.opensimKinematicFitting( self.m_calibratedOsim.m_model, self.m_ikToolFile) self._osimIK.setAccuracy(self.accuracy) self._osimIK.setResultsDirectory(self.opensimOutputDir)
def getStartEndEvents(btkAcq,context,startLabel="Start", endLabel="End"): events= btkAcq.GetEvents() start=[] end=[] for ev in btk.Iterate(events): if ev.GetContext()== utils.str(context) and ev.GetLabel()==utils.str(startLabel) : start.append(ev.GetFrame()) if ev.GetContext()==utils.str(context) and ev.GetLabel()==utils.str(endLabel) : end.append(ev.GetFrame()) if start==[] or end==[]: return None,None if len(start)>1 or len(end)>1: raise("[pyCGM2]: You can t have multiple Start and End events" ) elif end<start: raise("[pyCGM2]: wrong order ( start<end)" ) else: return start[0],end[0]
def constructMarker(acq,label,markers,numpyMethod=np.mean,desc=""): nFrames = acq.GetPointFrameNumber() x=np.zeros((nFrames, len(markers))) y=np.zeros((nFrames, len(markers))) z=np.zeros((nFrames, len(markers))) i=0 for marker in markers: x[:,i] = acq.GetPoint(utils.str(marker)).GetValues()[:,0] y[:,i] = acq.GetPoint(utils.str(marker)).GetValues()[:,1] z[:,i] = acq.GetPoint(utils.str(marker)).GetValues()[:,2] i+=1 values = np.zeros((nFrames,3)) values[:,0] = numpyMethod(x, axis=1) values[:,1] = numpyMethod(y, axis=1) values[:,2] = numpyMethod(z, axis=1) smartAppendPoint(acq,label,values,desc=desc)
def exportXml(self, filename, path=None): """ Export the generated inverse kinematic Tool :Parameters: - `filename` (str) - filename of the generated inverse kinematic Tool """ filename = filename if path is None else utils.str(path + filename) self._osimIK.m_ikTool.printToXML(filename)
def exportXml(self, filename, path=None): """ Export the calibrated model as an osim file :Parameters: - `filename` (str) - filename of the calibrated osim file """ filename = filename if path is None else utils.str(path + filename) self._osimModel.m_model.printToXML(filename)
def test_appendPoint(self): filename = pyCGM2.TEST_DATA_PATH + "LowLevel\\IO\\Hånnibøl_c3d\\static.c3d" acq = btkTools.smartReader(filename, translators=None) values = acq.GetPoint(utils.str("LASI")).GetValues() btkTools.smartAppendPoint(acq, "LASI2", values, PointType=btk.btkPoint.Marker, desc="toto", residuals=None)
def processC3d(self): for c3d in self.m_c3ds: filenameOut = c3d[:-4] + "_" + self.m_fileSuffix+".c3d" if self.m_fileSuffix is not None else c3d acq = btkTools.smartReader((self.m_c3dPath+c3d)) values = acq.GetAnalog(utils.str(self.m_label)).GetValues() valuesNorm = values / self.m_threshold btkTools.smartAppendAnalog(acq,self.m_label+"_Norm",valuesNorm, desc= "Normalization)") btkTools.smartWriter(acq, (self.m_c3dPath+filenameOut))
def isGap_inAcq(acq, markerList): """ Check if there is a gap :Parameters: - `acq` (btkAcquisition) - a btk acquisition inctance - `markerList` (list of str) - marker labels """ for m in markerList: residualValues = acq.GetPoint(utils.str(m)).GetResiduals() if any(residualValues== -1.0): raise Exception("[pyCGM2] gap founded for markers %s " % m )
def smartWriter(acq, filename): """ Convenient function to write a c3d with Btk :Parameters: - `acq` (btkAcquisition) - a btk acquisition inctance - `filename` (str) - path and filename of the c3d """ writer = btk.btkAcquisitionFileWriter() writer.SetInput(acq) writer.SetFilename(utils.str(filename)) writer.Update()
def isKineticFlag(trial): """ Flag up if correct kinetics available :Parameters: - `trial` (openma.trial) - an openma trial instance :Return: - `` (bool) - flag if kinetic available - `kineticEvent_times` (lst) - time of maximal Normal reaction Forces for both context - `kineticEvent_times_left` (lst) - time of maximal Normal reaction Forces for the Left context - `kineticEvent_times_right` (lst) - time of maximal Normal reaction Forces for the Right context """ kineticEvent_times = [] kineticEvent_times_left = [] kineticEvent_times_right = [] evsn = trial.findChild(ma.T_Node, utils.str("SortedEvents")) for ev in evsn.findChildren(ma.T_Event): if ev.context() == utils.str("General"): if ev.name() in [utils.str('Left-FP'), utils.str('Right-FP')]: kineticEvent_times.append(ev.time()) if ev.name() in [utils.str('Left-FP')]: kineticEvent_times_left.append(ev.time()) if ev.name() in [utils.str('Right-FP')]: kineticEvent_times_right.append(ev.time()) if kineticEvent_times == []: return False, 0, 0, 0 else: return True, kineticEvent_times, kineticEvent_times_left, kineticEvent_times_right
def plotComparisonOfPoint(acq, label, suffix, title=None): fig = plt.figure(figsize=(10, 4), dpi=100, facecolor="white") plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=0.5, hspace=0.5) ax1 = plt.subplot(1, 3, 1) ax2 = plt.subplot(1, 3, 2) ax3 = plt.subplot(1, 3, 3) ax1.plot(acq.GetPoint(utils.str(label)).GetValues()[:, 0], "-r") ax1.plot( acq.GetPoint(utils.str(label + "_" + suffix)).GetValues()[:, 0], "-b") ax2.plot(acq.GetPoint(utils.str(label)).GetValues()[:, 1], "-r") ax2.plot( acq.GetPoint(utils.str(label + "_" + suffix)).GetValues()[:, 1], "-b") ax3.plot(acq.GetPoint(utils.str(label)).GetValues()[:, 2], "-r") ax3.plot( acq.GetPoint(utils.str(label + "_" + suffix)).GetValues()[:, 2], "-b") if title is not None: plt.title(title) plt.show()
def getAnalogTimeSequenceData(self,analogLabel): """ Get analog data of the cycle :Parameters: - `analogLabel` (str) - analog Label """ if trialTools.isTimeSequenceExist(self.trial,analogLabel): return self.trial.findChild(ma.T_TimeSequence, utils.str(analogLabel)).data()[int((self.begin-self.firstFrame) * self.appf) : int((self.end-self.firstFrame+1) * self.appf),:] else: logging.debug("[pyCGM2] the Analog Label %s doesn t exist in %s" % (analogLabel,self.trial.name())) return None
def isTimeSequenceExist(trial, label): """ Check if a Time sequence exists inside a trial :Parameters: - `trial` (openma.trial) - an openma trial instance - `label` (str) - label of the time sequence """ try: ts = trial.findChild(ma.T_TimeSequence, utils.str(label)) return True except ValueError: return False
def getPointTimeSequenceData(self,pointLabel): """ Get temporal point data of the cycle :Parameters: - `pointLabel` (str) - point Label """ if trialTools.isTimeSequenceExist(self.trial,pointLabel): return self.trial.findChild(ma.T_TimeSequence, utils.str(pointLabel)).data()[self.begin-self.firstFrame:self.end-self.firstFrame+1,0:3] # 0.3 because openma::Ts includes a forth column (i.e residual) else: logging.debug("[pyCGM2] the point Label %s doesn t exist in %s" % (pointLabel,self.trial.name())) return None