diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.cpp b/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.cpp index b1c1764a09..a03a63545a 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.cpp +++ b/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.cpp @@ -1,262 +1,290 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2007-12-11 14:46:19 +0100 (Di, 11 Dez 2007) $ Version: $Revision: 13129 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkNavigationDataRecorder.h" #include #include #include #include mitk::NavigationDataRecorder::NavigationDataRecorder() { m_NumberOfInputs = 0; m_RecordingMode = NormalFile; m_Recording = false; m_NumberOfRecordedFiles = 0; m_Stream = NULL; m_FileName = ""; m_SystemTimeClock = RealTimeClock::New(); - m_OutputFormatMember = mitk::NavigationDataRecorder::xml; + m_OutputFormat = mitk::NavigationDataRecorder::xml; //To get a start time mitk::TimeStamp::GetInstance()->Start(this); } mitk::NavigationDataRecorder::~NavigationDataRecorder() { } void mitk::NavigationDataRecorder::GenerateData() { } void mitk::NavigationDataRecorder::AddNavigationData( const NavigationData* nd ) { // Process object is not const-correct so the const_cast is required here this->SetNthInput(m_NumberOfInputs, const_cast< mitk::NavigationData * >( nd ) ); m_NumberOfInputs++; this->Modified(); } void mitk::NavigationDataRecorder::SetRecordingMode( RecordingMode mode ) { m_RecordingMode = mode; this->Modified(); } void mitk::NavigationDataRecorder::Update() { if (m_Recording) { DataObjectPointerArray inputs = this->GetInputs(); //get all inputs mitk::NavigationData::TimeStampType timestamp=0.0; // timestamp for mitk time timestamp = mitk::TimeStamp::GetInstance()->GetElapsed(); mitk::NavigationData::TimeStampType sysTimestamp = 0.0; // timestamp for system time sysTimestamp = m_SystemTimeClock->GetCurrentStamp(); // cast system time double value to stringstream to avoid low precision rounding std::ostringstream strs; strs.precision(15); // rounding precision for system time double value strs << sysTimestamp; std::string sysTimeStr = strs.str(); + + //write csv header if first line + if ((m_OutputFormat == mitk::NavigationDataRecorder::csv) && m_firstLine) + { + m_firstLine = false; + *m_Stream << "TimeStamp"; + for (unsigned int index = 0; index < inputs.size(); index++){ *m_Stream << ";Valid_Tool" << index << + ";X_Tool" << index << + ";Y_Tool" << index << + ";Z_Tool" << index << + ";QX_Tool" << index << + ";QY_Tool" << index << + ";QZ_Tool" << index << + ";QR_Tool" << index;} + *m_Stream << "\n"; + } - + *m_Stream << timestamp; for (unsigned int index = 0; index < inputs.size(); index++) { mitk::NavigationData* nd = dynamic_cast(inputs[index].GetPointer()); nd->Update(); // call update to propagate update to previous filters mitk::NavigationData::PositionType position; mitk::NavigationData::OrientationType orientation(0.0, 0.0, 0.0, 0.0); mitk::NavigationData::CovarianceMatrixType matrix; bool hasPosition = true; bool hasOrientation = true; bool dataValid = false; position.Fill(0.0); matrix.SetIdentity(); position = nd->GetPosition(); orientation = nd->GetOrientation(); matrix = nd->GetCovErrorMatrix(); hasPosition = nd->GetHasPosition(); hasOrientation = nd->GetHasOrientation(); dataValid = nd->IsDataValid(); //use this one if you want the timestamps of the source //timestamp = nd->GetTimeStamp(); //a timestamp is never < 0! this case happens only if you are using the timestamp of the nd object instead of getting a new one if (timestamp >= 0) { - TiXmlElement* elem = new TiXmlElement("ND"); - - elem->SetDoubleAttribute("Time", timestamp); - elem->SetAttribute("SystemTime", sysTimeStr); // tag for system time - elem->SetDoubleAttribute("Tool", index); - elem->SetDoubleAttribute("X", position[0]); - elem->SetDoubleAttribute("Y", position[1]); - elem->SetDoubleAttribute("Z", position[2]); - - elem->SetDoubleAttribute("QX", orientation[0]); - elem->SetDoubleAttribute("QY", orientation[1]); - elem->SetDoubleAttribute("QZ", orientation[2]); - elem->SetDoubleAttribute("QR", orientation[3]); - - elem->SetDoubleAttribute("C00", matrix[0][0]); - elem->SetDoubleAttribute("C01", matrix[0][1]); - elem->SetDoubleAttribute("C02", matrix[0][2]); - elem->SetDoubleAttribute("C03", matrix[0][3]); - elem->SetDoubleAttribute("C04", matrix[0][4]); - elem->SetDoubleAttribute("C05", matrix[0][5]); - elem->SetDoubleAttribute("C10", matrix[1][0]); - elem->SetDoubleAttribute("C11", matrix[1][1]); - elem->SetDoubleAttribute("C12", matrix[1][2]); - elem->SetDoubleAttribute("C13", matrix[1][3]); - elem->SetDoubleAttribute("C14", matrix[1][4]); - elem->SetDoubleAttribute("C15", matrix[1][5]); - - if (dataValid) - elem->SetAttribute("Valid",1); - else - elem->SetAttribute("Valid",0); - - if (hasOrientation) - elem->SetAttribute("hO",1); - else - elem->SetAttribute("hO",0); - - if (hasPosition) - elem->SetAttribute("hP",1); - else - elem->SetAttribute("hP",0); - - *m_Stream << " " << *elem << std::endl; - - delete elem; + if (this->m_OutputFormat = mitk::NavigationDataRecorder::xml) + { + TiXmlElement* elem = new TiXmlElement("ND"); + + elem->SetDoubleAttribute("Time", timestamp); + elem->SetAttribute("SystemTime", sysTimeStr); // tag for system time + elem->SetDoubleAttribute("Tool", index); + elem->SetDoubleAttribute("X", position[0]); + elem->SetDoubleAttribute("Y", position[1]); + elem->SetDoubleAttribute("Z", position[2]); + + elem->SetDoubleAttribute("QX", orientation[0]); + elem->SetDoubleAttribute("QY", orientation[1]); + elem->SetDoubleAttribute("QZ", orientation[2]); + elem->SetDoubleAttribute("QR", orientation[3]); + + elem->SetDoubleAttribute("C00", matrix[0][0]); + elem->SetDoubleAttribute("C01", matrix[0][1]); + elem->SetDoubleAttribute("C02", matrix[0][2]); + elem->SetDoubleAttribute("C03", matrix[0][3]); + elem->SetDoubleAttribute("C04", matrix[0][4]); + elem->SetDoubleAttribute("C05", matrix[0][5]); + elem->SetDoubleAttribute("C10", matrix[1][0]); + elem->SetDoubleAttribute("C11", matrix[1][1]); + elem->SetDoubleAttribute("C12", matrix[1][2]); + elem->SetDoubleAttribute("C13", matrix[1][3]); + elem->SetDoubleAttribute("C14", matrix[1][4]); + elem->SetDoubleAttribute("C15", matrix[1][5]); + + if (dataValid) + elem->SetAttribute("Valid",1); + else + elem->SetAttribute("Valid",0); + + if (hasOrientation) + elem->SetAttribute("hO",1); + else + elem->SetAttribute("hO",0); + + if (hasPosition) + elem->SetAttribute("hP",1); + else + elem->SetAttribute("hP",0); + + *m_Stream << " " << *elem << std::endl; + + delete elem; + } + else if (this->m_OutputFormat = mitk::NavigationDataRecorder::csv) + { + *m_Stream << ";" << dataValid << ";" << position[0] << ";" << position[1] << ";" << position[2] << ";" << orientation[0] << ";" << orientation[1] << ";" << orientation[2] << ";" << orientation[3]; + } } } + if (this->m_OutputFormat = mitk::NavigationDataRecorder::csv) *m_Stream << "\n"; } } void mitk::NavigationDataRecorder::StartRecording() { if (m_Recording) { std::cout << "Already recording please stop before start new recording session" << std::endl; return; } if (m_Stream == NULL) { std::stringstream ss; std::ostream* stream; //An existing extension will be cut and replaced with .xml std::string tmpPath = itksys::SystemTools::GetFilenamePath(m_FileName); m_FileName = itksys::SystemTools::GetFilenameWithoutExtension(m_FileName); - ss << tmpPath << "/" << m_FileName << "-" << m_NumberOfRecordedFiles << ".xml"; + if (m_OutputFormat == mitk::NavigationDataRecorder::csv) ss << tmpPath << "/" << m_FileName << "-" << m_NumberOfRecordedFiles << ".csv"; + else ss << tmpPath << "/" << m_FileName << "-" << m_NumberOfRecordedFiles << ".xml"; switch(m_RecordingMode) { case Console: stream = &std::cout; break; case NormalFile: //Check if there is a file name and path if (m_FileName == "") { stream = &std::cout; std::cout << "No file name or file path set the output is redirected to the console"; } else { stream = new std::ofstream(ss.str().c_str()); } break; case ZipFile: stream = &std::cout; std::cout << "Sorry no ZipFile support yet"; break; default: stream = &std::cout; break; } + m_firstLine = true; StartRecording(stream); } } void mitk::NavigationDataRecorder::StartRecording(std::ostream* stream) { if (m_Recording) { std::cout << "Already recording please stop before start new recording session" << std::endl; return; } m_Stream = stream; m_Stream->precision(10); //TODO store date and GMT time if (m_Stream) { - *m_Stream << "" << std::endl; - /**m_Stream << "" << std::endl;*/ - // should be a generic version, meaning a member variable, which has the actual version - *m_Stream << " " << "" << std::endl; - + if (m_OutputFormat == mitk::NavigationDataRecorder::xml) + { + *m_Stream << "" << std::endl; + /**m_Stream << "" << std::endl;*/ + // should be a generic version, meaning a member variable, which has the actual version + *m_Stream << " " << "" << std::endl; + } m_Recording = true; } } void mitk::NavigationDataRecorder::StopRecording() { if (!m_Recording) { std::cout << "You have to start a recording first" << std::endl; return; } if (m_Stream) { *m_Stream << "" << std::endl; } m_NumberOfRecordedFiles++; m_Stream = NULL; m_Recording = false; } \ No newline at end of file diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.h b/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.h index 7352a88df7..2221fa121a 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.h +++ b/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.h @@ -1,170 +1,172 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2008-02-08 13:23:19 +0100 (Fr, 08 Feb 2008) $ Version: $Revision: 13561 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef _MITK_NavigationDataRecorder_H #define _MITK_NavigationDataRecorder_H #include #include "mitkNavigationData.h" #include #include namespace mitk { /**Documentation * \brief This class records NavigationData objects. * * The output of this class is formated as a XML document. * * Internal this class uses streams for recording NavigationData objects. Therefore different types of output are possible * and can be set with the SetOutputMode() method. The default output is directed to the console. If you want to save into a * file you have to set a file name and the path. The recording is started with the call of the method StartRecording(). Now * every Update() stores the current state of the added NavigationDatas. With StopRecording() the stream is stopped. With * another call of StartRecording() the output is written to a new file with incremented filename counter. * * \warning At the moment there is no check if the file is already existing and this class will override existing files. * \ingroup IGT */ class MitkIGT_EXPORT NavigationDataRecorder : public itk::ProcessObject { public: mitkClassMacro( NavigationDataRecorder, itk::ProcessObject ); itkNewMacro( Self ); /** * \brief sets the file name for the OutputMode NormalFile and ZipFile * * Any extensions will be cut * \warning existing files will be overridden * \warning do not use "." in file names at the end */ itkSetStringMacro(FileName); /** * \brief Returns the file name of the recording file (in OutputMode NormalFile and ZipFile) */ itkGetStringMacro(FileName); /** * \brief Returns whether the NavigationDataRecorder is recording or not */ itkGetMacro(Recording,bool); /** * \brief Adds the input NavigationDatas */ virtual void AddNavigationData(const NavigationData* nd); /**Documentation * \brief Starts the recording with the presetted OutputMode * this method calls StartRecording(std::ostream*) */ void StartRecording(); /**Documentation * \brief Starts the recording with an own preinitialized stream */ void StartRecording(std::ostream* stream); /**Documentation * \brief Stops the recording and closes the stream */ void StopRecording(); /**Documentation * \brief Every call of update causes one line for each added NavigationData in the output if the recording was started */ virtual void Update(); /**Documentation * \brief Determines where the output is directed to * * Console: std::cout * NormalFile: std::ofstream * ZipFile: Not supported yet -> std::cout */ enum RecordingMode { Console, NormalFile, ZipFile }; /**Documentation * \brief Determines the output format * * xml: XML format, also default, can be read by NavigationDataPlayer * csv: use to export in excel, matlab, etc. */ - enum OutputFormat + enum OutputFormatEnum { xml, csv }; /**Documentation * \brief Sets the recording mode which causes different types of output streams * see enum RecordingMode */ void SetRecordingMode(RecordingMode mode); /**Documentation * \brief Sets the output format which causes different formats of output streams. The XML format is default. * Also see enum OutputFormat for more information. */ - itkSetMacro(OutputFormatMember,mitk::NavigationDataRecorder::OutputFormat); + itkSetMacro(OutputFormat,mitk::NavigationDataRecorder::OutputFormatEnum); protected: /**Documentation * \brief filter execute method here it is not used * */ virtual void GenerateData(); NavigationDataRecorder(); virtual ~NavigationDataRecorder(); std::string m_FileName; ///< stores the file name and path unsigned int m_NumberOfInputs; ///< counts the numbers of added input NavigationDatas std::ostream* m_Stream; ///< the output stream RecordingMode m_RecordingMode; ///< stores the mode see enum RecordingMode - OutputFormat m_OutputFormatMember; ///< stores the output format; see enum OutputFormat + OutputFormatEnum m_OutputFormat; ///< stores the output format; see enum OutputFormat bool m_Recording; ///< indicates whether the recording is started or not + bool m_firstLine; //for the csv writer to detect wether the header must be written + unsigned int m_NumberOfRecordedFiles; ///< necessary for the naming of the file if there is more than one start-stop cycle mitk::RealTimeClock::Pointer m_SystemTimeClock; ///< system time clock for system time tag in output xml file }; } #endif // #define _MITK_POINT_SET_SOURCE_H