Ejemplo n.º 1
0
/**
 * Read sto file.
 *
 * @param aFilename name of sto file.
 */
void MarkerData::readStoFile(const string& aFileName)
{
    if (aFileName.empty())
        throw Exception("MarkerData.readStoFile: ERROR- Marker file name is empty",__FILE__,__LINE__);

    // If the file was written by STOFileAdapter, make the file readable by
    // Storage. Calls below have no effect otherwise.
    std::string tmpFileName{"tmp.sto"};
    bool versionChanged{revertToVersionNumber1(aFileName, tmpFileName)};
    if(versionChanged)
        addNumRowsNumColumns(tmpFileName, aFileName);
    std::remove(tmpFileName.c_str());

    Storage store(aFileName);

    // populate map between marker names and column numbers 
    std::map<int, std::string>  markerIndices;
    buildMarkerMap(store, markerIndices);

    if (markerIndices.size()==0){
        throw Exception("MarkerData.readStoFile: ERROR- No markers were identified. Markers should appear on consecutive columns as Marker1.x Marker1.y Marker1.z Marker2.x... etc.",__FILE__,__LINE__);
    }
    std::map<int, std::string>::iterator iter;

    for (iter = markerIndices.begin(); iter != markerIndices.end(); iter++) {
        SimTK::String markerNameWithSuffix = iter->second;
        size_t dotIndex =
            SimTK::String::toLower(markerNameWithSuffix).find_last_of(".x");
        SimTK::String candidateMarkerName = markerNameWithSuffix.substr(0, dotIndex-1);
        _markerNames.append(candidateMarkerName);
    }
    // use map to populate data for MarkerData header
    _numMarkers = (int) markerIndices.size();
    _numFrames = store.getSize();
    _firstFrameNumber = 1;
    _dataRate = 250;
    _cameraRate = 250;
    _originalDataRate = 250;
    _originalStartFrame = 1;
    _originalNumFrames = _numFrames;
    _fileName = aFileName;
    _units = Units(Units::Meters);

    double time;
    int sz = store.getSize();
    for (int i=0; i < sz; i++){
        StateVector* nextRow = store.getStateVector(i);
        time = nextRow->getTime();
        int frameNum = i+1;
        MarkerFrame *frame = new MarkerFrame(_numMarkers, frameNum, time, _units);
        const Array<double>& rowData = nextRow->getData();
        // Cycle through map and add Marker coordinates to the frame. Same order as header.
        for (iter = markerIndices.begin(); iter != markerIndices.end(); iter++) {
            int startIndex = iter->first; // startIndex includes time but data doesn't!
            frame->addMarker(SimTK::Vec3(rowData[startIndex-1], rowData[startIndex], rowData[startIndex+1]));
        }
        _frames.append(frame);
   }
}
Ejemplo n.º 2
0
/**
 * Average all the frames between aStartTime and
 * aEndTime (inclusive) and store the result in the first
 * frame. All other frames are deleted. The time and frame
 * number of this one remaining frame are copied from the
 * startIndex frame. The aThreshold parameter is for printing
 * a warning if any marker moves more than that amount in
 * the averaged frames. aThreshold is specified by the user,
 * and is assumed to be in the units of the marker data.
 *
 * @param aThreshold amount of marker movement that is allowed for averaging.
 * @param aStartTime start time of frame range to average.
 * @param aEndTime end time of frame range to average.
 */
void MarkerData::averageFrames(double aThreshold, double aStartTime, double aEndTime)
{
	if (_numFrames < 2)
		return;

	int startIndex = 0, endIndex = 1;
	double *minX = NULL, *minY = NULL, *minZ = NULL, *maxX = NULL, *maxY = NULL, *maxZ = NULL;

	findFrameRange(aStartTime, aEndTime, startIndex, endIndex);
	MarkerFrame *averagedFrame = new MarkerFrame(*_frames[startIndex]);

	/* If aThreshold is greater than zero, then calculate
	 * the movement of each marker so you can check if it
	 * is greater than aThreshold.
	 */
	if (aThreshold > 0.0)
	{
		minX = new double [_numMarkers];
		minY = new double [_numMarkers];
		minZ = new double [_numMarkers];
		maxX = new double [_numMarkers];
		maxY = new double [_numMarkers];
		maxZ = new double [_numMarkers];
		for (int i = 0; i < _numMarkers; i++)
		{
			minX[i] = minY[i] = minZ[i] =  SimTK::Infinity;
			maxX[i] = maxY[i] = maxZ[i] = -SimTK::Infinity;
		}
	}

	/* Initialize all the averaged marker locations to 0,0,0. Then
	 * loop through the frames to be averaged, adding each marker location
	 * to averagedFrame. Keep track of the min/max XYZ for each marker
	 * so you can compare it to aThreshold when you're done.
	 */
	for (int i = 0; i < _numMarkers; i++)
	{
		int numFrames = 0;
		Vec3& avePt = averagedFrame->updMarker(i);
		avePt = Vec3(0);

		for (int j = startIndex; j <= endIndex; j++)
		{
			Vec3& pt = _frames[j]->updMarker(i);
			if (!pt.isNaN())
			{
				Vec3& coords = pt; //.get();
				avePt += coords;
				numFrames++;
				if (aThreshold > 0.0)
				{
					if (coords[0] < minX[i])
						minX[i] = coords[0];
					if (coords[0] > maxX[i])
						maxX[i] = coords[0];
					if (coords[1] < minY[i])
						minY[i] = coords[1];
					if (coords[1] > maxY[i])
						maxY[i] = coords[1];
					if (coords[2] < minZ[i])
						minZ[i] = coords[2];
					if (coords[2] > maxZ[i])
						maxZ[i] = coords[2];
				}
			}
		}

		/* Now divide by the number of frames to get the average. */
		if (numFrames > 0)
			avePt /= (double)numFrames;
		else
			avePt = Vec3(SimTK::NaN) ;//(SimTK::NaN, SimTK::NaN, SimTK::NaN);
	}

	/* Store the indices from the file of the first frame and
	 * last frame that were averaged, so you can report them later.
	 */
	int startUserIndex = _frames[startIndex]->getFrameNumber();
	int endUserIndex = _frames[endIndex]->getFrameNumber();

	/* Now delete all the existing frames and insert the averaged one. */
	_frames.clearAndDestroy();
	_frames.append(averagedFrame);
	_numFrames = 1;
	_firstFrameNumber = _frames[0]->getFrameNumber();

	if (aThreshold > 0.0)
	{
		for (int i = 0; i < _numMarkers; i++)
		{
			Vec3& pt = _frames[0]->updMarker(i);

			if (pt.isNaN())
			{
				cout << "___WARNING___: marker " << _markerNames[i] << " is missing in frames " << startUserIndex
					  << " to " << endUserIndex << ". Coordinates will be set to NAN." << endl;
			}
			else if (maxX[i] - minX[i] > aThreshold ||
				      maxY[i] - minY[i] > aThreshold ||
				      maxZ[i] - minZ[i] > aThreshold)
			{
				double maxDim = maxX[i] - minX[i];
				maxDim = MAX(maxDim, (maxY[i] - minY[i]));
				maxDim = MAX(maxDim, (maxZ[i] - minZ[i]));
				cout << "___WARNING___: movement of marker " << _markerNames[i] << " in " << _fileName
					  << " is " << maxDim << " (threshold = " << aThreshold << ")" << endl;
			}
		}
	}

	cout << "Averaged frames from time " << aStartTime << " to " << aEndTime << " in " << _fileName
		  << " (frames " << startUserIndex << " to " << endUserIndex << ")" << endl;

	if (aThreshold > 0.0)
	{
		delete [] minX;
		delete [] minY;
		delete [] minZ;
		delete [] maxX;
		delete [] maxY;
		delete [] maxZ;
	}
}
Ejemplo n.º 3
0
/**
 * Read TRC file.
 *
 * @param aFilename name of TRC file.
 * @param aSMD MarkerData object to hold the file contents
 */
void MarkerData::readTRCFile(const string& aFileName, MarkerData& aSMD)
{
   ifstream in;
   string line, buffer;
   int frameNum, coordsRead;
   double time;
	SimTK::Vec3 coords;

	if (aFileName.empty())
		throw Exception("MarkerData.readTRCFile: ERROR- Marker file name is empty",__FILE__,__LINE__);

   in.open(aFileName.c_str());

	if (!in.good())
	{
		string errorMessage;
		errorMessage = "Unable to open marker file " + aFileName;
		throw Exception(errorMessage);
	}

   readTRCFileHeader(in, aFileName, aSMD);

   /* read frame data */
   while (getline(in, line))
   {
      /* skip over any blank lines */
      if (findFirstNonWhiteSpace(line) == -1)
         continue;

		if (aSMD._frames.getSize() == aSMD._numFrames)
		{
#if 0
			if (gUseGlobalMessages)
			{
				gErrorBuffer += "Extra data found at end of tracked marker file. ";
				gErrorBuffer += "Header declared only " + intToString(trc->header.numFrames) + " frames.\n";
			}
			rc = smFileWarning;
#endif
			break;
		}

      if (!readIntegerFromString(line, &frameNum))
      {
#if 0
         if (gUseGlobalMessages)
            gErrorBuffer += "Could not read frame number in tracked marker file.\n";
         rc = smFileError;
         goto cleanup;
#endif
      }

      if (!readDoubleFromString(line, &time))
      {
#if 0
         if (gUseGlobalMessages)
            gErrorBuffer += "Could not read time in tracked marker file.\n";
         rc = smFileError;
         goto cleanup;
#endif
      }

		MarkerFrame *frame = new MarkerFrame(aSMD._numMarkers, frameNum, time, aSMD._units);

      /* keep reading sets of coordinates until the end of the line is
       * reached. If more coordinates were read than there are markers,
       * return an error.
       */
      coordsRead = 0;
	  bool allowNaNs = true;
      while (readCoordinatesFromString(line, &coords[0], allowNaNs))
      {
         if (coordsRead >= aSMD._numMarkers)
         {
            break;

#if 0  // Don't return an error because many TRC files have extra data at the ends of rows
            if (gUseGlobalMessages)
               gErrorBuffer += "Extra data found in frame number " + intToString(frameNum) +
                               " in tracked marker file.\n";
            rc = smFileError;
            // delete the current markerCoordList because framesRead has not been incremented yet.
            delete [] f->markerCoordList;
            goto cleanup;
#endif
         }
         if (coordsRead < aSMD._numMarkers)
				frame->addMarker(coords);
         coordsRead++;
      }

      if (coordsRead < aSMD._numMarkers)
      {
#if 0
         if (gUseGlobalMessages)
            gErrorBuffer += " Missing data in frame number " + intToString(frameNum) +
                            " in tracked marker file.\n";
         rc = smFileError;
         // delete the current markerCoordList because framesRead has not been incremented yet.
         delete [] f->markerCoordList;
         goto cleanup;
#endif
      }
		aSMD._frames.append(frame);
   }

   if (aSMD._frames.getSize() < aSMD._numFrames)
   {
#if 0
      if (gUseGlobalMessages)
         gErrorBuffer += "Missing data in tracked marker file. Only " + intToString(framesRead) + " of " +
                         intToString(trc->header.numFrames) + " frames found.\n";
      rc = smFileError;
      goto cleanup;
#endif
		aSMD._numFrames = aSMD._frames.getSize();
   }

   /* If the user-defined frame numbers are not continguous from the first frame to the
    * last, reset them to a contiguous array. This is necessary because the user-defined
    * numbers are used to index the array of frames.
    */
	if (aSMD._frames[aSMD._numFrames-1]->getFrameNumber() - aSMD._frames[0]->getFrameNumber() !=
		 aSMD._numFrames - 1)
   {
		int firstIndex = aSMD._frames[0]->getFrameNumber();
      for (int i = 1; i < aSMD._numFrames; i++)
			aSMD._frames[i]->setFrameNumber(firstIndex + i);
   }

#if 0
   if (gUseGlobalMessages)
   {
      gMessage += "TRC file " + actualFileName + "\n\t" + intToString(trc->header.numFrames)
                  + " frames\n\t" + intToString(trc->header.numMarkers) + " markers/frame\n";
      gMessage += "Read " + intToString(framesRead) + " frames.\n";
   }
#endif

//cleanup:
   in.close();
}