diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataPlayerBase.h b/Modules/IGT/IGTFilters/mitkNavigationDataPlayerBase.h index fe48097463..95b314cf3b 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataPlayerBase.h +++ b/Modules/IGT/IGTFilters/mitkNavigationDataPlayerBase.h @@ -1,78 +1,78 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKNavigationDataPlayerBase_H_HEADER_INCLUDED_ #define MITKNavigationDataPlayerBase_H_HEADER_INCLUDED_ #include #include "tinyxml.h" namespace mitk{ /**Documentation * \brief This class is a slightly changed reimplementation of the * NavigationDataPlayer which does not care about timestamps and just * outputs the navigationdatas in their sequential order * * \ingroup IGT */ class MitkIGT_EXPORT NavigationDataPlayerBase : public NavigationDataSource { public: mitkClassMacro(NavigationDataPlayerBase, NavigationDataSource); /** * \brief Used for pipeline update just to tell the pipeline that we always have to update */ virtual void UpdateOutputInformation(); /** @return Returns an error message if there was one (e.g. if the stream is invalid). * Returns an empty string if there was no error in the current stream. */ itkGetStringMacro(ErrorMessage); /** @return Retruns if the current stream is valid or not. */ itkGetMacro(StreamValid,bool); /** * \brief This method checks if player arrived at end of file. * *\warning This method is not tested yet. It is not save to use! */ bool IsAtEnd(); protected: NavigationDataPlayerBase(); virtual ~NavigationDataPlayerBase(); virtual void GenerateData() = 0; /** * \brief Creates NavigationData from XML element and returns it - * @throw mitk::Exception Throws an exception if elem is NULL. + * @throw mitk::Exception Throws an exception if elem is NULL. */ mitk::NavigationData::Pointer ReadNavigationData(TiXmlElement* elem); bool m_StreamValid; ///< stores if the input stream is valid or not std::string m_ErrorMessage; ///< stores the error message if the stream is invalid }; } // namespace mitk #endif /* MITKNavigationDataSequentialPlayer_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.cpp b/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.cpp index 1b25b9fb0e..ed7cb572ff 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.cpp +++ b/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.cpp @@ -1,375 +1,366 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNavigationDataRecorder.h" #include - #include #include - #include -//for exceptions +//headers for exceptions #include "mitkIGTException.h" #include "mitkIGTIOException.h" -//default constructor mitk::NavigationDataRecorder::NavigationDataRecorder() { //set default values m_NumberOfInputs = 0; m_RecordingMode = NormalFile; m_Recording = false; m_NumberOfRecordedFiles = 0; m_Stream = NULL; m_FileName = ""; m_SystemTimeClock = RealTimeClock::New(); m_OutputFormat = mitk::NavigationDataRecorder::xml; m_RecordCounter = 0; m_RecordCountLimit = -1; m_DoNotOverwriteFiles = false; m_StreamMustBeDeleted = false; //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(); //if csv-mode: write csv header and timestamp at beginning if (m_OutputFormat == mitk::NavigationDataRecorder::csv) { //write header only when it's the first line if (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"; } //write timestamp (always) *m_Stream << timestamp; } //write tool data for every tool 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) { if (this->m_OutputFormat == mitk::NavigationDataRecorder::xml) { TiXmlElement* elem = new TiXmlElement("NavigationData"); 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); // set additional attribute? std::map >::iterator it = m_AdditionalAttributes.find( nd ); if( it != m_AdditionalAttributes.end() ) { elem->SetAttribute(it->second.first, it->second.second); } *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"; } } m_RecordCounter++; if ((m_RecordCountLimit<=m_RecordCounter)&&(m_RecordCountLimit != -1)) {StopRecording();} } void mitk::NavigationDataRecorder::SetAdditionalAttribute(const NavigationData* nd, const std::string& attributeName , const std::string& attributeValue ) { std::map >::iterator it = m_AdditionalAttributes.find( nd ); if( it == m_AdditionalAttributes.end() ) m_AdditionalAttributes[nd] = std::pair(attributeName, attributeValue); else { it->second.first = attributeName; it->second.second = attributeValue; } } void mitk::NavigationDataRecorder::RemoveAdditionalAttribute( const NavigationData* nd ) { std::map >::iterator it = m_AdditionalAttributes.find( nd ); if( it != m_AdditionalAttributes.end() ) m_AdditionalAttributes.erase(it); } void mitk::NavigationDataRecorder::StartRecording() { if(!m_Recording) { - 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); - std::string extension = ".xml"; - if (m_OutputFormat == mitk::NavigationDataRecorder::csv) - extension = ".csv"; + 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); + std::string extension = ".xml"; + if (m_OutputFormat == mitk::NavigationDataRecorder::csv) + extension = ".csv"; - ss << tmpPath << "/" << m_FileName << "-" << m_NumberOfRecordedFiles << extension; + ss << tmpPath << "/" << m_FileName << "-" << m_NumberOfRecordedFiles << extension; - if( m_DoNotOverwriteFiles ) - { - unsigned int index = m_NumberOfRecordedFiles+1; - while( itksys::SystemTools::FileExists( ss.str().c_str() ) ) + if( m_DoNotOverwriteFiles ) { - ss.str(""); - ss << tmpPath << "/" << m_FileName << "-" << index << extension; - index++; + unsigned int index = m_NumberOfRecordedFiles+1; + while( itksys::SystemTools::FileExists( ss.str().c_str() ) ) + { + ss.str(""); + ss << tmpPath << "/" << m_FileName << "-" << index << extension; + index++; + } } - } - - switch(m_RecordingMode) - { - case Console: - stream = &std::cout; - break; - case NormalFile: - //Check if there is a file name and path - if (m_FileName == "") - { + switch(m_RecordingMode) + { + case Console: stream = &std::cout; - //throw an exception - std::string message="No file name or file path set the output is redirected to the console"; - mitkThrowException(mitk::IGTIOException)<precision(10); //TODO store date and GMT time //cheking if the stream is good if (m_Stream->good()) { 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; } else { m_Recording = false; mitkThrowException(mitk::IGTException)<<"The stream is not good"; } } void mitk::NavigationDataRecorder::StopRecording() { if (!m_Recording) { std::cout << "You have to start a recording first" << std::endl; return; } if ((m_Stream) && (m_OutputFormat == mitk::NavigationDataRecorder::xml)) { *m_Stream << "" << std::endl; } m_NumberOfRecordedFiles++; m_Recording = false; m_Stream->flush(); if (m_StreamMustBeDeleted) //stream must only be deleted if it was created inside this class { m_StreamMustBeDeleted = false; delete m_Stream; } m_Stream = NULL; } diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.h b/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.h index 2f84c9581b..2c11f6e317 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.h +++ b/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.h @@ -1,216 +1,219 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #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 ); /**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 OutputFormatEnum { xml, csv }; /** * \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 If true the recorder will never overwrite a file */ itkSetMacro(DoNotOverwriteFiles,bool); /** * \brief Returns whether the NavigationDataRecorder is recording or not */ itkGetMacro(Recording,bool); /** * \brief Returns the recording mode */ itkGetMacro(RecordingMode,RecordingMode); /** * \brief Returns the number of data sets / frames which were recorded by the NavigationDataRecorder since start */ itkGetMacro(RecordCounter,int); /** * \brief Sets a limit of recorded data sets / frames. Recording will be stopped if the number is reached. -1 disables the limit, -1 is default value as well. */ itkSetMacro(RecordCountLimit,int); /** * \brief Adds the input NavigationDatas */ virtual void AddNavigationData(const NavigationData* nd); /// /// set an additional attribute for a specified navigation data /// this will be written for each navigation data and may be /// updated before calling Update() /// void SetAdditionalAttribute( const NavigationData* nd, const std::string& attributeName , const std::string& attributeValue ); void RemoveAdditionalAttribute( const NavigationData* nd ); - /**Documentation - * \brief Starts the recording with the presetted OutputMode - * this method calls StartRecording(std::ostream*) - * @throws Throws an exception if it is already recording and method StartRecorded is called again - * @throws Throws an exception if No file name or file path set the output is redirected to the console for the normal file - */ + /** + * Documentation + * \brief Starts the recording with the presetted OutputMode. + * This method calls StartRecording(std::ostream*). + * Does nothing if the recorder is already recording and + * the method StartRecording is called again. + * @throw mitk::IGTException Throws an exception if no file name or file path is set. + */ void StartRecording(); - /**Documentation - * \brief Starts the recording with an own preinitialized stream - * @throws Throws an exception if it is already recording and method StartRecorded is called - * @throws Throws an exception if the stream is not good - */ + /** + * Documentation + * \brief Starts the recording with an own preinitialized stream + * Does nothing if it is already recording and method StartRecorded is called + * @throw mitk::IGTException Throws an exception if the stream is not good. + */ 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 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(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 bool m_StreamMustBeDeleted; RecordingMode m_RecordingMode; ///< stores the mode see enum RecordingMode OutputFormatEnum m_OutputFormat; ///< stores the output format; see enum OutputFormat bool m_Recording; ///< indicates whether the recording is started or not int m_RecordCounter; ///< counts the number of frames which are recorded since StartRecording int m_RecordCountLimit; ///< limits the number of frames, recording will be stopped if the limit is reached. -1 disables the limit 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 bool m_DoNotOverwriteFiles; ///< do not overwrite any files if true std::map > m_AdditionalAttributes; }; } #endif // #define _MITK_POINT_SET_SOURCE_H diff --git a/Modules/IGT/Testing/mitkNavigationDataRecorderTest.cpp b/Modules/IGT/Testing/mitkNavigationDataRecorderTest.cpp index 943fcfe777..fcbdfe3a8e 100644 --- a/Modules/IGT/Testing/mitkNavigationDataRecorderTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataRecorderTest.cpp @@ -1,414 +1,395 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include //for exceptions #include "mitkIGTException.h" #include "mitkIGTIOException.h" class mitkNavigationDataRecorderTestClass { public: static void TestInstantiation() { // let's create an object of our class mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New(); MITK_TEST_CONDITION( recorder.IsNotNull(), "Testing instatiation of NavigationDataRecorder"); } static void TestRecordingWithGivenStream() { std::string tmp = ""; std::ostringstream* stream = new std::ostringstream( std::ostringstream::trunc ); stream->setf( std::ios::fixed, std::ios::floatfield ); // let's create an object of our class mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New(); MITK_TEST_CONDITION(recorder->GetInputs().size() == 0, "testing initial number of inputs"); MITK_TEST_CONDITION(recorder->GetOutputs().size() == 0, "testing initial number of outputs"); mitk::NavigationData::Pointer naviData = mitk::NavigationData::New(); recorder->AddNavigationData( naviData ); //recorder->SetFileName("e:/test"); //recorder->SetRecordingMode( mitk::NavigationDataRecorder::NormalFile ); recorder->StartRecording( stream ); for ( unsigned int i=0; i<5; i++ ) { mitk::Point3D pnt; pnt[0] = i + 1; pnt[1] = i + 1/2; pnt[2] = i +1*3; naviData->SetPosition(pnt); //naviData->Modified(); recorder->Update(); //Sleep(80 + i*10); } recorder->StopRecording(); std::string str = stream->str(); int pos = str.find( "ToolCount=" ); std::string sub = stream->str().substr(pos+11, 1); MITK_TEST_CONDITION( sub.compare("1") == 0, "check if number of inputs is correct by stringstream"); pos = str.find( "X=" ); sub = stream->str().substr(pos+3, 1); MITK_TEST_CONDITION( sub.compare("1") == 0, "check if the X coordinate is correct"); pos = str.find( "Y=" ); sub = stream->str().substr(pos+3, 1); MITK_TEST_CONDITION( sub.compare("0") == 0, "check if the Y coordinate is correct"); pos = str.find( "Z=" ); sub = stream->str().substr(pos+3, 1); MITK_TEST_CONDITION( sub.compare("3") == 0, "check if the Z coordinate is correct"); recorder->SetFileName("blablabla"); const char* string = recorder->GetFileName(); MITK_TEST_CONDITION( strcmp(string, "blablabla") == 0, "check if set- and getName-methods work"); } static void TestRecordingOnHarddiscXML() { mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New(); //create filename std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest.xml"; recorder->SetFileName(filename.c_str()); mitk::NavigationData::Pointer naviData = mitk::NavigationData::New(); recorder->AddNavigationData( naviData ); recorder->StartRecording(); for ( unsigned int i=0; i<5; i++ ) { mitk::Point3D pnt; pnt[0] = i + 1; pnt[1] = i + 1/2; pnt[2] = i +1*3; naviData->SetPosition(pnt); recorder->Update(); } recorder->StopRecording(); std::string prooffilename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest-0.xml"; Poco::File myFile(prooffilename); MITK_TEST_CONDITION(myFile.exists(),"Testing XML recording on harddisc (does file exist?)."); } static void TestRecordingOnHarddiscXMLZIP() { mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New(); //create filename std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertestzip.xml"; recorder->SetFileName(filename.c_str()); recorder->SetRecordingMode(mitk::NavigationDataRecorder::ZipFile); MITK_TEST_CONDITION(recorder->GetRecordingMode()==mitk::NavigationDataRecorder::ZipFile,"Testing setter of recording mode."); /* Zip file not supported yet, activate later mitk::NavigationData::Pointer naviData = mitk::NavigationData::New(); recorder->AddNavigationData( naviData ); recorder->StartRecording(); for ( unsigned int i=0; i<5; i++ ) { mitk::Point3D pnt; pnt[0] = i + 1; pnt[1] = i + 1/2; pnt[2] = i +1*3; naviData->SetPosition(pnt); recorder->Update(); } recorder->StopRecording(); std::string prooffilename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest-0.xml"; Poco::File myFile(prooffilename); MITK_TEST_CONDITION(myFile.exists(),"Testing XML Zip recording on harddisc (does file exist?)."); */ } static void TestRecordingOnHarddiscCSV() { mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New(); //create filename std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest.xml"; recorder->SetFileName(filename.c_str()); recorder->SetOutputFormat(mitk::NavigationDataRecorder::csv); mitk::NavigationData::Pointer naviData = mitk::NavigationData::New(); recorder->AddNavigationData( naviData ); recorder->StartRecording(); for ( unsigned int i=0; i<5; i++ ) { mitk::Point3D pnt; pnt[0] = i + 1; pnt[1] = i + 1/2; pnt[2] = i + 1*3; naviData->SetPosition(pnt); recorder->Update(); } recorder->StopRecording(); std::string prooffilename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest-0.csv"; Poco::File myFile(prooffilename); MITK_TEST_CONDITION(myFile.exists(),"Testing CSV recording on harddisc (does file exist?)."); } static void TestLoadingRecordedXMLFile() { mitk::NavigationDataPlayer::Pointer myPlayer = mitk::NavigationDataPlayer::New(); std::string filenameXML = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest-0.xml"; myPlayer->SetFileName(filenameXML.c_str()); myPlayer->StartPlaying(); //only testing first position at the moment myPlayer->Update(); mitk::NavigationData::Pointer thisData = myPlayer->GetOutput(); mitk::Point3D reference_pnt; reference_pnt[0] = 1; reference_pnt[1] = 1/2; reference_pnt[2] = 1*3; myPlayer->StopPlaying(); MITK_TEST_CONDITION((thisData->GetPosition() == reference_pnt),"Testing load data from xml file."); } static void TestRecordingInvalidData() { std::string tmp = ""; std::ostringstream* stream = new std::ostringstream( std::ostringstream::trunc ); stream->setf( std::ios::fixed, std::ios::floatfield ); // let's create an object of our class mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New(); mitk::NavigationData::Pointer naviData = mitk::NavigationData::New(); recorder->AddNavigationData( naviData ); naviData->SetDataValid(false); //recorder->SetFileName("e:/test"); //recorder->SetRecordingMode( mitk::NavigationDataRecorder::NormalFile ); recorder->StartRecording( stream ); for ( unsigned int i=0; i<5; i++ ) { mitk::Point3D pnt; pnt[0] = i + 1; pnt[1] = i + 1/2; pnt[2] = i +1*3; naviData->SetPosition(pnt); //naviData->Modified(); recorder->Update(); //Sleep(80 + i*10); } recorder->StopRecording(); bool record_success = true; std::string str = stream->str(); int pos = str.find( "ToolCount=" ); std::string sub = stream->str().substr(pos+11, 1); if (sub.compare("1") != 0) {record_success = false;} pos = str.find( "X=" ); sub = stream->str().substr(pos+3, 1); if (sub.compare("1") != 0) {record_success = false;} pos = str.find( "Y=" ); sub = stream->str().substr(pos+3, 1); if (sub.compare("0") != 0) {record_success = false;} pos = str.find( "Z=" ); sub = stream->str().substr(pos+3, 1); if (sub.compare("3") != 0) {record_success = false;} MITK_TEST_CONDITION(record_success,"Testing recording of invalid data."); } static void CleanUp() { std::string filenameXML = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest-0.xml"; std::string filenameCSV = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest-0.csv"; Poco::File myFileXML(filenameXML); Poco::File myFileCSV(filenameCSV); try { if (myFileXML.exists()) {myFileXML.remove();} } catch(std::exception e) { MITK_WARN << "Cannot delete file while cleanup: " << filenameXML; } try { if (myFileCSV.exists()) {myFileCSV.remove();} } catch(std::exception e) { MITK_WARN << "Cannot delete file while cleanup: " << filenameCSV; } } static void TestStartRecordingExceptions() - { + { //Testing Start Recording for exceptions if recording has already started mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New(); std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest.xml"; recorder->SetFileName(filename.c_str()); - bool exceptionThrown = false; + //Testing double call of StartRecording(). mitk::NavigationData::Pointer naviData = mitk::NavigationData::New(); recorder->AddNavigationData( naviData ); recorder->StartRecording(); - try{ recorder->StartRecording(); - } - catch(mitk::IGTException) - { - exceptionThrown = true; - MITK_TEST_OUTPUT(<<"Tested exception for the case recorder already started recording in StartRecording. Application should not crash."); - } - MITK_TEST_CONDITION(exceptionThrown,"Testing exception thrown when recorder starts recording for the case if recording has already started ."); - recorder->StopRecording(); - - //Testing Start Recording for exceptions if no file name or file path set the output is redirected to the console. + MITK_TEST_OUTPUT(<<"Tested double call of StartRecording(). Application should not crash."); + + //Testing exceptions for method StartRecording() when no file is set. mitk::NavigationDataRecorder::Pointer recorder1 = mitk::NavigationDataRecorder::New(); std::string filename1 = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+"Recordertest.xml"; recorder->SetFileName(""); - bool exceptionThrown1 = false; mitk::NavigationData::Pointer naviData1 = mitk::NavigationData::New(); recorder1->AddNavigationData( naviData1 ); - try{ - recorder1->StartRecording(); - } - catch(mitk::IGTIOException) - { - exceptionThrown1 = true; - MITK_TEST_OUTPUT(<<"Tested exception for the case no file name or file path set the output is redirected to the console in StartRecording. Application should not crash."); - } - MITK_TEST_CONDITION(exceptionThrown1,"Testing exception thrown when no file name or file path set the output is redirected to the console."); + try + { + recorder1->StartRecording(); + } + catch(mitk::IGTException) + { + exceptionThrown1 = true; + } + MITK_TEST_CONDITION(exceptionThrown1,"Testing exception throwing when no file name or file path is set."); - //Testing Start Recording method for the stream for exceptions if recording has already started + //Testing double call of StartRecording(stream) method. mitk::NavigationDataRecorder::Pointer recorder2 = mitk::NavigationDataRecorder::New(); std::string tmp = ""; std::ostringstream* stream = new std::ostringstream( std::ostringstream::trunc ); stream->setf( std::ios::fixed, std::ios::floatfield ); - bool exceptionThrown2 = false; recorder2->StartRecording(stream); - try - { recorder2->StartRecording(stream); - } - catch(mitk::IGTException) - { - exceptionThrown2 = true; - MITK_TEST_OUTPUT(<<"Tested exception for the case recorder already started recording in StartRecording. Application should not crash."); - } - MITK_TEST_CONDITION(exceptionThrown2,"Testing exception thrown when recorder starts recording for the stream."); - + recorder2->StopRecording(); + MITK_TEST_OUTPUT(<<"Tested double call of StartRecording(stream). Application should not crash."); + //Testing exceptions if the stream is not good mitk::NavigationDataRecorder::Pointer recorder3 = mitk::NavigationDataRecorder::New(); - //making an empty stream - std::ofstream* stream3 = new std::ofstream(""); + std::ofstream* stream3 = new std::ofstream(""); //making an empty stream bool exceptionThrown3 = false; - try{ - recorder3->StartRecording(stream3); - } + try + { + recorder3->StartRecording(stream3); + } catch(mitk::IGTException) - { - exceptionThrown3 = true; - MITK_TEST_OUTPUT(<<"Tested exception for the case if the stream is not good in StartRecording. Application should not crash."); - } + { + exceptionThrown3 = true; + } MITK_TEST_CONDITION(exceptionThrown3,"Testing exception thrown when the stream in not good."); - - } + } }; /**Documentation * test for the class "NavigationDataRecorder". */ int mitkNavigationDataRecorderTest(int /* argc */, char* /*argv*/[]) { MITK_TEST_BEGIN("NavigationDataRecorder"); mitkNavigationDataRecorderTestClass::TestInstantiation(); mitkNavigationDataRecorderTestClass::TestRecordingWithGivenStream(); mitkNavigationDataRecorderTestClass::TestRecordingOnHarddiscXML(); mitkNavigationDataRecorderTestClass::TestRecordingOnHarddiscXMLZIP(); mitkNavigationDataRecorderTestClass::TestRecordingOnHarddiscCSV(); mitkNavigationDataRecorderTestClass::TestRecordingInvalidData(); mitkNavigationDataRecorderTestClass::TestStartRecordingExceptions(); //Test fails under linux, perhaps reading permission problems, deactivated it temporary //mitkNavigationDataRecorderTestClass::TestLoadingRecordedXMLFile(); mitkNavigationDataRecorderTestClass::CleanUp(); // always end with this! MITK_TEST_END(); }