diff --git a/Modules/IGT/CMakeLists.txt b/Modules/IGT/CMakeLists.txt index 84de8cfe35..7067c79cd6 100644 --- a/Modules/IGT/CMakeLists.txt +++ b/Modules/IGT/CMakeLists.txt @@ -1,46 +1,46 @@ include(MITKIGTHardware.cmake) if(MITK_USE_MICRON_TRACKER) set(INCLUDE_DIRS_INTERNAL ${INCLUDE_DIRS_INTERNAL} ${MITK_MICRON_TRACKER_INCLUDE_DIR}) set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_MICRON_TRACKER_LIB}) endif(MITK_USE_MICRON_TRACKER) if(MITK_USE_MICROBIRD_TRACKER) set(INCLUDE_DIRS_INTERNAL ${INCLUDE_DIRS_INTERNAL} ${MITK_USE_MICROBIRD_TRACKER_INCLUDE_DIR}) set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_USE_MICROBIRD_TRACKER_LIB}) endif(MITK_USE_MICROBIRD_TRACKER) MITK_CREATE_MODULE(MitkIGT SUBPROJECTS MITK-IGT - INCLUDE_DIRS IGTFilters IGTTrackingDevices IGTToolManagement + INCLUDE_DIRS IGTFilters IGTTrackingDevices IGTToolManagement IGTExceptionHandling INTERNAL_INCLUDE_DIRS ${INCLUDE_DIRS_INTERNAL} DEPENDS Mitk tinyxml SceneSerialization ADDITIONAL_LIBS "${ADDITIONAL_LIBS}" ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/IGTTrackingDevices/TrackingVolumeData/ClaronMicron.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/IGTTrackingDevices/TrackingVolumeData/IntuitiveDaVinci.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/IGTTrackingDevices/TrackingVolumeData/NDIAurora.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/IGTTrackingDevices/TrackingVolumeData/NDIAurora_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/IGTTrackingDevices/TrackingVolumeData/NDIAuroraCompactFG_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/IGTTrackingDevices/TrackingVolumeData/NDIAuroraPlanarFG_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/IGTTrackingDevices/TrackingVolumeData/NDIAuroraTabletopFG_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/IGTTrackingDevices/TrackingVolumeData/NDIAuroraTabletopFG_Prototype_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/IGTTrackingDevices/TrackingVolumeData/NDIPolaris.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/IGTTrackingDevices/TrackingVolumeData/NDIPolarisVicra.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/IGTTrackingDevices/TrackingVolumeData/StandardVolume.stl ) MITK_CHECK_MODULE(_RESULT MitkIGT) if(_RESULT) message(STATUS "IGTTutorialStep1 won't be built. Missing: ${_RESULT}") else(_RESULT) ## create IGT config configure_file(mitkIGTConfig.h.in ${PROJECT_BINARY_DIR}/mitkIGTConfig.h @ONLY) # add test programm for serial communication classADD_EXECUTABLE(SerialCommunicationTest IGTTrackingDevices/mitkSerialCommunicationTest.cpp)target_link_libraries(SerialCommunicationTest mitkIGT Mitk tinyxml PocoXML) add_subdirectory(IGTTutorial) add_subdirectory(Testing) endif(_RESULT) diff --git a/Modules/IGT/IGTExceptionHandling/mitkIGTIOException.cpp b/Modules/IGT/IGTExceptionHandling/mitkIGTIOException.cpp new file mode 100644 index 0000000000..299c95c703 --- /dev/null +++ b/Modules/IGT/IGTExceptionHandling/mitkIGTIOException.cpp @@ -0,0 +1,17 @@ +/*=================================================================== + +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 "mitkIGTIOException.h" diff --git a/Modules/IGT/IGTExceptionHandling/mitkIGTIOException.h b/Modules/IGT/IGTExceptionHandling/mitkIGTIOException.h new file mode 100644 index 0000000000..849ea1bfa6 --- /dev/null +++ b/Modules/IGT/IGTExceptionHandling/mitkIGTIOException.h @@ -0,0 +1,34 @@ +/*=================================================================== + +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 IGTIOEXCEPTION_H_INCLUDED +#define IGTIOEXCEPTION_H_INCLUDED + +#include "mitkIGTException.h" +#include "mitkExceptionMacro.h" + +namespace mitk { + /**Documentation + * \brief An object of this class represents an exception of the MITK-IGT module which are releated to the input/output problems (e.g. reading writing files, etc.). + * + * \ingroup IGT + */ class MitkIGT_EXPORT IGTIOException : public mitk::IGTException + { + public: + mitkExceptionClassMacro(IGTIOException,mitk::IGTException); + }; +} // namespace mitk +#endif diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataPlayer.cpp b/Modules/IGT/IGTFilters/mitkNavigationDataPlayer.cpp index aad1e3bc7c..2db1cbcf25 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataPlayer.cpp +++ b/Modules/IGT/IGTFilters/mitkNavigationDataPlayer.cpp @@ -1,536 +1,550 @@ /*=================================================================== 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 "mitkNavigationDataPlayer.h" -//for the pause #include - #include #include +//includes for exceptions +#include "mitkIGTException.h" +#include "mitkIGTIOException.h" + mitk::NavigationDataPlayer::NavigationDataPlayer() : mitk::NavigationDataPlayerBase() { m_NumberOfOutputs = 0; m_Pause = false; m_Playing = false; m_Stream = NULL; m_PlayerMode = NormalFile; m_FileName = ""; m_FileVersion = 1; m_Playing = false; m_Pause = false; m_NumberOfOutputs = 0; m_StartPlayingTimeStamp = 0.0; m_PauseTimeStamp = 0.0; m_parentElement = NULL; m_currentNode = NULL; m_StreamEnd = false; m_StreamSetOutsideFromClass = false; //To get a start time mitk::TimeStamp::GetInstance()->Start(this); } mitk::NavigationDataPlayer::~NavigationDataPlayer() { StopPlaying(); delete m_parentElement; } void mitk::NavigationDataPlayer::GenerateData() { //Only produce new output if the player is started - if (!m_Playing) + if (!m_Playing) //m_Playing==true means player has started { //The output is not valid anymore for (unsigned int index = 0; index < m_NumberOfOutputs; index++) { mitk::NavigationData* output = this->GetOutput(index); assert(output); mitk::NavigationData::Pointer nd = mitk::NavigationData::New(); mitk::NavigationData::PositionType position; mitk::NavigationData::OrientationType orientation(0.0,0.0,0.0,0.0); position.Fill(0.0); nd->SetPosition(position); nd->SetOrientation(orientation); nd->SetDataValid(false); output->Graft(nd); } return; } //first of all get current time TimeStampType now = mitk::TimeStamp::GetInstance()->GetElapsed(); //now we make a little time arithmetic //to get the elapsed time since the start of the player TimeStampType timeSinceStart = now - m_StartPlayingTimeStamp; - //init the vectors std::vector< NavigationData::Pointer > nextCandidates; std::vector< NavigationData::Pointer > lastCandidates; std::vector< NavigationData::TimeStampType > currentTimeOfData; - for (unsigned int index=0; index < m_NumberOfOutputs; index++) { - nextCandidates.push_back(m_NextToPlayNavigationData.at(index)); lastCandidates.push_back(m_NextToPlayNavigationData.at(index)); currentTimeOfData.push_back(timeSinceStart + m_StartTimeOfData.at(index)); } if (m_NextToPlayNavigationData.size() != m_NumberOfOutputs) { MITK_ERROR << "Mismatch in data"; return; } // Now we try to find next NavigationData in the stream: // This means we step through the stream of NavigationDatas until we find // a NavigationData which has a current timestamp (currentTimeOfData) greater - // then the current playing time. Then we store the data in + // than the current playing time. Then we store the data in // m_NextToPlayNavigationData and take the last data (lastCandidates) for the // output of this filter. // // The loop will stop when a suitable NavigationData is found or we reach EOF. // The timestamps of each recorded NavigationData should be equal // therefore we take always the time from the first. - while( nextCandidates[0]->GetTimeStamp() < currentTimeOfData[0]) { for (unsigned int index=0; index < m_NumberOfOutputs; index++) { lastCandidates[index] = nextCandidates.at(index); - - switch(m_FileVersion) + switch(m_FileVersion) // m_FileVersion indicates which XML encoding is used { - case 1: + case 1: nextCandidates[index] = ReadVersion1(); break; - default: //this case should not happen! therefore the return at this point + default: //this case should not happen! therefore return at this point + MITK_ERROR << "File encoding format was not stored, aborting!"; return; break; } //check if the input stream delivered a correct NavigationData object for (unsigned int i = 0; i < m_NumberOfOutputs; i++) { if (nextCandidates.at(index).IsNull()) + //Stops playing because there is now more nextCandidate, the file ended for all outputs { m_StreamEnd = true; StopPlaying(); return; //the case if no NavigationData is found, e.g. EOF, bad stream } } } } //Now lastCandidates stores the new output and nextCandidates is stored to the m_NextToPlay vector for (unsigned int index = 0; index < m_NumberOfOutputs; index++) { mitk::NavigationData* output = this->GetOutput(index); assert(output); - output->Graft(lastCandidates.at(index)); m_NextToPlayNavigationData[index] = nextCandidates.at(index); } } void mitk::NavigationDataPlayer::UpdateOutputInformation() { this->Modified(); // make sure that we need to be updated Superclass::UpdateOutputInformation(); } void mitk::NavigationDataPlayer::InitPlayer() { if (m_Stream == NULL) - { + { StreamInvalid("Playing not possible. Wrong file name or path?"); return; } if (!m_Stream->good()) { StreamInvalid("Playing not possible. Stream is not good!"); return; } - - m_FileVersion = GetFileVersion(m_Stream); //first get the file version - //check if we have a valid version + //first get the file version + m_FileVersion = GetFileVersion(m_Stream); + + //check if we have a valid version: m_FileVersion has to be always bigger than 1 for playing if (m_FileVersion < 1) - { + { StreamInvalid("Playing not possible. Invalid file version!"); return; } - //now read the number of Tracked Tools - if(m_NumberOfOutputs == 0){m_NumberOfOutputs = GetNumberOfNavigationDatas(m_Stream);} + if(m_NumberOfOutputs == 0) {m_NumberOfOutputs = GetNumberOfNavigationDatas(m_Stream);} //with the information about the tracked tool number we can generate the output if (m_NumberOfOutputs > 0) { //Generate the output only if there are changes to the amount of outputs //This happens when the player is stopped and start again with different file if (this->GetNumberOfOutputs() != m_NumberOfOutputs) {SetNumberOfOutputs(m_NumberOfOutputs);} //initialize the player with first data GetFirstData(); //set stream valid m_ErrorMessage = ""; m_StreamValid = true; } else { StreamInvalid("The input stream seems to have NavigationData incompatible format"); return; } } unsigned int mitk::NavigationDataPlayer::GetFileVersion(std::istream* stream) { if (stream==NULL) { MITK_ERROR << "No input stream set!"; - return 0; + mitkThrowException(mitk::IGTException)<<"No input stream set!"; } if (!stream->good()) { - MITK_ERROR << "Stream not good!"; - return 0; + MITK_ERROR << "Stream is not good!"; + mitkThrowException(mitk::IGTException)<<"Stream is not good!"; } int version = 1; TiXmlDeclaration* dec = new TiXmlDeclaration(); *stream >> *dec; - if(strcmp(dec->Version(),"") == 0){ + if(strcmp(dec->Version(),"") == 0) + { MITK_ERROR << "The input stream seems to have XML incompatible format"; - return 0; + mitkThrowException(mitk::IGTIOException) << "The input stream seems to have XML incompatible format"; } m_parentElement = new TiXmlElement(""); *stream >> *m_parentElement; //2nd line this is the file version std::string tempValue = m_parentElement->Value(); if(tempValue != "Version") { if(tempValue == "Data"){ m_parentElement->QueryIntAttribute("version",&version); } } else { m_parentElement->QueryIntAttribute("Ver",&version); } if (version > 0) return version; else return 0; } unsigned int mitk::NavigationDataPlayer::GetNumberOfNavigationDatas(std::istream* stream) { if (stream == NULL) - { + { MITK_ERROR << "No input stream set!"; - return 0; + mitkThrowException(mitk::IGTException)<<"No input stream set!"; } if (!stream->good()) - { + { MITK_ERROR << "Stream not good!"; - return 0; + mitkThrowException(mitk::IGTException)<<"Stream not good!"; } //If something has changed in a future version of the XML definition e.g. navigationcount or addional parameters //catch this here with a select case block (see GenerateData() method) int numberOfTools = 0; std::string tempValue = m_parentElement->Value(); if(tempValue == "Version"){ *stream >> *m_parentElement; } m_parentElement->QueryIntAttribute("ToolCount",&numberOfTools); if (numberOfTools > 0) return numberOfTools; return 0; } mitk::NavigationData::Pointer mitk::NavigationDataPlayer::ReadVersion1() { if (m_Stream == NULL) { m_Playing = false; MITK_ERROR << "Playing not possible. Wrong file name or path? "; - return NULL; + mitkThrowException(mitk::IGTException) << "Playing not possible. Wrong file name or path? "; } if (!m_Stream->good()) { m_Playing = false; MITK_ERROR << "Playing not possible. Stream is not good!"; - return NULL; + mitkThrowException(mitk::IGTException) << "Playing not possible. Stream is not good!"; } /*TiXmlElement* elem = new TiXmlElement(""); m_currentNode = m_parentElement->IterateChildren(m_currentNode); if(m_currentNode) { elem = m_currentNode->ToElement(); }*/ TiXmlElement* elem; m_currentNode = m_parentElement->IterateChildren(m_currentNode); bool delElem; if(m_currentNode) { elem = m_currentNode->ToElement(); + if(elem==NULL) + { + mitkThrowException(mitk::IGTException) << "Cannot find element: Is this file damaged?"; + } delElem = false; } else { elem = new TiXmlElement(""); delElem = true; } mitk::NavigationData::Pointer nd = this->ReadNavigationData(elem); if(delElem) delete elem; return nd; } - void mitk::NavigationDataPlayer::StartPlaying() { if (m_Stream == NULL) { m_Playing = false; - + //Perhaps the SetStream method was not called so we do this when a FileName is set with SetStream(PlayerMode) if (m_FileName != "") { - //The PlayerMode is initialized with LastSetStream - //SetStream also calls InitPlayer() - SetStream(m_PlayerMode); + //The PlayerMode is initialized with LastSetStream + //CreateStreamFromFilename also calls InitPlayer() + try + { + CreateStreamFromFilename(); + } + catch(mitk::IGTIOException e) + { + MITK_ERROR << "Cannot create stream from filename, please check the stream"; + throw e; //TODO replace by macro + } + catch(mitk::IGTException e2) + { + MITK_ERROR << "Cannot open the file, please check the file"; + throw e2; //TODO replace by macro + } } //now check again if (m_Stream == NULL) { StopPlaying(); MITK_ERROR << "Playing not possible. Wrong file name or path?"; - return; + mitkThrowException(mitk::IGTException) << "Playing not possible. Wrong file name or path?"; } } if (!m_Playing && m_Stream->good()) { - m_Playing = true; //starts the player + m_Playing = true; m_StartPlayingTimeStamp = mitk::TimeStamp::GetInstance()->GetElapsed(); } else { MITK_ERROR << "Player already started or stream is not good!"; StopPlaying(); } } + + void mitk::NavigationDataPlayer::StopPlaying() { //re init all data!! for playing again with different data //only PlayerMode and FileName are not changed m_Pause = false; m_Playing = false; if (!m_StreamSetOutsideFromClass) {delete m_Stream;} m_Stream = NULL; m_FileVersion = 1; m_Playing = false; m_Pause = false; m_StartPlayingTimeStamp = 0.0; m_PauseTimeStamp = 0.0; m_NextToPlayNavigationData.clear(); m_StartTimeOfData.clear(); } void mitk::NavigationDataPlayer::GetFirstData() { //Here we read the first lines of input (dependend on the number of inputs) for (unsigned int index=0; index < m_NumberOfOutputs; index++) { //Here we init the vector for later use m_NextToPlayNavigationData.push_back(NULL); m_StartTimeOfData.push_back(0.0); mitk::NavigationData::Pointer nd = this->GetOutput(index); switch(m_FileVersion) { case 1: m_NextToPlayNavigationData[index] = ReadVersion1(); //check if there is valid data in it if (m_NextToPlayNavigationData[index].IsNull()) { m_StreamEnd = true; - StopPlaying(); - MITK_ERROR << "XML File is corrupt or has no NavigationData" << std::endl; - return; + mitkThrowException(mitk::IGTIOException) << "XML File is corrupt or has no NavigationData."; } //Have a look it the output was set already without this check the pipline will disconnect after a start/stop cycle - if (nd.IsNull()) - this->SetNthOutput(index, m_NextToPlayNavigationData[index]); + if (nd.IsNull()) {this->SetNthOutput(index, m_NextToPlayNavigationData[index]);} m_StartTimeOfData[index] = m_NextToPlayNavigationData[index]->GetTimeStamp(); break; + default: //this case should not happen! therefore the return at this point return; break; } } } void mitk::NavigationDataPlayer::Pause() { //player runs and pause was called -> pause the player if(m_Playing && !m_Pause) { m_Playing = false; m_Pause = true; m_PauseTimeStamp = mitk::TimeStamp::GetInstance()->GetElapsed(); } else { MITK_ERROR << "Player is either not started or already is paused" << std::endl; } } void mitk::NavigationDataPlayer::Resume() { //player is in pause mode -> play at the last position if(!m_Playing && m_Pause) { m_Playing = true; m_Pause = false; mitk::NavigationData::TimeStampType now = mitk::TimeStamp::GetInstance()->GetElapsed(); // in this case m_StartPlayingTimeStamp is set to the total elapsed time with NO playback m_StartPlayingTimeStamp = now - (m_PauseTimeStamp - m_StartPlayingTimeStamp); } else { MITK_ERROR << "Player is not paused!" << std::endl; } } -void mitk::NavigationDataPlayer::SetStream( PlayerMode /*mode*/ ) +void mitk::NavigationDataPlayer::CreateStreamFromFilename() { m_Stream = NULL; if (!itksys::SystemTools::FileExists(m_FileName.c_str())) { - MITK_ERROR << "File dont exist!" << std::endl; - return; + mitkThrowException(mitk::IGTIOException) << "File does not exist!"; } + switch(m_PlayerMode) { case NormalFile: - m_Stream = new std::ifstream(m_FileName.c_str()); - m_StreamSetOutsideFromClass = false; - + m_StreamSetOutsideFromClass = false; break; - case ZipFile: + case ZipFile: m_Stream = NULL; MITK_ERROR << "Sorry no ZipFile support yet"; - break; + default: m_Stream = NULL; + mitkThrowException(mitk::IGTException) << "The stream is NULL"; break; } this->Modified(); InitPlayer(); } void mitk::NavigationDataPlayer::SetStream( std::istream* stream ) { if ( (stream == NULL) || (!stream->good())) { + // throw an exception for stream=NULL or it is not good + mitkThrowException(mitk::IGTException) << "The stream is NULL or it is not good"; m_StreamEnd = true; - MITK_ERROR << "The stream is not good"; return; } m_Stream = stream; m_StreamSetOutsideFromClass = true; this->Modified(); InitPlayer(); } bool mitk::NavigationDataPlayer::IsAtEnd() { return this->m_StreamEnd; } void mitk::NavigationDataPlayer::StreamInvalid(std::string message) { m_StreamEnd = true; StopPlaying(); m_ErrorMessage = message; m_StreamValid = false; - MITK_ERROR << m_ErrorMessage; - return; -} + mitkThrowException(mitk::IGTIOException) << "Invalid stream!"; +} \ No newline at end of file diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataPlayer.h b/Modules/IGT/IGTFilters/mitkNavigationDataPlayer.h index 7f714bd76f..07e412437e 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataPlayer.h +++ b/Modules/IGT/IGTFilters/mitkNavigationDataPlayer.h @@ -1,205 +1,225 @@ /*=================================================================== 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 MITKNavigationDataPlayer_H_HEADER_INCLUDED_ #define MITKNavigationDataPlayer_H_HEADER_INCLUDED_ #include #include #include //for the Recording Mode enum #include "mitkTrackingDevice.h" #include #include "tinyxml.h" #include namespace mitk { /**Documentation * \brief This class is used to play recorded (see mitkNavigationDataRecorder class) files. * * If you want to play a file you have to set an input stream. This can be an own one (use StartPlaying(std::istream*)) * or a preset (use StartPlaying()). The presets are NormalFile and ZipFile and can be set with the method * SetPlayerMode(PlayerMode). The presets need a FileName. Therefore the FileName must be set before the preset. * For pausing the player call Pause(). A call of Resume() will continue the playing. * * * \ingroup IGT */ class MitkIGT_EXPORT NavigationDataPlayer : public NavigationDataPlayerBase { public: mitkClassMacro(NavigationDataPlayer, NavigationDataPlayerBase); itkNewMacro(Self); /** * \brief sets the file name and path for the PlayerMode NormalFile and ZipFile */ itkSetStringMacro(FileName); /** * \brief returns the file name and path for the PlayerMode NormalFile and ZipFile */ itkGetStringMacro(FileName); - + /** * \brief Used for pipeline update just to tell the pipeline that we always have to update */ virtual void UpdateOutputInformation(); /** - * \brief This method starts the player. - * - * Before the stream has to be set. Either with a PlayingMode (SetStream(PlayerMode)) and FileName. Or - * with an own inputstream (SetStream(istream*)). - */ + * \brief This method starts the player. + * + * Before the stream has to be set. Either with a PlayingMode (SetStream(PlayerMode)) and FileName. Or + * with an own inputstream (SetStream(istream*)). + * + * @throw mitk::IGTIOException Throws an exception if the file cannot be opened. + * @throw mitk::IGTIOException Throws an exception if there is no valid filename. + * @throw mitk::IGTIOException Throws an exception if the file is damaged. + * @throw mitk::IGTException Throws an exception if there is no stream (i.e stream=NULL). + */ void StartPlaying(); /** - * \brief Stops the player and closes the stream. After a call of StopPlaying() - * StartPlaying() must be called to get new output data - * - * \warning the output is generated in this method because we know first about the number of output after - * reading the first lines of the XML file. Therefore you should assign your output after the call of this method - */ + * \brief Stops the player and closes the stream. After a call of StopPlaying() + * StartPlaying() must be called to get new output data + * + * \warning the output is generated in this method because we know first about the number of output after + * reading the first lines of the XML file. Therefore you should assign your output after the call of this method + */ void StopPlaying(); /** - * \brief This method pauses the player. If you want to play again call Resume() - * - *\warning This method is not tested yet. It is not save to use! - */ + * \brief This method pauses the player. If you want to play again call Resume() + */ void Pause(); /** - * \brief This method resumes the player when it was paused. - * - *\warning This method is not tested yet. It is not save to use! - */ + * \brief This method resumes the player when it was paused. + */ void Resume(); /** - * \brief This method checks if player arrived at end of file. - * - *\warning This method is not tested yet. It is not save to use! - */ + * \brief This method checks if player arrived at end of file. + * + */ bool IsAtEnd(); /** - * \brief The PlayerMode is used for generating a presetted output stream. You do not need to - * set it if you want to use your own stream. - * - * There are: - * NormalFile: ifstream - * ZipFile: not implemented yet - * - *\warning The ZipFile Mode is not implemented yet - */ + * \brief The PlayerMode is used for generating a presetted output stream. You do not need to + * set it if you want to use your own stream. + * + * There are: + * NormalFile: ifstream + * ZipFile: not implemented yet + * + *\warning The ZipFile Mode is not implemented yet + */ enum PlayerMode { NormalFile, ZipFile }; - /** - * \brief sets the recording mode which causes different types of output streams - * This method is overloaded with SetStream( ostream* ) - */ - void SetStream(PlayerMode mode); + /** @return Returns the current playing mode of the player. */ + itkGetMacro(PlayerMode,PlayerMode); + + /** @brief Sets the playing mode of the player. */ + itkSetMacro(PlayerMode,PlayerMode); /** - * \brief sets the recording mode which causes different types of output streams - * This method is overloaded with SetStream( PlayerMode ) - */ + * \brief Sets the stream of this player. + * @throw mitk::IGTException Throws an exception if stream is NULL or if it is not good. + */ void SetStream(std::istream* stream); protected: NavigationDataPlayer(); virtual ~NavigationDataPlayer(); typedef mitk::NavigationData::TimeStampType TimeStampType; /** - * \brief filter execute method - */ + * \brief filter execute method + */ virtual void GenerateData(); /** - * \brief Returns the file version out of the XML document. - */ + * \brief Creates a stream out of the filename given by the variable m_FileName. + * The stream is then set to m_Stream. + * + * @throw mitk::IGTIOException Throws an exception if file does not exist + * @throw mitk::IGTException Throws an exception if the stream is NULL + */ + void CreateStreamFromFilename(); + + /** + * \brief Returns the file version out of the XML document. + * @throw mitk::IGTException Throws an mitk::IGTException an exception if stream is NULL or not good. + * @throw mitk::IGTIOException Throws an mitk::IGTIOException if the stream has an incompatible XML format. + */ unsigned int GetFileVersion(std::istream* stream); /** - * \brief Returns the number of tracked tools out of the XML document. - */ + * \brief Returns the number of tracked tools out of the XML document. + * @throw Throws an exception if stream is NULL. + * @throw Throws an exception if the input stream has an XML incompatible format. + */ unsigned int GetNumberOfNavigationDatas(std::istream* stream); /** - * \brief Gets the first data for initializing the player - */ + * \brief Gets the first data for initializing the player + */ void GetFirstData(); /** - * \brief This method reads one line of the XML document and returns the data as a NavigationData object - * If there is a new file version another method must be added which reads this data. - */ + * \brief This method reads one line of the XML document and returns the data as a NavigationData object + * If there is a new file version another method must be added which reads this data. + * @throw mitk::IGTException Throws an exceptions if file is damaged. + */ mitk::NavigationData::Pointer ReadVersion1(); /** - * \brief This method initializes the player with first data - */ + * \brief This method initializes the player with first data + */ void InitPlayer(); std::istream* m_Stream; ///< stores a pointer to the input stream bool m_StreamSetOutsideFromClass; ///< stores if the stream was created in this class and must be deleted in the end PlayerMode m_PlayerMode; ///< stores the mode for the presetted PlayerMode sieh enum PlayerMode std::string m_FileName; ///< stores the filename unsigned int m_FileVersion; ///< indicates which XML encoding is used bool m_Playing; ///< indicates whether the generateoutput method generates new output or not bool m_Pause; ///< indicates if the player is paused unsigned int m_NumberOfOutputs; ///< stores the number of outputs known from the XML document TimeStampType m_StartPlayingTimeStamp; ///< the starttime of the playing set in the method StartPlaying() TimeStampType m_PauseTimeStamp; ///< stores the beginning of a pause std::vector m_NextToPlayNavigationData; ///< stores the next possible candidate for playing std::vector m_StartTimeOfData; ///< stores the start time of the different tools TiXmlElement * m_parentElement; TiXmlNode * m_currentNode; bool m_StreamEnd; ///< stores if the input stream arrived at end - + + /** + * @brief This is a helping method which gives an error message and throws an exception with the given message. + * It can be used if a stream is found to be invalid. + * + * @throw mitk::IGTIOException Always throws an exception. + */ void StreamInvalid(std::string message); ///< help method which sets the stream invalid and displays an error }; } // namespace mitk #endif /* MITKNavigationDataPlayer_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataPlayerBase.cpp b/Modules/IGT/IGTFilters/mitkNavigationDataPlayerBase.cpp index 39211ae84f..62db618854 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataPlayerBase.cpp +++ b/Modules/IGT/IGTFilters/mitkNavigationDataPlayerBase.cpp @@ -1,117 +1,118 @@ /*=================================================================== 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 "mitkNavigationDataPlayerBase.h" mitk::NavigationDataPlayerBase::NavigationDataPlayerBase() : m_StreamValid(true), m_ErrorMessage("") { m_Name ="Navigation Data Player Source"; } mitk::NavigationDataPlayerBase::~NavigationDataPlayerBase() { } void mitk::NavigationDataPlayerBase::UpdateOutputInformation() { this->Modified(); // make sure that we need to be updated Superclass::UpdateOutputInformation(); } mitk::NavigationData::Pointer mitk::NavigationDataPlayerBase::ReadNavigationData(TiXmlElement* elem) { + if (elem == NULL) {mitkThrow() << "Error: Element is NULL!";} + mitk::NavigationData::Pointer nd = mitk::NavigationData::New(); mitk::NavigationData::PositionType position; mitk::NavigationData::OrientationType orientation(0.0,0.0,0.0,0.0); mitk::NavigationData::TimeStampType timestamp = -1; mitk::NavigationData::CovarianceMatrixType matrix; bool hasPosition = true; bool hasOrientation = true; bool dataValid = false; position.Fill(0.0); matrix.SetIdentity(); - elem->QueryDoubleAttribute("Time",×tamp); if (timestamp == -1) { return NULL; //the calling method should check the return value if it is valid/not NULL } elem->QueryFloatAttribute("X", &position[0]); elem->QueryFloatAttribute("Y", &position[1]); elem->QueryFloatAttribute("Z", &position[2]); elem->QueryFloatAttribute("QX", &orientation[0]); elem->QueryFloatAttribute("QY", &orientation[1]); elem->QueryFloatAttribute("QZ", &orientation[2]); elem->QueryFloatAttribute("QR", &orientation[3]); elem->QueryFloatAttribute("C00", &matrix[0][0]); elem->QueryFloatAttribute("C01", &matrix[0][1]); elem->QueryFloatAttribute("C02", &matrix[0][2]); elem->QueryFloatAttribute("C03", &matrix[0][3]); elem->QueryFloatAttribute("C04", &matrix[0][4]); elem->QueryFloatAttribute("C05", &matrix[0][5]); elem->QueryFloatAttribute("C10", &matrix[1][0]); elem->QueryFloatAttribute("C11", &matrix[1][1]); elem->QueryFloatAttribute("C12", &matrix[1][2]); elem->QueryFloatAttribute("C13", &matrix[1][3]); elem->QueryFloatAttribute("C14", &matrix[1][4]); elem->QueryFloatAttribute("C15", &matrix[1][5]); int tmpval = 0; elem->QueryIntAttribute("Valid", &tmpval); if (tmpval == 0) dataValid = false; else dataValid = true; tmpval = 0; elem->QueryIntAttribute("hO", &tmpval); if (tmpval == 0) hasOrientation = false; else hasOrientation = true; tmpval = 0; elem->QueryIntAttribute("hP", &tmpval); if (tmpval == 0) hasPosition = false; else hasPosition = true; nd->SetTimeStamp(timestamp); nd->SetPosition(position); nd->SetOrientation(orientation); nd->SetCovErrorMatrix(matrix); nd->SetDataValid(dataValid); nd->SetHasOrientation(hasOrientation); nd->SetHasPosition(hasPosition); return nd; } diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataPlayerBase.h b/Modules/IGT/IGTFilters/mitkNavigationDataPlayerBase.h index 61a598b12b..95b314cf3b 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataPlayerBase.h +++ b/Modules/IGT/IGTFilters/mitkNavigationDataPlayerBase.h @@ -1,77 +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. */ 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 38f44e91c1..ed7cb572ff 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.cpp +++ b/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.cpp @@ -1,364 +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 - - - - - +//headers for exceptions +#include "mitkIGTException.h" +#include "mitkIGTIOException.h" 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 timpstamp at beginning + //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) - { - std::cout << "Already recording please stop before start new recording session" << std::endl; - return; - } - - if (m_Stream == NULL) + if(!m_Recording) { - 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; - 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; - break; - case ZipFile: - stream = &std::cout; - std::cout << "Sorry no ZipFile support yet"; - break; - default: - stream = &std::cout; - break; + case NormalFile: + if (m_FileName == "") //Check if there is a file name and path + { + std::string message = "No file name or file path set."; + MITK_ERROR << message; + mitkThrowException(mitk::IGTException) << message; + } + else + { + stream = new std::ofstream(ss.str().c_str()); + } + break; + + case ZipFile: + stream = &std::cout; + MITK_WARN << "Sorry no ZipFile support yet"; + break; + + default: + stream = &std::cout; + break; + } + m_Stream = stream; + m_StreamMustBeDeleted = true; + m_firstLine = true; + m_RecordCounter = 0; + StartRecording(stream); } - m_Stream = stream; - m_StreamMustBeDeleted = true; - m_firstLine = true; - m_RecordCounter = 0; - StartRecording(stream); - } - - - - + } +else if (m_Recording) + { + MITK_WARN << "Already recording please stop before start new recording session"; + return; + } } + void mitk::NavigationDataRecorder::StartRecording(std::ostream* stream) { if (m_Recording) { - std::cout << "Already recording please stop before start new recording session" << std::endl; + MITK_WARN << "Already recording please stop before start new recording session"; return; } m_Stream = stream; m_Stream->precision(10); //TODO store date and GMT time - if (m_Stream) - { + //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 fcc18add9c..2c11f6e317 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.h +++ b/Modules/IGT/IGTFilters/mitkNavigationDataRecorder.h @@ -1,211 +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 - }; + 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*) - */ + /** + * 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 - */ + /** + * 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 + /**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); + 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 + 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/IGTFilters/mitkNavigationDataSequentialPlayer.cpp b/Modules/IGT/IGTFilters/mitkNavigationDataSequentialPlayer.cpp index 326a1b014a..3cdb0f0da0 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataSequentialPlayer.cpp +++ b/Modules/IGT/IGTFilters/mitkNavigationDataSequentialPlayer.cpp @@ -1,199 +1,227 @@ /*=================================================================== 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 "mitkNavigationDataSequentialPlayer.h" -//for the pause -#include +#include //for the pause #include #include #include +//Exceptions +#include "mitkIGTException.h" +#include "mitkIGTIOException.h" + mitk::NavigationDataSequentialPlayer::NavigationDataSequentialPlayer() : mitk::NavigationDataPlayerBase() , m_Doc(new TiXmlDocument) , m_DataElem(0) , m_CurrentElem(0) , m_Repeat(false) , m_NumberOfSnapshots(0) , m_LastGoTo(0) { } mitk::NavigationDataSequentialPlayer::~NavigationDataSequentialPlayer() { delete m_Doc; } void mitk::NavigationDataSequentialPlayer::ReinitXML() { m_DataElem = m_Doc->FirstChildElement("Data"); int toolcount; if(!m_DataElem) + { MITK_WARN << "Data element not found"; + mitkThrowException(mitk::IGTException) << "Data element not found"; + } else { m_DataElem->QueryIntAttribute("ToolCount", &toolcount); this->SetNumberOfOutputs(toolcount); mitk::NavigationData::Pointer emptyNd = mitk::NavigationData::New(); mitk::NavigationData::PositionType position; mitk::NavigationData::OrientationType orientation(0.0,0.0,0.0,0.0); position.Fill(0.0); emptyNd->SetPosition(position); emptyNd->SetOrientation(orientation); emptyNd->SetDataValid(false); mitk::NavigationData::Pointer tmp; for (unsigned int index = 0; index < this->GetNumberOfOutputs(); index++) { tmp = mitk::NavigationData::New(); tmp->Graft(emptyNd); this->SetNthOutput(index, tmp); } // find out _NumberOfSnapshots m_NumberOfSnapshots = 0; TiXmlElement* nextND = m_DataElem->FirstChildElement("NavigationData"); while(nextND) { ++m_NumberOfSnapshots; nextND = nextND->NextSiblingElement("NavigationData"); } // e.g. 12 nd found and 2 tools used => number of snapshots is 12:2=6 m_NumberOfSnapshots = m_NumberOfSnapshots/toolcount; } } void mitk::NavigationDataSequentialPlayer::GoToSnapshot(int i) { + if(!m_Repeat && (this->GetNumberOfSnapshots() numOfUpdateCalls = 4 if(m_LastGoTo <= i) numOfUpdateCalls = i - m_LastGoTo; // goto(4), m_LastGoTo=7 => numOfUpdateCalls = 7 else { if(!m_Repeat) { - MITK_WARN << "cannot go back to snapshot " << i << " because the " + std::stringstream message; + message <<"cannot go back to snapshot " << i << " because the " << this->GetNameOfClass() << " is configured to not repeat the" << " navigation data"; - + MITK_WARN << message; + mitkThrowException(mitk::IGTException) << message; } else { numOfUpdateCalls = (m_NumberOfSnapshots - m_LastGoTo) + i; } } for(int j=0; jUpdate(); m_LastGoTo = i; } void mitk::NavigationDataSequentialPlayer:: SetFileName(const std::string& _FileName) { m_FileName = _FileName; - + if(!m_Doc->LoadFile(m_FileName)) { this->SetNumberOfOutputs(0); std::ostringstream s; s << "File " << _FileName << " could not be loaded"; - throw std::invalid_argument(s.str()); + mitkThrowException(mitk::IGTIOException)<ReinitXML(); + } this->Modified(); } void mitk::NavigationDataSequentialPlayer:: SetXMLString(const std::string& _XMLString) { m_XMLString = _XMLString; - - m_Doc->Parse( m_XMLString.c_str() ); - this->ReinitXML(); - + if((m_Doc->Parse( m_XMLString.c_str()))== NULL) + { + this->ReinitXML(); + } + else + { + //if the string is not an XML string + std::ostringstream s; + s << "String" << _XMLString << " is not an XML string"; + mitkThrowException(mitk::IGTIOException)<Modified(); } void mitk::NavigationDataSequentialPlayer::GenerateData() { assert(m_DataElem); - - // very important: go through the tools (there could be more then one) + // very important: go through the tools (there could be more than one) mitk::NavigationData::Pointer tmp; - //MITK_INFO << "this->GetNumberOfOutputs()" << this->GetNumberOfOutputs(); + for (unsigned int index = 0; index < this->GetNumberOfOutputs(); index++) { - //MITK_INFO << "index" << index; // go to the first element if(!m_CurrentElem) m_CurrentElem = m_DataElem->FirstChildElement("NavigationData"); // go to the next element else + { m_CurrentElem = m_CurrentElem->NextSiblingElement(); + } // if repeat is on: go back to the first element (prior calls delivered NULL // elem) if(!m_CurrentElem && m_Repeat) m_CurrentElem = m_DataElem->FirstChildElement("NavigationData"); mitk::NavigationData* output = this->GetOutput(index); tmp = this->ReadVersion1(); if(tmp.IsNotNull()) { output->Graft(tmp); m_StreamValid = true; } else // no valid output { output->SetDataValid(false); m_StreamValid = false; + m_ErrorMessage = "Error: Cannot parse input file."; + mitkThrowException(mitk::IGTException)<ReadNavigationData(elem); } void mitk::NavigationDataSequentialPlayer::UpdateOutputInformation() { this->Modified(); // make sure that we need to be updated Superclass::UpdateOutputInformation(); } + + + diff --git a/Modules/IGT/IGTFilters/mitkNavigationDataSequentialPlayer.h b/Modules/IGT/IGTFilters/mitkNavigationDataSequentialPlayer.h index 4354ef96b9..d99e842e7f 100644 --- a/Modules/IGT/IGTFilters/mitkNavigationDataSequentialPlayer.h +++ b/Modules/IGT/IGTFilters/mitkNavigationDataSequentialPlayer.h @@ -1,110 +1,122 @@ /*=================================================================== 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 MITKNavigationDataSequentialPlayer_H_HEADER_INCLUDED_ #define MITKNavigationDataSequentialPlayer_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 NavigationDataSequentialPlayer : public NavigationDataPlayerBase { public: mitkClassMacro(NavigationDataSequentialPlayer, NavigationDataPlayerBase); itkNewMacro(Self); /** - * \brief sets the file name and path (if XMLString is set, this is neglected) - */ + * \brief sets the file name and path (if XMLString is set, this is neglected) + * @throw mitk::IGTIOException Throws an exception if the given file cannot be loaded. + */ void SetFileName(const std::string& _FileName); /** - * \brief returns the file name and path + * \brief returns the file name and path */ itkGetStringMacro(FileName); /** * \brief sets a xml string (by this, the xml string is not read from file) + * @throw mitk::IGTExcepton Throws an mitk::IGTExcepton if the string to set is not an XMLString */ void SetXMLString(const std::string& _XMLString); /** * \brief returns the current xml string */ itkGetStringMacro(XMLString); - /// - /// set to true if the data player should repeat the outputs - /// + /** + * @brief Set to true if the data player should repeat the outputs. + */ itkSetMacro(Repeat, bool); - /// - /// set if the data player should repeat the outputs - /// + + /** + * @return Returns if the data player should repeat the outputs. + */ itkGetMacro(Repeat, bool); - /// - /// \return the number of navigation data snapshots available in the file - /// + + /** + * @return Returns the number of navigation data snapshots available in the file + */ itkGetMacro(NumberOfSnapshots, unsigned int); - /// - /// advance the output to the i-th snapshot - /// e.g. if you want to have the NavData of snapshot - /// 17 then you can call GoToSnapshot(17). index begins at 1! - /// you can then also go back to snapshot 1 with GoToSnapshot(1) - /// + /** + * advance the output to the i-th snapshot + * e.g. if you want to have the NavData of snapshot + * 17 then you can call GoToSnapshot(17). index begins at 1! + * you can then also go back to snapshot 1 with GoToSnapshot(1) + * + * @throw mitk::IGTException Throws an exception if cannot go back to particular snapshot. + */ void GoToSnapshot(int i); /** * \brief Used for pipeline update just to tell the pipeline * that we always have to update */ virtual void UpdateOutputInformation(); protected: NavigationDataSequentialPlayer(); virtual ~NavigationDataSequentialPlayer(); + + /** + * @throw mitk::IGTException Throws an exception if data element is not found. + */ void ReinitXML(); + mitk::NavigationData::Pointer ReadVersion1(); - /// - /// do the work here - /// + + /** + * @throw mitk::IGTException Throws an exception if cannot parse input file + */ virtual void GenerateData(); std::string m_FileName; std::string m_XMLString; TiXmlDocument* m_Doc; TiXmlElement* m_DataElem; TiXmlElement* m_CurrentElem; bool m_Repeat; unsigned int m_NumberOfSnapshots; int m_LastGoTo; }; } // namespace mitk #endif /* MITKNavigationDataSequentialPlayer_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageDeserializer.cpp b/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageDeserializer.cpp index 1f5da4113f..12308ea537 100644 --- a/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageDeserializer.cpp +++ b/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageDeserializer.cpp @@ -1,116 +1,120 @@ /*=================================================================== 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. ===================================================================*/ //Poco headers #include "Poco/Zip/Decompress.h" #include "Poco/Path.h" #include "Poco/File.h" #include "mitkNavigationToolStorageDeserializer.h" #include #include #include "mitkNavigationToolReader.h" //POCO #include + +#include "mitkIGTException.h" +#include "mitkIGTIOException.h" + + mitk::NavigationToolStorageDeserializer::NavigationToolStorageDeserializer(mitk::DataStorage::Pointer dataStorage) { m_DataStorage = dataStorage; //create temp directory for this reader m_tempDirectory = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory() + Poco::Path::separator() + "tempNavigationToolDeserializer"; Poco::File myFile(m_tempDirectory); myFile.createDirectory(); } mitk::NavigationToolStorageDeserializer::~NavigationToolStorageDeserializer() { //remove temp directory Poco::File myFile(m_tempDirectory); try { if (myFile.exists()) myFile.remove(); } catch(...) { MITK_ERROR << "Can't remove temp directory " << m_tempDirectory << "!"; } } mitk::NavigationToolStorage::Pointer mitk::NavigationToolStorageDeserializer::Deserialize(std::string filename) { bool success = false; //decomress zip file into temporary directory - success = decomressFiles(filename,m_tempDirectory); - - //currently returns an empty storage in case of an error. TODO when exception handling is availiable in MITK: Throw an exception? - if (!success) {return mitk::NavigationToolStorage::New();} + decomressFiles(filename,m_tempDirectory); //now read all files and convert them to navigation tools mitk::NavigationToolStorage::Pointer returnValue = mitk::NavigationToolStorage::New(m_DataStorage); bool cont = true; int i; for (i=0; cont==true; i++) { std::string fileName = m_tempDirectory + Poco::Path::separator() + "NavigationTool" + convertIntToString(i) + ".tool"; mitk::NavigationToolReader::Pointer myReader = mitk::NavigationToolReader::New(); mitk::NavigationTool::Pointer readTool = myReader->DoRead(fileName); if (readTool.IsNull()) cont = false; else returnValue->AddTool(readTool); //delete file std::remove(fileName.c_str()); } if(i==1) { + //throw an exception here in case of not finding any tool m_ErrorMessage = "Error: did not find any tool. \n Is this a tool storage file?"; - MITK_ERROR << "Error: did not find any tool. Is this a tool storage file?"; + mitkThrowException(mitk::IGTException)<<"Error: did not find any tool. \n Is this a tool storage file?"; } return returnValue; } std::string mitk::NavigationToolStorageDeserializer::convertIntToString(int i) - { - std::string s; - std::stringstream out; - out << i; - s = out.str(); - return s; - } +{ +std::string s; +std::stringstream out; +out << i; +s = out.str(); +return s; +} -bool mitk::NavigationToolStorageDeserializer::decomressFiles(std::string filename,std::string path) - { +void mitk::NavigationToolStorageDeserializer::decomressFiles(std::string filename,std::string path) +{ std::ifstream file( filename.c_str(), std::ios::binary ); if (!file.good()) { m_ErrorMessage = "Cannot open '" + filename + "' for reading"; - return false; + mitkThrowException(mitk::IGTException)<<"Cannot open"+filename+" for reading"; } + try { Poco::Zip::Decompress unzipper( file, Poco::Path( path ) ); unzipper.decompressAllFiles(); file.close(); } + catch(Poco::IllegalStateException e) //temporary solution: replace this by defined exception handling later! - { + { m_ErrorMessage = "Error: wrong file format! \n (please only load tool storage files)"; - MITK_ERROR << "Error: wrong file format! (please only load tool storage files)"; - return false; + MITK_ERROR << m_ErrorMessage; + mitkThrowException(mitk::IGTException) << m_ErrorMessage; } - return true; } diff --git a/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageDeserializer.h b/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageDeserializer.h index 0dfb1e4a07..e7411c60ed 100644 --- a/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageDeserializer.h +++ b/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageDeserializer.h @@ -1,68 +1,72 @@ /*=================================================================== 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 NAVIGATIONTOOLSTORAGEDESERIALIZER_H_INCLUDED #define NAVIGATIONTOOLSTORAGEDESERIALIZER_H_INCLUDED //itk headers #include //mitk headers #include #include #include "mitkNavigationToolStorage.h" #include namespace mitk { /**Documentation * \brief This class offers methods to load an object of the class NavigationToolStorage * from the harddisc. * * \ingroup IGT */ class MitkIGT_EXPORT NavigationToolStorageDeserializer : public itk::Object { public: mitkClassMacro(NavigationToolStorageDeserializer,itk::Object); mitkNewMacro1Param(Self,mitk::DataStorage::Pointer); /** * @brief Loads a collection of navigation tools represented by a mitk::NavigationToolStorage * from a file. * @return Returns the storage which was loaded or an empty storage if there was an error in the loading process. - * + * @throw mitk::IGTException Throws an Exception if the file cannot be decopressed. + * @throw mitk::IGTException Throws an Exception if no tool was found inside the storage. */ mitk::NavigationToolStorage::Pointer Deserialize(std::string filename); itkGetMacro(ErrorMessage,std::string); protected: NavigationToolStorageDeserializer(mitk::DataStorage::Pointer dataStorage); ~NavigationToolStorageDeserializer(); std::string m_ErrorMessage; mitk::DataStorage::Pointer m_DataStorage; std::string m_tempDirectory; std::string convertIntToString(int i); - bool decomressFiles(std::string file,std::string path); + /** + * @throws Throws an Exception if particular file cannot be opened for reading + */ + void decomressFiles(std::string file,std::string path); }; } // namespace mitk #endif //NAVIGATIONTOOLSTORAGEDESERIALIZER diff --git a/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageSerializer.cpp b/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageSerializer.cpp index 4a1e4757e4..2da85d35f9 100644 --- a/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageSerializer.cpp +++ b/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageSerializer.cpp @@ -1,95 +1,102 @@ /*=================================================================== 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. ===================================================================*/ //Poco headers #include "Poco/Zip/Compress.h" #include "Poco/Path.h" #include "Poco/File.h" #include "mitkNavigationToolStorageSerializer.h" #include "mitkNavigationToolWriter.h" +#include "mitkIGTException.h" +#include "mitkIGTIOException.h" #include #include #include #include + + mitk::NavigationToolStorageSerializer::NavigationToolStorageSerializer() - { +{ //create temp directory - m_tempDirectory = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory() + Poco::Path::separator() + "tempNavigationToolSerializer"; + mitk::UIDGenerator myUIDGen = mitk::UIDGenerator("",16); + m_tempDirectory = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory() + Poco::Path::separator() + "tempNavigationToolSerializer_" + myUIDGen.GetUID(); Poco::File myFile(m_tempDirectory); myFile.createDirectory(); - } +} mitk::NavigationToolStorageSerializer::~NavigationToolStorageSerializer() +{ + //remove temp directory + Poco::File myFile(m_tempDirectory); + try { - //remove temp directory - Poco::File myFile(m_tempDirectory); - try - { - if (myFile.exists()) myFile.remove(); - } - catch(...) - { - MITK_ERROR << "Can't remove temp directory " << m_tempDirectory << "!"; - } + if (myFile.exists()) myFile.remove(true); } + catch(...) + { + MITK_ERROR << "Can't remove temp directory " << m_tempDirectory << "!"; + } +} bool mitk::NavigationToolStorageSerializer::Serialize(std::string filename, mitk::NavigationToolStorage::Pointer storage) - { +{ //save every tool to temp directory mitk::NavigationToolWriter::Pointer myToolWriter = mitk::NavigationToolWriter::New(); for(int i=0; iGetToolCount();i++) - { + { std::string fileName = m_tempDirectory + Poco::Path::separator() + "NavigationTool" + convertIntToString(i) + ".tool"; - if (!myToolWriter->DoWrite(fileName,storage->GetTool(i))) return false; - } - + if (!myToolWriter->DoWrite(fileName,storage->GetTool(i))) + { + mitkThrowException(mitk::IGTIOException) << "Could not write tool to tempory directory: " << filename; + } + } //add all files to zip archive std::ofstream file( filename.c_str(), std::ios::binary | std::ios::out); - if (!file.good()) - { - m_ErrorMessage = "Could not open a zip file for writing: '" + filename + "'"; + if (!file.good()) //test if the zip archive is ready for writing + { + //first: clean up for (int i=0; iGetToolCount();i++) - { + { std::string fileName = m_tempDirectory + Poco::Path::separator() + "NavigationTool" + convertIntToString(i) + ".tool"; std::remove(fileName.c_str()); - } - return false; } + //then: throw an exception + mitkThrowException(mitk::IGTIOException) << "Could not open a file for writing: " << filename; + } Poco::Zip::Compress zipper( file, true ); for (int i=0; iGetToolCount();i++) - { - std::string fileName = m_tempDirectory + Poco::Path::separator() + "NavigationTool" + convertIntToString(i) + ".tool"; - zipper.addFile(fileName,myToolWriter->GetFileWithoutPath(fileName)); - //delete file: - std::remove(fileName.c_str()); - } - zipper.close(); - file.close(); - - return true; + { + std::string fileName = m_tempDirectory + Poco::Path::separator() + "NavigationTool" + convertIntToString(i) + ".tool"; + zipper.addFile(fileName,myToolWriter->GetFileWithoutPath(fileName)); + std::remove(fileName.c_str()); //delete file } + zipper.close(); + file.close(); + + return true; + } std::string mitk::NavigationToolStorageSerializer::convertIntToString(int i) - { + { std::string s; std::stringstream out; out << i; s = out.str(); return s; - } + } diff --git a/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageSerializer.h b/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageSerializer.h index cd2ce9dd34..e1aa9389c9 100644 --- a/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageSerializer.h +++ b/Modules/IGT/IGTToolManagement/mitkNavigationToolStorageSerializer.h @@ -1,62 +1,68 @@ /*=================================================================== 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 NAVIGATIONTOOLSTORAGESERIALIZER_H_INCLUDED #define NAVIGATIONTOOLSTORAGESERIALIZER_H_INCLUDED //itk headers #include //mitk headers #include #include "mitkNavigationToolStorage.h" #include namespace mitk { /**Documentation * \brief This class offers methods to save an object of the class NavigationToolStorage * to the harddisc. * * \ingroup IGT */ class MitkIGT_EXPORT NavigationToolStorageSerializer : public itk::Object { - public: mitkClassMacro(NavigationToolStorageSerializer,itk::Object); itkNewMacro(Self); /** - * @brief Saves a mitk navigation tool storage to a file. - * @return Returns true if the file was saved successfully. False if not. + * @brief Saves a mitk navigation tool storage to a file. + * @return Returns true always true since error handling was converted to exception handling. + * The return value is decrepated. Will be changed to void. + * @throw mitk::IGTIOException Throws an exception if the given filename cannot be opened for writing or + * if the temp directory is not accessible. */ bool Serialize(std::string filename, mitk::NavigationToolStorage::Pointer storage); + /** + * @brief This method is decrepated. Exceptions are used for error handling now! + * @return Returns always an empty string since error handling was converted to exception handling. + */ itkGetMacro(ErrorMessage,std::string); protected: NavigationToolStorageSerializer(); ~NavigationToolStorageSerializer(); - std::string m_ErrorMessage; + std::string m_ErrorMessage; - std::string convertIntToString(int i); + std::string convertIntToString(int i); - std::string m_tempDirectory; + std::string m_tempDirectory; }; } // namespace mitk #endif //NAVIGATIONTOOLSTORAGESERIALIZER diff --git a/Modules/IGT/Testing/Data/EmptyZipFile.zip b/Modules/IGT/Testing/Data/EmptyZipFile.zip new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Modules/IGT/Testing/Data/InvalidDataNavigationDataTestData.xml b/Modules/IGT/Testing/Data/InvalidDataNavigationDataTestData.xml index 7e28877b81..15cb0ecb3e 100644 Binary files a/Modules/IGT/Testing/Data/InvalidDataNavigationDataTestData.xml and b/Modules/IGT/Testing/Data/InvalidDataNavigationDataTestData.xml differ diff --git a/Modules/IGT/Testing/files.cmake b/Modules/IGT/Testing/files.cmake index 4c70dc3ca9..e380216f2c 100644 --- a/Modules/IGT/Testing/files.cmake +++ b/Modules/IGT/Testing/files.cmake @@ -1,49 +1,49 @@ set(MODULE_TESTS mitkCameraVisualizationTest.cpp mitkClaronInterfaceTest.cpp mitkClaronToolTest.cpp mitkClaronTrackingDeviceTest.cpp mitkInternalTrackingToolTest.cpp mitkNavigationDataDisplacementFilterTest.cpp mitkNavigationDataLandmarkTransformFilterTest.cpp mitkNavigationDataObjectVisualizationFilterTest.cpp mitkNavigationDataTest.cpp mitkNavigationDataRecorderTest.cpp mitkNavigationDataReferenceTransformFilterTest.cpp mitkNavigationDataSequentialPlayerTest.cpp mitkNavigationDataSourceTest.cpp mitkNavigationDataToMessageFilterTest.cpp mitkNavigationDataToNavigationDataFilterTest.cpp mitkNavigationDataToPointSetFilterTest.cpp mitkNavigationDataTransformFilterTest.cpp mitkNDIPassiveToolTest.cpp mitkNDIProtocolTest.cpp mitkNDITrackingDeviceTest.cpp mitkTimeStampTest.cpp mitkTrackingVolumeGeneratorTest.cpp mitkTrackingDeviceTest.cpp mitkTrackingToolTest.cpp mitkVirtualTrackingDeviceTest.cpp - # mitkNavigationDataPlayerTest.cpp # deactivated see bug 11636 + mitkNavigationDataPlayerTest.cpp # deactivated see bug 11636 mitkTrackingDeviceSourceTest.cpp mitkTrackingDeviceSourceConfiguratorTest.cpp mitkNavigationDataEvaluationFilterTest.cpp mitkTrackingTypesTest.cpp # ------------------ Navigation Tool Management Tests ------------------- mitkNavigationToolStorageTest.cpp mitkNavigationToolStorageSerializerAndDeserializerTest.cpp mitkNavigationToolTest.cpp mitkNavigationToolReaderAndWriterTest.cpp # ----------------------------------------------------------------------- # ------------------ Deavtivated Tests ---------------------------------- # ----------------------------------------------------------------------- ) set(MODULE_CUSTOM_TESTS mitkNDIAuroraHardwareTest.cpp mitkNDIPolarisHardwareTest.cpp mitkClaronTrackingDeviceHardwareTest.cpp ) \ No newline at end of file diff --git a/Modules/IGT/Testing/mitkNavigationDataPlayerTest.cpp b/Modules/IGT/Testing/mitkNavigationDataPlayerTest.cpp index 4af31878ad..709f6e52fb 100644 --- a/Modules/IGT/Testing/mitkNavigationDataPlayerTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataPlayerTest.cpp @@ -1,351 +1,550 @@ /*=================================================================== 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 "mitkNavigationDataPlayer.h" #include "mitkNavigationData.h" #include "mitkTestingMacros.h" #include "mitkStandardFileLocations.h" #include "mitkTimeStamp.h" #include #include #include +#include "mitkIGTException.h" +#include "mitkIGTIOException.h" + + + +#include + class mitkNavigationDataPlayerTestClass { public: static void TestInstantiation() { // let's create an object of our class mitk::NavigationDataPlayer::Pointer player = mitk::NavigationDataPlayer::New(); // first test: did this work? // using MITK_TEST_CONDITION_REQUIRED makes the test stop after failure, since // it makes no sense to continue without an object. MITK_TEST_CONDITION_REQUIRED(player.IsNotNull(), "Testing instantiation"); } static void TestSimpleDataPlay() { std::string tmp = ""; // let's create an object of our class mitk::NavigationDataPlayer::Pointer player = mitk::NavigationDataPlayer::New(); std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData.xml", "Modules/IGT/Testing/Data"); player->SetFileName( file ); MITK_TEST_CONDITION_REQUIRED( strcmp(player->GetFileName(), file.c_str()) == 0, "Testing SetFileName and GetFileName"); - - player->SetStream( mitk::NavigationDataPlayer::NormalFile ); + //exception is thrown in StartPlaying method player->StartPlaying(); player->Update(); - player->StopPlaying(); + player->StopPlaying();; mitk::NavigationData::Pointer nd = player->GetOutput(); mitk::Point3D pnt; pnt[0] = 1; pnt[1] = 0; pnt[2] = 3; MITK_TEST_CONDITION_REQUIRED( nd->GetPosition() == pnt, "Testing position of replayed NavigaionData" ); player = mitk::NavigationDataPlayer::New(); player->SetFileName( file ); - player->SetStream( mitk::NavigationDataPlayer::NormalFile ); - + std::vector times, refTimes; refTimes.resize(5); refTimes[0] = 3.9; refTimes[1] = 83.6; refTimes[2] = 174.4; refTimes[3] = 275.0; refTimes[4] = 385.39; std::vector points, refPoints; refPoints.resize(5); refPoints[0][0] = 1; refPoints[0][1] = 0; refPoints[0][2] = 3; refPoints[1][0] = 2; refPoints[1][1] = 1; refPoints[1][2] = 4; refPoints[2][0] = 3; refPoints[2][1] = 2; refPoints[2][2] = 5; refPoints[3][0] = 4; refPoints[3][1] = 3; refPoints[3][2] = 6; refPoints[4][0] = 5; refPoints[4][1] = 4; refPoints[4][2] = 7; mitk::TimeStamp::Pointer timer = mitk::TimeStamp::GetInstance(); timer->Initialize(); itk::Object::Pointer obj = itk::Object::New(); mitk::Point3D oldPos; oldPos[0] = 1; oldPos[1] = 0; oldPos[2] = 3; timer->Start( obj ); player->StartPlaying(); while( times.size()<5 ) { player->Update(); pnt = player->GetOutput()->GetPosition(); if ( pnt != oldPos ) { times.push_back( timer->GetElapsed(obj) ); points.push_back(oldPos); oldPos = pnt; } } player->StopPlaying(); // if this test fails, it may be because the dartclient runs on a virtual machine. // Under these circumstances, it may be impossible to achieve a time-accuracy of 10ms for ( int i=0;i<5;i++ ) { if ((times[i]>refTimes[i]-150 && times[i]refTimes[i]-150 && times[i]FindFile("NavigationDataTestData.xml", "Modules/IGT/Testing/Data"); player->SetFileName( file ); MITK_TEST_CONDITION_REQUIRED( strcmp(player->GetFileName(), file.c_str()) == 0, "Testing SetFileName and GetFileName"); - player->SetStream( mitk::NavigationDataPlayer::NormalFile ); player->StartPlaying(); player->Update(); + mitk::NavigationData::Pointer nd = player->GetOutput(); + mitk::Point3D pnt; + pnt[0] = 1; + pnt[1] = 0; + pnt[2] = 3; + + MITK_TEST_CONDITION_REQUIRED( nd->GetPosition() == pnt, "Testing position of replayed NavigaionData" ); + MITK_TEST_OUTPUT(<<"Test double call of Pause() method!"); player->Pause(); //test pause method player->Pause(); //call again to see if this causes an error MITK_TEST_OUTPUT(<<"Test double call of Resume() method!"); player->Resume(); //test resume method player->Resume(); //call again to see if this causes an error player->Update(); player->StopPlaying(); - mitk::NavigationData::Pointer nd = player->GetOutput(); - mitk::Point3D pnt; - pnt[0] = 1; - pnt[1] = 0; - pnt[2] = 3; - - MITK_TEST_CONDITION_REQUIRED( nd->GetPosition() == pnt, "Testing position of replayed NavigaionData" ); - player = mitk::NavigationDataPlayer::New(); player->SetFileName( file ); - player->SetStream( mitk::NavigationDataPlayer::NormalFile ); std::vector times, refTimes; refTimes.resize(5); refTimes[0] = 3.9; refTimes[1] = 83.6; refTimes[2] = 174.4; refTimes[3] = 275.0; refTimes[4] = 385.39; std::vector points, refPoints; refPoints.resize(5); refPoints[0][0] = 1; refPoints[0][1] = 0; refPoints[0][2] = 3; refPoints[1][0] = 2; refPoints[1][1] = 1; refPoints[1][2] = 4; refPoints[2][0] = 3; refPoints[2][1] = 2; refPoints[2][2] = 5; refPoints[3][0] = 4; refPoints[3][1] = 3; refPoints[3][2] = 6; refPoints[4][0] = 5; refPoints[4][1] = 4; refPoints[4][2] = 7; mitk::TimeStamp::Pointer timer = mitk::TimeStamp::GetInstance(); timer->Initialize(); itk::Object::Pointer obj = itk::Object::New(); mitk::Point3D oldPos; oldPos[0] = 1; oldPos[1] = 0; oldPos[2] = 3; timer->Start( obj ); player->StartPlaying(); MITK_TEST_CONDITION_REQUIRED(!player->IsAtEnd(), "Testing method IsAtEnd() #0"); while( times.size()<3 ) { player->Update(); pnt = player->GetOutput()->GetPosition(); if ( pnt != oldPos ) { times.push_back( timer->GetElapsed(obj) ); points.push_back(oldPos); oldPos = pnt; } } MITK_TEST_OUTPUT(<<"Test pause method!"); player->Pause(); MITK_TEST_CONDITION_REQUIRED(!player->IsAtEnd(), "Testing method IsAtEnd() #1"); MITK_TEST_OUTPUT(<<"Test resume method!"); player->Resume(); while( times.size()<5 ) { player->Update(); pnt = player->GetOutput()->GetPosition(); if ( pnt != oldPos ) { times.push_back( timer->GetElapsed(obj) ); points.push_back(oldPos); oldPos = pnt; } } player->StopPlaying(); // if this test fails, it may be because the dartclient runs on a virtual machine. // Under these circumstances, it may be impossible to achieve a time-accuracy of 10ms for ( int i=0;i<5;i++ ) { if ((times[i]>refTimes[i]-150 && times[i]refTimes[i]-150 && times[i]IsAtEnd(), "Testing method IsAtEnd() #2"); } static void TestInvalidStream() { MITK_TEST_OUTPUT(<<"#### Testing invalid input data: errors are expected. ####"); //declarate test variables mitk::NavigationDataPlayer::Pointer player; std::string file; //case 0: stream not set player = mitk::NavigationDataPlayer::New(); - player->SetStream( mitk::NavigationDataPlayer::ZipFile ); + bool InvalidStreamException0 = false; + try + { player->StartPlaying(); + } + catch(mitk::IGTException) + { + InvalidStreamException0=true; player->Update(); player->StopPlaying(); MITK_TEST_OUTPUT(<<"#0: Tested stream not set. Application should not crash."); + } + + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException0, "Testing Invalid Stream method if exception (stream not set) was thrown."); //case 1: non-existing file player = mitk::NavigationDataPlayer::New(); + bool InvalidStreamException1 = false; player->SetFileName( "ffdsd" ); - player->SetStream( mitk::NavigationDataPlayer::NormalFile ); + try + { player->StartPlaying(); + } + catch(mitk::IGTException) + { + InvalidStreamException1=true; player->Update(); player->StopPlaying(); MITK_TEST_OUTPUT(<<"#1: Tested non-existing file. Application should not crash."); + } + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException1, "Testing Invalid Stream method if exception (non-existing file) was thrown."); + //case 2: wrong file format player = mitk::NavigationDataPlayer::New(); + bool InvalidStreamException2 = false; file = mitk::StandardFileLocations::GetInstance()->FindFile("SROMFile.rom", "Modules/IGT/Testing/Data"); player->SetFileName( file ); - player->SetStream( mitk::NavigationDataPlayer::NormalFile ); + try + { player->StartPlaying(); + } + catch(mitk::IGTException) + { + InvalidStreamException2=true; player->Update(); player->StopPlaying(); MITK_TEST_OUTPUT(<<"#2: Tested wrong file format. Application should not crash."); + } + + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException2, "Testing Invalid Stream method if exception (wrong file format) was thrown."); //case 3: wrong file version player = mitk::NavigationDataPlayer::New(); file = mitk::StandardFileLocations::GetInstance()->FindFile("InvalidVersionNavigationDataTestData.xml", "Modules/IGT/Testing/Data"); player->SetFileName( file ); - player->SetStream( mitk::NavigationDataPlayer::NormalFile ); + bool InvalidStreamException3 = false; + try + { player->StartPlaying(); + } + catch(mitk::IGTException) + { + InvalidStreamException3 = true; player->Update(); player->StopPlaying(); MITK_TEST_OUTPUT(<<"#3: Tested wrong file version. Application should not crash."); + } + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException3, "Testing Invalid Stream method if exception (wrong file version) was thrown."); //case 4: wrong file player = mitk::NavigationDataPlayer::New(); player->SetFileName( "cs:\fsd/$%§²³ffdsd" ); - player->SetStream( mitk::NavigationDataPlayer::NormalFile ); + bool InvalidStreamException4=false; + try + { player->StartPlaying(); - player->Update(); - player->StopPlaying(); + } + catch(mitk::IGTException) + { + InvalidStreamException4=true; MITK_TEST_OUTPUT(<<"#4: Tested wrong file. Application should not crash."); + } + + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException4, "Testing Invalid Stream method if exception (wrong file) was thrown."); //case 5: null stream player = mitk::NavigationDataPlayer::New(); - player->SetStream( NULL ); + bool InvalidStreamException5=false; + try + { player->StartPlaying(); + } + catch(mitk::IGTException) + { + InvalidStreamException5=true; player->Update(); player->StopPlaying(); MITK_TEST_OUTPUT(<<"#5: Tested null stream. Application should not crash."); + } - //case 6: empty stream + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException5, "Testing Invalid Stream method if exception (null stream) was thrown."); + + //case 6: empty stream, exception is thrown in setstream player = mitk::NavigationDataPlayer::New(); - std::ifstream* myEmptyStream = new std::ifstream(""); + bool InvalidStreamException6=false; + std::ifstream* myEmptyStream; + try + { + myEmptyStream = new std::ifstream(""); player->SetStream( myEmptyStream ); - player->StartPlaying(); - player->Update(); - player->StopPlaying(); + } + catch(mitk::IGTException) + { + InvalidStreamException6=true; MITK_TEST_OUTPUT(<<"#6: Tested empty stream. Application should not crash."); + } + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException6, "Testing Invalid Stream method if exception (empty stream) was thrown."); + + + //case 7: wrong stream player = mitk::NavigationDataPlayer::New(); file = mitk::StandardFileLocations::GetInstance()->FindFile("SROMFile.rom", "Modules/IGT/Testing/Data"); - std::ifstream* myWrongStream = new std::ifstream(file.c_str()); + + bool InvalidStreamException7=false; + std::ifstream* myWrongStream; + myWrongStream = new std::ifstream(file.c_str()); + try + { player->SetStream( myWrongStream ); - player->StartPlaying(); - player->Update(); - player->StopPlaying(); + } + catch(mitk::IGTIOException) + { + InvalidStreamException7=true; MITK_TEST_OUTPUT(<<"#7: Tested wrong stream. Application should not crash."); + } + + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException7, "Testing Invalid Stream method if exception (wrong stream) was thrown."); + + //case 8: invalid player = mitk::NavigationDataPlayer::New(); file = mitk::StandardFileLocations::GetInstance()->FindFile("InvalidDataNavigationDataTestData.xml", "Modules/IGT/Testing/Data"); player->SetFileName( file ); - player->SetStream( mitk::NavigationDataPlayer::NormalFile ); + bool InvalidStreamException8=false; + try + { player->StartPlaying(); - player->Update(); - player->StopPlaying(); + } + catch(mitk::IGTIOException) + { + InvalidStreamException8=true; MITK_TEST_OUTPUT(<<"#8: Tested invalid file version. Application should not crash."); + } + MITK_TEST_CONDITION_REQUIRED(InvalidStreamException8, "Testing Invalid Stream method if exception (Invalid) was thrown."); //clean up delete myEmptyStream; delete myWrongStream; } + + static void TestSetStreamExceptions() + { + mitk::NavigationDataPlayer::Pointer myTestPlayer = mitk::NavigationDataPlayer::New(); + std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestData.xml", "Modules/IGT/Testing/Data"); + myTestPlayer->SetFileName( file ); + + + bool exceptionThrown=false; + + try + { + std::istream* stream=NULL; + myTestPlayer->SetStream(stream); + } + catch(mitk::IGTException) + { + exceptionThrown = true; + MITK_TEST_OUTPUT(<<"#9: Tested exceptions in SetStream. Application should not crash."); + + } + MITK_TEST_CONDITION_REQUIRED(exceptionThrown, "Testing SetStream method in exception was thrown."); + + } + + static void TestStartPlayingExceptions() + { + MITK_INFO <<"In the following, exceptions are tested. Errors will occur and are expected."; + + + //Case1 Testing if stream=NULL + mitk::NavigationDataPlayer::Pointer myTestPlayer1 = mitk::NavigationDataPlayer::New(); + bool exceptionThrown1 = false; + try + { + myTestPlayer1->StartPlaying(); + + } + catch(mitk::IGTException) + { + exceptionThrown1 = true; + myTestPlayer1->StopPlaying(); + MITK_TEST_OUTPUT(<<"#10: Tested exception for the case when stream=NULL in StartPlaying. Application should not crash."); + } + + MITK_TEST_CONDITION_REQUIRED(exceptionThrown1, "Testing StartPlaying method if exception (stream=NULL) was thrown."); + + //Case2 Testing if file does not exist + mitk::NavigationDataPlayer::Pointer myTestPlayer2 = mitk::NavigationDataPlayer::New(); + myTestPlayer2->SetFileName("ffdsd"); + bool exceptionThrown2 = false; + try{ + myTestPlayer2->StartPlaying(); + } + catch(mitk::IGTIOException) + { + exceptionThrown2 = true; + myTestPlayer2->StopPlaying(); + MITK_TEST_OUTPUT(<<"#11: Tested exception for the case when file does not exist in StartPlaying. Application should not crash."); + } + MITK_TEST_CONDITION_REQUIRED(exceptionThrown2, "Testing StartPlaying method if exception is thrown when file does not exist."); + + + //Case3 Testing if wrong file format + mitk::NavigationDataPlayer::Pointer myTestPlayer3 = mitk::NavigationDataPlayer::New(); + std::string file3 = mitk::StandardFileLocations::GetInstance()->FindFile("SROMFile.rom", "Modules/IGT/Testing/Data"); + myTestPlayer3->SetFileName( file3 ); + bool exceptionThrown3 = false; + try{ + myTestPlayer3->StartPlaying(); + } + catch(mitk::IGTIOException) + { + exceptionThrown3 = true; + myTestPlayer3->StopPlaying(); + MITK_TEST_OUTPUT(<<"#12: Tested exception for the case when file format is wrong in StartPlaying. Application should not crash."); + } + MITK_TEST_CONDITION_REQUIRED(exceptionThrown3, "Testing StartPlaying method if exception (file format is wrong) was thrown."); + + + //Case4 Testing if wrong file version + mitk::NavigationDataPlayer::Pointer myTestPlayer4 = mitk::NavigationDataPlayer::New(); + std::string file4 = mitk::StandardFileLocations::GetInstance()->FindFile("InvalidVersionNavigationDataTestData.xml", "Modules/IGT/Testing/Data"); + myTestPlayer4->SetFileName( file3 ); + bool exceptionThrown4 = false; + try{ + myTestPlayer4->StartPlaying(); + } + catch(mitk::IGTIOException) + { + exceptionThrown4 = true; + myTestPlayer4->StopPlaying(); + MITK_TEST_OUTPUT(<<"#13: Tested exception for the case when file version is wrong in StartPlaying. Application should not crash."); + } + MITK_TEST_CONDITION_REQUIRED(exceptionThrown4, "Testing StartPlaying method if exception (file version is wrong) was thrown."); + + //Case5 Testing if not existing file name + mitk::NavigationDataPlayer::Pointer myTestPlayer5 = mitk::NavigationDataPlayer::New(); + myTestPlayer5->SetFileName("ffdsd"); + bool exceptionThrown5 = false; + try{ + myTestPlayer5->StartPlaying(); + } + catch(mitk::IGTIOException) + { + exceptionThrown5 = true; + myTestPlayer5->StopPlaying(); + MITK_TEST_OUTPUT(<<"#14: Tested exception for the case when non-existing file name in StartPlaying. Application should not crash."); + } + MITK_TEST_CONDITION_REQUIRED(exceptionThrown5, "Testing StartPlaying method if exception (non-existing file name) was thrown."); + + } - }; +}; /**Documentation * test for the class "NavigationDataPlayer". */ + int mitkNavigationDataPlayerTest(int /* argc */, char* /*argv*/[]) { MITK_TEST_BEGIN("NavigationDataPlayer"); std::string tmp = ""; mitkNavigationDataPlayerTestClass::TestInstantiation(); mitkNavigationDataPlayerTestClass::TestSimpleDataPlay(); + mitkNavigationDataPlayerTestClass::TestSetStreamExceptions(); + mitkNavigationDataPlayerTestClass::TestStartPlayingExceptions(); mitkNavigationDataPlayerTestClass::TestPauseAndResume(); mitkNavigationDataPlayerTestClass::TestInvalidStream(); // always end with this! MITK_TEST_END(); } + + + diff --git a/Modules/IGT/Testing/mitkNavigationDataRecorderTest.cpp b/Modules/IGT/Testing/mitkNavigationDataRecorderTest.cpp index c8e84f216b..fcbdfe3a8e 100644 --- a/Modules/IGT/Testing/mitkNavigationDataRecorderTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataRecorderTest.cpp @@ -1,313 +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; + 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();} - Poco::File myFileCSV(filenameCSV); + } + 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()); + + //Testing double call of StartRecording(). + mitk::NavigationData::Pointer naviData = mitk::NavigationData::New(); + recorder->AddNavigationData( naviData ); + recorder->StartRecording(); + recorder->StartRecording(); + recorder->StopRecording(); + 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::IGTException) + { + exceptionThrown1 = true; + } + MITK_TEST_CONDITION(exceptionThrown1,"Testing exception throwing when no file name or file path is set."); + + //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 ); + recorder2->StartRecording(stream); + recorder2->StartRecording(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(); + std::ofstream* stream3 = new std::ofstream(""); //making an empty stream + bool exceptionThrown3 = false; + try + { + recorder3->StartRecording(stream3); + } + catch(mitk::IGTException) + { + 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(); } diff --git a/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp b/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp index 01e947fee3..277845cfa9 100644 --- a/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp @@ -1,135 +1,223 @@ /*=================================================================== 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 "mitkTestingMacros.h" #include #include +//foe exceptions +#include "mitkIGTException.h" +#include "mitkIGTIOException.h" + + const char* XML_STRING = "" "" "" "" "" "" "" ""; +const char* XML_INVALID_TESTSTRING = + "< ToolCount=\"2\">" + "" + "" + "" + "" + "" + "" + ""; + vnl_vector tTool0Snapshot1(3); vnl_vector tTool1Snapshot2(3); mitk::Quaternion qTool0Snapshot0; mitk::Quaternion qTool1Snapshot1; mitk::NavigationDataSequentialPlayer::Pointer player( mitk::NavigationDataSequentialPlayer::New()); -void runLoop() +bool runLoop() { + + + bool success = true; mitk::NavigationData::Pointer nd0; mitk::NavigationData::Pointer nd1; for(unsigned int i=0; iGetNumberOfSnapshots();++i) { player->Update(); nd0 = player->GetOutput(); nd1 = player->GetOutput(1); // test some values - MITK_TEST_CONDITION_REQUIRED(nd0.IsNotNull(), "nd0.IsNotNull()"); - MITK_TEST_CONDITION_REQUIRED(nd1.IsNotNull(), "nd1.IsNotNull()"); + if(nd0.IsNull() || nd1.IsNull()) return false; if(i==0) { - MITK_TEST_CONDITION(qTool0Snapshot0.as_vector() == nd0->GetOrientation().as_vector(), - "qTool0Snapshot0.as_vector() == nd0->GetOrientation().as_vector()"); + if (!(qTool0Snapshot0.as_vector() == nd0->GetOrientation().as_vector())) {success = false;} } else if(i==1) { - MITK_TEST_CONDITION(tTool0Snapshot1 == nd0->GetPosition().GetVnlVector(), - "tTool0Snapshot1 == nd0->GetPosition().GetVnlVector()"); - - MITK_TEST_CONDITION(qTool1Snapshot1.as_vector() == nd1->GetOrientation().as_vector(), - "qTool1Snapshot1.as_vector() == nd1->GetOrientation().as_vector()"); + if (!(tTool0Snapshot1 == nd0->GetPosition().GetVnlVector())) {success = false;} + else if (!(qTool1Snapshot1.as_vector() == nd1->GetOrientation().as_vector())) {success = false;} } else if(i==2) // should be repeated { - MITK_TEST_CONDITION(tTool1Snapshot2 == nd1->GetPosition().GetVnlVector(), - "tTool1Snapshot2 == nd1->GetPosition().GetVnlVector()"); + if (!(tTool1Snapshot2 == nd1->GetPosition().GetVnlVector())) {success = false;} } } + return success; } -/**Documentation - * test for the class "NavigationDataRecorder". - */ -int mitkNavigationDataSequentialPlayerTest(int /* argc */, char* /*argv*/[]) +void TestStandardWorkflow() { - MITK_TEST_BEGIN("NavigationDataSequentialPlayer"); - // create test values valid for the xml data above tTool0Snapshot1[0] = -336.65; tTool0Snapshot1[1] = 138.5; tTool0Snapshot1[2]= -2061.07; tTool1Snapshot2[0] = -56.93; tTool1Snapshot2[1] = 233.79; tTool1Snapshot2[2]= -2042.6; vnl_vector_fixed qVec; qVec[0] = 0.0085; qVec[1] = -0.0576; qVec[2]= -0.0022; qVec[3]= 0.9982; qTool0Snapshot0 = mitk::Quaternion(qVec); qVec[0] = 0.4683; qVec[1] = 0.0188; qVec[2]= -0.8805; qVec[3]= 0.0696; qTool1Snapshot1 = mitk::Quaternion(qVec); - player - ->SetXMLString(XML_STRING); - - MITK_TEST_CONDITION_REQUIRED(player->GetNumberOfSnapshots() == 3, - "player->GetNumberOfSnapshots() == 3"); - player - ->SetRepeat(true); - - runLoop(); - // repeat is on should work a second time - runLoop(); - - // now test the go to snapshot function + //test SetXMLString() + player->SetXMLString(XML_STRING); + MITK_TEST_CONDITION_REQUIRED(player->GetNumberOfSnapshots() == 3,"Testing method SetXMLString with 3 navigation datas."); + + //rest repeat + player->SetRepeat(true); + MITK_TEST_CONDITION_REQUIRED(runLoop(),"Testing first run."); + MITK_TEST_CONDITION_REQUIRED(runLoop(),"Testing second run."); //repeat is on should work a second time + + // now test the go to snapshot function player->GoToSnapshot(3); mitk::NavigationData::Pointer nd1 = player->GetOutput(1); MITK_TEST_CONDITION(tTool1Snapshot2 == nd1->GetPosition().GetVnlVector(), - "tTool1Snapshot2 == nd1->GetPosition().GetVnlVector()"); + "Testing GoToSnapshot() [1]"); player->GoToSnapshot(1); mitk::NavigationData::Pointer nd0 = player->GetOutput(0); MITK_TEST_CONDITION(qTool0Snapshot0.as_vector() == nd0->GetOrientation().as_vector(), - "qTool0Snapshot0.as_vector() == nd0->GetOrientation().as_vector()"); + "Testing GoToSnapshot() [2]"); player->GoToSnapshot(3); // and a third time - runLoop(); + MITK_TEST_CONDITION_REQUIRED(runLoop(),"Tested if repeat works again."); + +} + +void TestSetFileNameException() +{ //testing exception if file name hasnt been set + mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer = mitk::NavigationDataSequentialPlayer::New(); + bool exceptionThrown=false; + try + { + myTestPlayer->SetFileName(""); + } + catch(mitk::IGTIOException) + { + exceptionThrown=true; + MITK_TEST_OUTPUT(<<"Tested exception for the case when file version is wrong in SetFileName. Application should not crash."); + } + MITK_TEST_CONDITION_REQUIRED(exceptionThrown, "Testing SetFileName method if exception (if file name hasnt been set) was thrown."); + + //testing ReInItXML method if data element is not found + mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer1 = mitk::NavigationDataSequentialPlayer::New(); + std::string file = mitk::StandardFileLocations::GetInstance()->FindFile("NavigationDataTestDataInvalidTags.xml", "Modules/IGT/Testing/Data"); + bool exceptionThrown1=false; + try + { + myTestPlayer1->SetFileName(file); + } + catch(mitk::IGTException) + { + exceptionThrown1=true; + } + MITK_TEST_CONDITION_REQUIRED(exceptionThrown1, "Testing SetFileName method if exception (if data element not found) was thrown."); + +} + +void TestGoToSnapshotException() +{ + //testing GoToSnapShot for exception + mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer2 = mitk::NavigationDataSequentialPlayer::New(); + myTestPlayer2->SetXMLString(XML_STRING); + + bool exceptionThrown2=false; + try + { + myTestPlayer2->GoToSnapshot(1000); + } + catch(mitk::IGTException) + { + exceptionThrown2=true; + } + MITK_TEST_CONDITION_REQUIRED(exceptionThrown2, "Testing if exception is thrown when GoToSnapShot method is called with an index that doesn't exist."); +} + +void TestSetXMLStringException() +{ + mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer3 = mitk::NavigationDataSequentialPlayer::New(); + + bool exceptionThrown3=false; + + //The string above XML_INVALID_TESTSTRING is a wrong string, some element were deleted in above + try + { + myTestPlayer3->SetXMLString(XML_INVALID_TESTSTRING); + } + catch(mitk::IGTException) + { + exceptionThrown3=true; + } + MITK_TEST_CONDITION_REQUIRED(exceptionThrown3, "Testing SetXMLString method with an invalid XML string."); +} + + + + +/**Documentation + * test for the class "NavigationDataRecorder". + */ +int mitkNavigationDataSequentialPlayerTest(int /* argc */, char* /*argv*/[]) +{ + MITK_TEST_BEGIN("NavigationDataSequentialPlayer"); - // always end with this! + TestStandardWorkflow(); + TestSetFileNameException(); + TestSetXMLStringException(); + TestGoToSnapshotException(); + MITK_TEST_END(); } diff --git a/Modules/IGT/Testing/mitkNavigationToolStorageSerializerAndDeserializerTest.cpp b/Modules/IGT/Testing/mitkNavigationToolStorageSerializerAndDeserializerTest.cpp index f84615c241..81e8d3589e 100644 --- a/Modules/IGT/Testing/mitkNavigationToolStorageSerializerAndDeserializerTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationToolStorageSerializerAndDeserializerTest.cpp @@ -1,365 +1,442 @@ /*=================================================================== 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. ===================================================================*/ //Poco headers #include "Poco/Path.h" #include #include #include #include #include #include #include #include "mitkNavigationToolStorage.h" //POCO #include +#include "mitkIGTException.h" +#include "mitkIGTIOException.h" + class NavigationToolStorageSerializerAndDeserializerTestClass { public: static void TestInstantiationSerializer() { // let's create objects of our classes mitk::NavigationToolStorageSerializer::Pointer testSerializer = mitk::NavigationToolStorageSerializer::New(); MITK_TEST_CONDITION_REQUIRED(testSerializer.IsNotNull(),"Testing instantiation of NavigationToolStorageSerializer"); } static void TestInstantiationDeserializer() { mitk::DataStorage::Pointer tempStorage = dynamic_cast(mitk::StandaloneDataStorage::New().GetPointer()); //needed for deserializer! mitk::NavigationToolStorageDeserializer::Pointer testDeserializer = mitk::NavigationToolStorageDeserializer::New(tempStorage); MITK_TEST_CONDITION_REQUIRED(testDeserializer.IsNotNull(),"Testing instantiation of NavigationToolStorageDeserializer") } static void TestWriteSimpleToolStorage() { //create Tool Storage mitk::NavigationToolStorage::Pointer myStorage = mitk::NavigationToolStorage::New(); //first tool mitk::NavigationTool::Pointer myTool1 = mitk::NavigationTool::New(); myTool1->SetIdentifier("001"); myStorage->AddTool(myTool1); //second tool mitk::NavigationTool::Pointer myTool2 = mitk::NavigationTool::New(); myTool2->SetIdentifier("002"); myStorage->AddTool(myTool2); //third tool mitk::NavigationTool::Pointer myTool3 = mitk::NavigationTool::New(); myTool3->SetIdentifier("003"); myStorage->AddTool(myTool3); //create Serializer mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New(); //create filename std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+".."+Poco::Path::separator()+"TestStorage.storage"; //test serialization bool success = mySerializer->Serialize(filename,myStorage); MITK_TEST_CONDITION_REQUIRED(success,"Testing serialization of simple tool storage"); } static void TestWriteAndReadSimpleToolStorageWithToolLandmarks() { //create Tool Storage mitk::NavigationToolStorage::Pointer myStorage = mitk::NavigationToolStorage::New(); //first tool mitk::NavigationTool::Pointer myTool1 = mitk::NavigationTool::New(); myTool1->SetIdentifier("001"); mitk::PointSet::Pointer CalLandmarks1 = mitk::PointSet::New(); mitk::Point3D testPt1; mitk::FillVector3D(testPt1,1,2,3); CalLandmarks1->SetPoint(0,testPt1); mitk::PointSet::Pointer RegLandmarks1 = mitk::PointSet::New(); mitk::Point3D testPt2; mitk::FillVector3D(testPt2,4,5,6); RegLandmarks1->SetPoint(5,testPt2); myTool1->SetToolCalibrationLandmarks(CalLandmarks1); myTool1->SetToolRegistrationLandmarks(RegLandmarks1); myStorage->AddTool(myTool1); //create Serializer mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New(); //create filename std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+".."+Poco::Path::separator()+"TestStorageToolReg.storage"; //test serialization bool success = mySerializer->Serialize(filename,myStorage); MITK_TEST_CONDITION_REQUIRED(success,"Testing serialization of tool storage with tool registrations"); mitk::DataStorage::Pointer tempStorage = dynamic_cast(mitk::StandaloneDataStorage::New().GetPointer()); //needed for deserializer! mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(tempStorage); mitk::NavigationToolStorage::Pointer readStorage = myDeserializer->Deserialize(mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+".."+Poco::Path::separator()+"TestStorageToolReg.storage"); MITK_TEST_CONDITION_REQUIRED(readStorage.IsNotNull(),"Testing deserialization of tool storage with tool registrations"); MITK_TEST_CONDITION_REQUIRED(readStorage->GetToolCount()==1," ..Testing number of tools in storage"); mitk::PointSet::Pointer readRegLandmarks = readStorage->GetTool(0)->GetToolRegistrationLandmarks(); mitk::PointSet::Pointer readCalLandmarks = readStorage->GetTool(0)->GetToolCalibrationLandmarks(); MITK_TEST_CONDITION_REQUIRED(((readRegLandmarks->GetPoint(5)[0] == 4)&&(readRegLandmarks->GetPoint(5)[1] == 5)&&(readRegLandmarks->GetPoint(5)[2] == 6)),"..Testing if tool registration landmarks have been stored and loaded correctly."); MITK_TEST_CONDITION_REQUIRED(((readCalLandmarks->GetPoint(0)[0] == 1)&&(readCalLandmarks->GetPoint(0)[1] == 2)&&(readCalLandmarks->GetPoint(0)[2] == 3)),"..Testing if tool calibration landmarks have been stored and loaded correctly."); } static void TestReadSimpleToolStorage() { mitk::DataStorage::Pointer tempStorage = dynamic_cast(mitk::StandaloneDataStorage::New().GetPointer()); //needed for deserializer! mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(tempStorage); mitk::NavigationToolStorage::Pointer readStorage = myDeserializer->Deserialize(mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+".."+Poco::Path::separator()+"TestStorage.storage"); MITK_TEST_CONDITION_REQUIRED(readStorage.IsNotNull(),"Testing deserialization of simple tool storage"); MITK_TEST_CONDITION_REQUIRED(readStorage->GetToolCount()==3," ..Testing number of tools in storage"); //TODO: why is the order of tools changed is save/load process?? bool foundtool1 = false; bool foundtool2 = false; bool foundtool3 = false; for(int i=0; i<3; i++) { if ((readStorage->GetTool(i)->GetIdentifier()=="001")) foundtool1 = true; else if ((readStorage->GetTool(i)->GetIdentifier()=="002")) foundtool2 = true; else if ((readStorage->GetTool(i)->GetIdentifier()=="003")) foundtool3 = true; } MITK_TEST_CONDITION_REQUIRED(foundtool1&&foundtool2&&foundtool3," ..Testing if identifiers of tools where saved / loaded successfully"); } static void CleanUp() { try { std::remove((mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+".."+Poco::Path::separator()+"TestStorage.storage").c_str()); std::remove((mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+".."+Poco::Path::separator()+"TestStorageToolReg.storage").c_str()); std::remove((mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+".."+Poco::Path::separator()+"TestStorage2.storage").c_str()); } catch(...) { MITK_INFO << "Warning: Error occured when deleting test file!"; } } static void TestWriteComplexToolStorage() { //create first tool mitk::Surface::Pointer testSurface; std::string toolFileName = mitk::StandardFileLocations::GetInstance()->FindFile("ClaronTool", "Modules/IGT/Testing/Data"); MITK_TEST_CONDITION(toolFileName.empty() == false, "Check if tool calibration of claron tool file exists"); mitk::NavigationTool::Pointer myNavigationTool = mitk::NavigationTool::New(); myNavigationTool->SetCalibrationFile(toolFileName); mitk::DataNode::Pointer myNode = mitk::DataNode::New(); myNode->SetName("ClaronTool"); //load an stl File mitk::STLFileReader::Pointer stlReader = mitk::STLFileReader::New(); try { stlReader->SetFileName( mitk::StandardFileLocations::GetInstance()->FindFile("ClaronTool.stl", "Testing/Data/").c_str() ); stlReader->Update(); } catch (...) { MITK_TEST_FAILED_MSG(<<"Cannot read stl file."); } if ( stlReader->GetOutput() == NULL ) { MITK_TEST_FAILED_MSG(<<"Cannot read stl file."); } else { testSurface = stlReader->GetOutput(); myNode->SetData(testSurface); } myNavigationTool->SetDataNode(myNode); myNavigationTool->SetIdentifier("ClaronTool#1"); myNavigationTool->SetSerialNumber("0815"); myNavigationTool->SetTrackingDeviceType(mitk::ClaronMicron); myNavigationTool->SetType(mitk::NavigationTool::Fiducial); //create second tool mitk::NavigationTool::Pointer myNavigationTool2 = mitk::NavigationTool::New(); mitk::Surface::Pointer testSurface2; mitk::DataNode::Pointer myNode2 = mitk::DataNode::New(); myNode2->SetName("AuroraTool"); //load an stl File try { stlReader->SetFileName( mitk::StandardFileLocations::GetInstance()->FindFile("EMTool.stl", "Testing/Data/").c_str() ); stlReader->Update(); } catch (...) { MITK_TEST_FAILED_MSG(<<"Cannot read stl file."); } if ( stlReader->GetOutput() == NULL ) { MITK_TEST_FAILED_MSG(<<"Cannot read stl file."); } else { testSurface2 = stlReader->GetOutput(); myNode2->SetData(testSurface2); } myNavigationTool2->SetDataNode(myNode2); myNavigationTool2->SetIdentifier("AuroraTool#1"); myNavigationTool2->SetSerialNumber("0816"); myNavigationTool2->SetTrackingDeviceType(mitk::NDIAurora); myNavigationTool2->SetType(mitk::NavigationTool::Instrument); //create navigation tool storage mitk::NavigationToolStorage::Pointer myStorage = mitk::NavigationToolStorage::New(); myStorage->AddTool(myNavigationTool); myStorage->AddTool(myNavigationTool2); //create Serializer mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New(); //create filename std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+".."+Poco::Path::separator()+"TestStorage2.storage"; //test serialization bool success = mySerializer->Serialize(filename,myStorage); MITK_TEST_CONDITION_REQUIRED(success,"Testing serialization of complex tool storage"); } static void TestReadComplexToolStorage() { mitk::DataStorage::Pointer tempStorage = dynamic_cast(mitk::StandaloneDataStorage::New().GetPointer()); //needed for deserializer! mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(tempStorage); mitk::NavigationToolStorage::Pointer readStorage = myDeserializer->Deserialize(mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+".."+Poco::Path::separator()+"TestStorage2.storage"); MITK_TEST_CONDITION_REQUIRED(readStorage.IsNotNull(),"Testing deserialization of complex tool storage"); MITK_TEST_CONDITION_REQUIRED(readStorage->GetToolCount()==2," ..Testing number of tools in storage"); } static void TestReadNotExistingStorage() { mitk::DataStorage::Pointer tempStorage = dynamic_cast(mitk::StandaloneDataStorage::New().GetPointer()); //needed for deserializer! mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(tempStorage); mitk::NavigationToolStorage::Pointer readStorage = myDeserializer->Deserialize("noStorage.tfl"); MITK_TEST_CONDITION_REQUIRED(readStorage->isEmpty(),"Testing deserialization of not existing data storage."); MITK_TEST_CONDITION_REQUIRED(myDeserializer->GetErrorMessage() == "Cannot open 'noStorage.tfl' for reading", "Checking Error Message"); } static void TestReadStorageWithUnknownFiletype() { mitk::DataStorage::Pointer tempStorage = dynamic_cast(mitk::StandaloneDataStorage::New().GetPointer()); //needed for deserializer! std::string toolFileName = mitk::StandardFileLocations::GetInstance()->FindFile("ClaronTool.stl", "Modules/IGT/Testing/Data"); MITK_TEST_CONDITION(toolFileName.empty() == false, "Check if tool calibration of claron tool file exists"); mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(tempStorage); mitk::NavigationToolStorage::Pointer readStorage = myDeserializer->Deserialize(toolFileName); MITK_TEST_CONDITION_REQUIRED(readStorage->isEmpty(), "Testing deserialization of existing file with unknown filetype."); } static void TestReadZipFileWithNoToolstorage() { mitk::DataStorage::Pointer tempStorage = dynamic_cast(mitk::StandaloneDataStorage::New().GetPointer()); //needed for deserializer! std::string toolFileName = mitk::StandardFileLocations::GetInstance()->FindFile("Empty.zip", "Modules/IGT/Testing/Data"); MITK_TEST_CONDITION(toolFileName.empty() == false, "Check if tool calibration of claron tool file exists"); mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(tempStorage); mitk::NavigationToolStorage::Pointer readStorage = myDeserializer->Deserialize(toolFileName); MITK_TEST_CONDITION_REQUIRED(readStorage->isEmpty(), "Testing deserialization of empty zip file with no toolstorage in it"); } static void TestWriteStorageToInvalidFile() { //create Tool Storage mitk::NavigationToolStorage::Pointer myStorage = mitk::NavigationToolStorage::New(); //first tool mitk::NavigationTool::Pointer myTool1 = mitk::NavigationTool::New(); myTool1->SetIdentifier("001"); myStorage->AddTool(myTool1); //second tool mitk::NavigationTool::Pointer myTool2 = mitk::NavigationTool::New(); myTool2->SetIdentifier("002"); myStorage->AddTool(myTool2); //third tool mitk::NavigationTool::Pointer myTool3 = mitk::NavigationTool::New(); myTool3->SetIdentifier("003"); myStorage->AddTool(myTool3); //create Serializer mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New(); //create filename #ifdef WIN32 std::string filename = "C:\342INVALIDFILE<>.storage"; //invalid filename for windows #else std::string filename = "/dsfdsf:$§$342INVALIDFILE.storage"; //invalid filename for linux #endif //test serialization - bool success = true; - success = mySerializer->Serialize(filename,myStorage); - - MITK_TEST_CONDITION_REQUIRED(!success,"Testing serialization into invalid file."); + bool exceptionThrown = false; + try + { + mySerializer->Serialize(filename,myStorage); + } + catch(mitk::IGTException e) + { + exceptionThrown = true; + } + MITK_TEST_CONDITION_REQUIRED(exceptionThrown,"Testing if an exception is thrown if an invalid file is used."); } static void TestWriteEmptyToolStorage() { //create Tool Storage mitk::NavigationToolStorage::Pointer myStorage = mitk::NavigationToolStorage::New(); //create Serializer mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New(); //create filename std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+".."+Poco::Path::separator()+"TestStorage.storage"; //test serialization bool success = mySerializer->Serialize(filename,myStorage); MITK_TEST_CONDITION_REQUIRED(success,"Testing serialization of simple tool storage"); } + //new tests for exception throwing of NavigationToolStorageSerializer + static void TestSerializerForExceptions() + { + mitk::NavigationToolStorageSerializer::Pointer testSerializer = mitk::NavigationToolStorageSerializer::New(); + mitk::NavigationToolStorage::Pointer myStorage = mitk::NavigationToolStorage::New(); + + //create an invalid filename + std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory()+Poco::Path::separator()+".."+Poco::Path::separator()+""; + + //now try to serialize an check if an exception is thrown + bool ExceptionThrown = false; + try + { + testSerializer->Serialize(filename,myStorage); + } + catch(mitk::IGTException) + { + ExceptionThrown = true; + } + MITK_TEST_CONDITION_REQUIRED(ExceptionThrown, "Testing serializer with invalid filename."); + } + + //new tests for exception throwing of NavigationToolStorageDeserializer + static void TestDeserializerForExceptions() + { + + + // Desearializing file with invalid name + mitk::DataStorage::Pointer tempStorage = dynamic_cast(mitk::StandaloneDataStorage::New().GetPointer()); + mitk::NavigationToolStorageDeserializer::Pointer testDeseralizer= mitk::NavigationToolStorageDeserializer::New(tempStorage); + bool ExceptionThrown1 = false; + try + { + mitk::NavigationToolStorage::Pointer readStorage = testDeseralizer->Deserialize("InvalidName"); + } + catch(mitk::IGTException) + { + ExceptionThrown1 = true; + } + MITK_TEST_CONDITION_REQUIRED(ExceptionThrown1, "Testing deserializer with invalid filename."); + + bool ExceptionThrown2 = false; + + // Deserializing of empty zip file + mitk::NavigationToolStorageDeserializer::Pointer testDeseralizer2= mitk::NavigationToolStorageDeserializer::New(tempStorage); + try + { + std::string filename = mitk::StandardFileLocations::GetInstance()->FindFile("EmptyZipFile.zip", "Modules/IGT/Testing/Data"); + mitk::NavigationToolStorage::Pointer readStorage = testDeseralizer2->Deserialize(filename); + } + catch(mitk::IGTException) + { + ExceptionThrown2 = true; + } + MITK_TEST_CONDITION_REQUIRED(ExceptionThrown2, "Testing deserializer method with empty zip file."); + + } + }; + + + + + /** This function is testing the TrackingVolume class. */ int mitkNavigationToolStorageSerializerAndDeserializerTest(int /* argc */, char* /*argv*/[]) { MITK_TEST_BEGIN("NavigationToolStorageSerializerAndDeserializer"); - - ///** TESTS DEACTIVATED BECAUSE OF DART-CLIENT PROBLEMS + NavigationToolStorageSerializerAndDeserializerTestClass::TestInstantiationSerializer(); NavigationToolStorageSerializerAndDeserializerTestClass::TestInstantiationDeserializer(); NavigationToolStorageSerializerAndDeserializerTestClass::TestWriteSimpleToolStorage(); NavigationToolStorageSerializerAndDeserializerTestClass::TestWriteAndReadSimpleToolStorageWithToolLandmarks(); NavigationToolStorageSerializerAndDeserializerTestClass::TestReadSimpleToolStorage(); NavigationToolStorageSerializerAndDeserializerTestClass::TestWriteComplexToolStorage(); NavigationToolStorageSerializerAndDeserializerTestClass::TestReadComplexToolStorage(); NavigationToolStorageSerializerAndDeserializerTestClass::TestReadNotExistingStorage(); NavigationToolStorageSerializerAndDeserializerTestClass::TestReadStorageWithUnknownFiletype(); NavigationToolStorageSerializerAndDeserializerTestClass::TestReadZipFileWithNoToolstorage(); NavigationToolStorageSerializerAndDeserializerTestClass::TestWriteStorageToInvalidFile(); NavigationToolStorageSerializerAndDeserializerTestClass::TestWriteEmptyToolStorage(); + //TestReadInvalidStorage() fails + // NavigationToolStorageSerializerAndDeserializerTestClass::TestReadInvalidStorage(); + + NavigationToolStorageSerializerAndDeserializerTestClass::TestSerializerForExceptions(); + NavigationToolStorageSerializerAndDeserializerTestClass::TestDeserializerForExceptions(); + NavigationToolStorageSerializerAndDeserializerTestClass::CleanUp(); MITK_TEST_END(); } diff --git a/Modules/IGT/files.cmake b/Modules/IGT/files.cmake index 147e232381..0730d714ad 100644 --- a/Modules/IGT/files.cmake +++ b/Modules/IGT/files.cmake @@ -1,62 +1,63 @@ set(CPP_FILES IGTFilters/mitkNavigationDataLandmarkTransformFilter.cpp IGTFilters/mitkNavigationDataReferenceTransformFilter.cpp IGTFilters/mitkNavigationDataTransformFilter.cpp IGTFilters/mitkNavigationDataRecorder.cpp IGTFilters/mitkNavigationDataPlayer.cpp IGTFilters/mitkNavigationDataPlayerBase.cpp IGTFilters/mitkNavigationDataObjectVisualizationFilter.cpp IGTFilters/mitkCameraVisualization.cpp IGTFilters/mitkNavigationData.cpp IGTFilters/mitkNavigationDataDisplacementFilter.cpp IGTFilters/mitkNavigationDataSequentialPlayer.cpp IGTFilters/mitkNavigationDataSource.cpp IGTFilters/mitkNavigationDataToMessageFilter.cpp IGTFilters/mitkNavigationDataToNavigationDataFilter.cpp IGTFilters/mitkNavigationDataToPointSetFilter.cpp IGTFilters/mitkNavigationDataEvaluationFilter.cpp IGTFilters/mitkTrackingDeviceSource.cpp IGTFilters/mitkTrackingVolumeGenerator.cpp IGTFilters/mitkTimeStamp.cpp IGTFilters/mitkRealTimeClock.cpp IGTFilters/mitkTrackingDeviceSourceConfigurator.cpp IGTTrackingDevices/mitkClaronTool.cpp IGTTrackingDevices/mitkClaronTrackingDevice.cpp IGTTrackingDevices/mitkInternalTrackingTool.cpp IGTTrackingDevices/mitkNDIPassiveTool.cpp IGTTrackingDevices/mitkNDIProtocol.cpp IGTTrackingDevices/mitkNDITrackingDevice.cpp IGTTrackingDevices/mitkSerialCommunication.cpp IGTTrackingDevices/mitkTrackingDevice.cpp IGTTrackingDevices/mitkTrackingTool.cpp IGTTrackingDevices/mitkVirtualTrackingDevice.cpp IGTTrackingDevices/mitkVirtualTrackingTool.cpp IGTToolManagement/mitkNavigationToolStorage.cpp IGTToolManagement/mitkNavigationToolStorageSerializer.cpp IGTToolManagement/mitkNavigationToolStorageDeserializer.cpp IGTToolManagement/mitkNavigationTool.cpp IGTToolManagement/mitkNavigationToolReader.cpp IGTToolManagement/mitkNavigationToolWriter.cpp IGTExceptionHandling/mitkIGTException.cpp IGTExceptionHandling/mitkIGTHardwareException.cpp + IGTExceptionHandling/mitkIGTIOException.cpp ) if(MITK_USE_MICRON_TRACKER) set(CPP_FILES ${CPP_FILES} IGTTrackingDevices/mitkClaronInterface.cpp) else() set(CPP_FILES ${CPP_FILES} IGTTrackingDevices/mitkClaronInterfaceStub.cpp) endif(MITK_USE_MICRON_TRACKER) if(MITK_USE_MICROBIRD_TRACKER) set(CPP_FILES ${CPP_FILES} IGTTrackingDevices/mitkMicroBirdTrackingDevice.cpp) endif(MITK_USE_MICROBIRD_TRACKER) if(WIN32) set(CPP_FILES ${CPP_FILES} IGTFilters/mitkWindowsRealTimeClock.cpp) else() set(CPP_FILES ${CPP_FILES} IGTFilters/mitkLinuxRealTimeClock.cpp) endif(WIN32) diff --git a/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.cpp b/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.cpp index 00eb05729e..c7d396a6f6 100644 --- a/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.cpp @@ -1,548 +1,573 @@ /*=================================================================== 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 "QmitkIGTPlayerWidget.h" //mitk headers #include "mitkTrackingTypes.h" #include #include #include #include #include #include #include +#include //qt headers #include #include #include QmitkIGTPlayerWidget::QmitkIGTPlayerWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) ,m_RealTimePlayer(NULL) ,m_SequentialPlayer(NULL) ,m_StartTime(-1.0) ,m_CurrentSequentialPointNumber(0) { m_Controls = NULL; CreateQtPartControl(this); CreateConnections(); m_Controls->samplePositionHorizontalSlider->setVisible(false); this->ResetLCDNumbers(); // reset lcd numbers at start } QmitkIGTPlayerWidget::~QmitkIGTPlayerWidget() { m_PlayingTimer->stop(); m_RealTimePlayer = NULL; m_PlayingTimer = NULL; } void QmitkIGTPlayerWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkIGTPlayerWidgetControls; m_Controls->setupUi(parent); m_PlayingTimer = new QTimer(this); // initialize update timer } } void QmitkIGTPlayerWidget::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->selectPushButton), SIGNAL(clicked()), this, SLOT(OnSelectPressed()) ); // open file dialog connect( (QObject*)(m_Controls->playPushButton), SIGNAL(clicked(bool)), this, SLOT(OnPlayButtonClicked(bool)) ); // play button connect( (QObject*)(m_PlayingTimer), SIGNAL(timeout()), this, SLOT(OnPlaying()) ); // update timer connect( (QObject*) (m_Controls->beginPushButton), SIGNAL(clicked()), this, SLOT(OnGoToBegin()) ); // reset player and go to begin connect( (QObject*) (m_Controls->stopPushButton), SIGNAL(clicked()), this, SLOT(OnGoToEnd()) ); // reset player // pass this widgets protected combobox signal to public signal connect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); // pass this widgets protected checkbox signal to public signal connect( m_Controls->splineModeCheckBox, SIGNAL(toggled(bool)), this, SIGNAL(SignalSplineModeToggled(bool)) ); connect( m_Controls->sequencialModeCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnSequencialModeToggled(bool)) ); connect( m_Controls->samplePositionHorizontalSlider, SIGNAL(sliderPressed()), this, SLOT(OnSliderPressed()) ); connect( m_Controls->samplePositionHorizontalSlider, SIGNAL(sliderReleased()), this, SLOT(OnSliderReleased()) ); } } bool QmitkIGTPlayerWidget::IsTrajectoryInSplineMode() { return m_Controls->splineModeCheckBox->isChecked(); } bool QmitkIGTPlayerWidget::CheckInputFileValid() { QFile file(m_CmpFilename); // check if file exists if(!file.exists()) { QMessageBox::warning(NULL, "IGTPlayer: Error", "No valid input file was loaded. Please load input file first!"); return false; } return true; } unsigned int QmitkIGTPlayerWidget::GetNumberOfTools() { unsigned int result = 0; if(this->GetCurrentPlaybackMode() == RealTimeMode) { if(m_RealTimePlayer.IsNotNull()) result = m_RealTimePlayer->GetNumberOfOutputs(); } else if(this->GetCurrentPlaybackMode() == SequentialMode) { if(m_SequentialPlayer.IsNotNull()) result = m_SequentialPlayer->GetNumberOfOutputs(); } // at the moment this works only if player is initialized return result; } void QmitkIGTPlayerWidget::SetUpdateRate(unsigned int msecs) { m_PlayingTimer->setInterval((int) msecs); // set update timer update rate } void QmitkIGTPlayerWidget::OnPlayButtonClicked(bool checked) { if(CheckInputFileValid()) // no playing possible without valid input file { PlaybackMode currentMode = this->GetCurrentPlaybackMode(); bool isRealTimeMode = currentMode == RealTimeMode; bool isSequentialMode = currentMode == SequentialMode; if(checked) // play { if( (isRealTimeMode && m_RealTimePlayer.IsNull()) || (isSequentialMode && m_SequentialPlayer.IsNull())) // start play { if(isRealTimeMode) { m_RealTimePlayer = mitk::NavigationDataPlayer::New(); m_RealTimePlayer->SetFileName(m_CmpFilename.toStdString()); - m_RealTimePlayer->StartPlaying(); + try + { + m_RealTimePlayer->StartPlaying(); + } + catch(mitk::IGTException) + { + std::string errormessage = "Error during start playing. Invalid or wrong file?"; + QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); + m_Controls->playPushButton->setChecked(false); + m_RealTimePlayer = NULL; + return; + } } else if(isSequentialMode) { m_SequentialPlayer = mitk::NavigationDataSequentialPlayer::New(); + try + { m_SequentialPlayer->SetFileName(m_CmpFilename.toStdString()); - + } + catch(mitk::IGTException) + { + std::string errormessage = "Error during start playing. Invalid or wrong file type?"; + QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); + m_Controls->playPushButton->setChecked(false); + m_RealTimePlayer = NULL; + return; + } + m_Controls->samplePositionHorizontalSlider->setMinimum(0); + m_Controls->samplePositionHorizontalSlider->setMaximum(m_SequentialPlayer->GetNumberOfSnapshots()); + m_Controls->samplePositionHorizontalSlider->setEnabled(true); } m_PlayingTimer->start(100); emit SignalPlayingStarted(); } else // resume play { if(isRealTimeMode) m_RealTimePlayer->Resume(); m_PlayingTimer->start(100); emit SignalPlayingResumed(); } } else // pause { if(isRealTimeMode) m_RealTimePlayer->Pause(); m_PlayingTimer->stop(); emit SignalPlayingPaused(); } } else m_Controls->playPushButton->setChecked(false); // uncheck play button if file unvalid } QmitkIGTPlayerWidget::PlaybackMode QmitkIGTPlayerWidget::GetCurrentPlaybackMode() { if(m_Controls->sequencialModeCheckBox->isChecked()) return SequentialMode; else return RealTimeMode; } QTimer* QmitkIGTPlayerWidget::GetPlayingTimer() { return m_PlayingTimer; } void QmitkIGTPlayerWidget::OnStopPlaying() { this->StopPlaying(); } void QmitkIGTPlayerWidget::StopPlaying() { m_PlayingTimer->stop(); emit SignalPlayingStopped(); if(m_RealTimePlayer.IsNotNull()) m_RealTimePlayer->StopPlaying(); m_RealTimePlayer = NULL; m_SequentialPlayer = NULL; m_StartTime = -1; // set starttime back m_CurrentSequentialPointNumber = 0; m_Controls->samplePositionHorizontalSlider->setSliderPosition(m_CurrentSequentialPointNumber); m_Controls->sampleLCDNumber->display(static_cast(m_CurrentSequentialPointNumber)); this->ResetLCDNumbers(); m_Controls->playPushButton->setChecked(false); // set play button unchecked } void QmitkIGTPlayerWidget::OnPlaying() { PlaybackMode currentMode = this->GetCurrentPlaybackMode(); bool isRealTimeMode = currentMode == RealTimeMode; bool isSequentialMode = currentMode == SequentialMode; if(isRealTimeMode && m_RealTimePlayer.IsNull()) return; else if(isSequentialMode && m_SequentialPlayer.IsNull()) return; if(isRealTimeMode && m_StartTime < 0) m_StartTime = m_RealTimePlayer->GetOutput()->GetTimeStamp(); // get playback start time if(isRealTimeMode && !m_RealTimePlayer->IsAtEnd()) { m_RealTimePlayer->Update(); // update player int msc = (int) (m_RealTimePlayer->GetOutput()->GetTimeStamp() - m_StartTime); // calculation for playing time display int ms = msc % 1000; msc = (msc - ms) / 1000; int s = msc % 60; int min = (msc-s) / 60; // set lcd numbers m_Controls->msecLCDNumber->display(ms); m_Controls->secLCDNumber->display(s); m_Controls->minLCDNumber->display(min); emit SignalPlayerUpdated(); // player successfully updated } else if(isSequentialMode && (m_CurrentSequentialPointNumber < m_SequentialPlayer->GetNumberOfSnapshots())) { m_SequentialPlayer->Update(); // update sequential player m_Controls->samplePositionHorizontalSlider->setSliderPosition(m_CurrentSequentialPointNumber++); // refresh slider position m_Controls->sampleLCDNumber->display(static_cast(m_CurrentSequentialPointNumber)); //for debugging purposes //std::cout << "Sample: " << m_CurrentSequentialPointNumber << " X: " << m_SequentialPlayer->GetOutput(0)->GetPosition()[0] << " Y: " << m_SequentialPlayer->GetOutput(0)->GetPosition()[1] << " Y: " << m_SequentialPlayer->GetOutput(0)->GetPosition()[2] << std::endl; emit SignalPlayerUpdated(); // player successfully updated } else this->StopPlaying(); // if player is at EOF } const std::vector QmitkIGTPlayerWidget::GetNavigationDatas() { std::vector navDatas; if(this->GetCurrentPlaybackMode() == RealTimeMode && m_RealTimePlayer.IsNotNull()) { for(unsigned int i=0; i < m_RealTimePlayer->GetNumberOfOutputs(); ++i) { navDatas.push_back(m_RealTimePlayer->GetOutput(i)); // push back current navigation data for each tool } } else if(this->GetCurrentPlaybackMode() == SequentialMode && m_SequentialPlayer.IsNotNull()) { for(unsigned int i=0; i < m_SequentialPlayer->GetNumberOfOutputs(); ++i) { navDatas.push_back(m_SequentialPlayer->GetOutput(i)); // push back current navigation data for each tool } } return navDatas; } const mitk::PointSet::Pointer QmitkIGTPlayerWidget::GetNavigationDatasPointSet() { mitk::PointSet::Pointer result = mitk::PointSet::New(); mitk::PointSet::PointType pointType; PlaybackMode currentMode = this->GetCurrentPlaybackMode(); bool isRealTimeMode = currentMode == RealTimeMode; bool isSequentialMode = currentMode == SequentialMode; if( (isRealTimeMode && m_RealTimePlayer.IsNotNull()) || (isSequentialMode && m_SequentialPlayer.IsNotNull())) { int numberOfOutputs = 0; if(isRealTimeMode) numberOfOutputs = m_RealTimePlayer->GetNumberOfOutputs(); else if(isSequentialMode) numberOfOutputs = m_SequentialPlayer->GetNumberOfOutputs(); for(unsigned int i=0; i < m_RealTimePlayer->GetNumberOfOutputs(); ++i) { mitk::NavigationData::PositionType position; if(isRealTimeMode) position = m_RealTimePlayer->GetOutput(i)->GetPosition(); else if(isSequentialMode) position = m_SequentialPlayer->GetOutput(i)->GetPosition(); pointType[0] = position[0]; pointType[1] = position[1]; pointType[2] = position[2]; result->InsertPoint(i,pointType); // insert current ND as Pointtype in PointSet for return } } return result; } const mitk::PointSet::PointType QmitkIGTPlayerWidget::GetNavigationDataPoint(unsigned int index) { if( index > this->GetNumberOfTools() || index < 0 ) throw std::out_of_range("Tool Index out of range!"); PlaybackMode currentMode = this->GetCurrentPlaybackMode(); bool isRealTimeMode = currentMode == RealTimeMode; bool isSequentialMode = currentMode == SequentialMode; // create return PointType from current ND for tool index mitk::PointSet::PointType result; if( (isRealTimeMode && m_RealTimePlayer.IsNotNull()) || (isSequentialMode && m_SequentialPlayer.IsNotNull())) { mitk::NavigationData::PositionType position; if(isRealTimeMode) position = m_RealTimePlayer->GetOutput(index)->GetPosition(); else if(isSequentialMode) position = m_SequentialPlayer->GetOutput(index)->GetPosition(); result[0] = position[0]; result[1] = position[1]; result[2] = position[2]; } return result; } void QmitkIGTPlayerWidget::SetInputFileName(const QString& inputFileName) { this->OnGoToEnd(); /// stops playing and resets lcd numbers QString oldName = m_CmpFilename; m_CmpFilename.clear(); m_CmpFilename = inputFileName; QFile file(m_CmpFilename); if(m_CmpFilename.isEmpty() || !file.exists()) { QMessageBox::warning(NULL, "Warning", QString("Please enter valid path! Using previous path again.")); m_CmpFilename=oldName; m_Controls->inputFileLineEdit->setText(m_CmpFilename); } } void QmitkIGTPlayerWidget::SetRealTimePlayer( mitk::NavigationDataPlayer::Pointer player ) { if(player.IsNotNull()) m_RealTimePlayer = player; } void QmitkIGTPlayerWidget::SetSequentialPlayer( mitk::NavigationDataSequentialPlayer::Pointer player ) { if(player.IsNotNull()) m_SequentialPlayer = player; } void QmitkIGTPlayerWidget::OnSelectPressed() { QString oldName = m_CmpFilename; m_CmpFilename.clear(); m_CmpFilename = QFileDialog::getOpenFileName(this, "Load tracking data", QDir::currentPath(),"XML files (*.xml)"); if (m_CmpFilename.isEmpty())//if something went wrong or user pressed cancel in the save dialog m_CmpFilename=oldName; else { this->OnGoToEnd(); /// stops playing and resets lcd numbers emit SignalInputFileChanged(); } m_Controls->inputFileLineEdit->setText(m_CmpFilename); } void QmitkIGTPlayerWidget::OnGoToEnd() { this->StopPlaying(); // reset lcd numbers this->ResetLCDNumbers(); } void QmitkIGTPlayerWidget::OnGoToBegin() { // stop player manual so no PlayingStopped() m_PlayingTimer->stop(); if(this->GetCurrentPlaybackMode() == RealTimeMode && m_RealTimePlayer.IsNotNull()) { m_RealTimePlayer->StopPlaying(); m_RealTimePlayer = NULL; // set player to NULL so it can be initialized again if playback is called afterwards } m_StartTime = -1; // set starttime back //reset view elements m_Controls->playPushButton->setChecked(false); this->ResetLCDNumbers(); } void QmitkIGTPlayerWidget::ResetLCDNumbers() { m_Controls->minLCDNumber->display(QString("00")); m_Controls->secLCDNumber->display(QString("00")); m_Controls->msecLCDNumber->display(QString("000")); } void QmitkIGTPlayerWidget::SetTrajectoryNames(const QStringList toolNames) { QComboBox* cBox = m_Controls->trajectorySelectComboBox; if(cBox->count() > 0) this->ClearTrajectorySelectCombobox(); // before making changed to QComboBox it is recommended to disconnet it's SIGNALS and SLOTS disconnect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); if(!toolNames.isEmpty()) m_Controls->trajectorySelectComboBox->insertItems(0, toolNames); // adding current tool names to combobox // reconnect after performed changes connect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); } int QmitkIGTPlayerWidget::GetResolution() { return m_Controls->resolutionSpinBox->value(); // return currently selected trajectory resolution } void QmitkIGTPlayerWidget::ClearTrajectorySelectCombobox() { // before making changed to QComboBox it is recommended to disconnet it's SIGNALS and SLOTS disconnect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); m_Controls->trajectorySelectComboBox->clear(); // reconnect after performed changes connect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); } void QmitkIGTPlayerWidget::OnSequencialModeToggled(bool toggled) { this->StopPlaying(); // stop playing when mode is changed if(toggled) { m_Controls->samplePositionHorizontalSlider->setEnabled(true); // enable slider if sequential mode } else if(!toggled) { m_Controls->samplePositionHorizontalSlider->setSliderPosition(0); // set back and disable slider m_Controls->samplePositionHorizontalSlider->setDisabled(true); } } void QmitkIGTPlayerWidget::OnSliderReleased() { int currentSliderValue = m_Controls->samplePositionHorizontalSlider->value(); // current slider value selected through user movement if(currentSliderValue > m_CurrentSequentialPointNumber) // at the moment only forward scrolling is possible { m_SequentialPlayer->GoToSnapshot(currentSliderValue); // move player to selected snapshot m_CurrentSequentialPointNumber = currentSliderValue; m_Controls->sampleLCDNumber->display(currentSliderValue); // update lcdnumber in widget } else m_Controls->samplePositionHorizontalSlider->setValue(m_CurrentSequentialPointNumber); } void QmitkIGTPlayerWidget::OnSliderPressed() { if(m_Controls->playPushButton->isChecked()) // check if widget is playing m_Controls->playPushButton->click(); // perform click to pause the play -} +} \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp index 6958bf1f83..e850e8aeb8 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp @@ -1,618 +1,663 @@ /*=================================================================== 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. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkMITKIGTTrackingToolboxView.h" #include "QmitkStdMultiWidget.h" // Qt #include #include // MITK #include #include #include #include #include #include #include // vtk #include - +//for exceptions +#include +#include const std::string QmitkMITKIGTTrackingToolboxView::VIEW_ID = "org.mitk.views.mitkigttrackingtoolbox"; QmitkMITKIGTTrackingToolboxView::QmitkMITKIGTTrackingToolboxView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) { m_TrackingTimer = new QTimer(this); m_tracking = false; m_logging = false; m_loggedFrames = 0; } QmitkMITKIGTTrackingToolboxView::~QmitkMITKIGTTrackingToolboxView() { //remove the tracking volume this->GetDataStorage()->Remove(m_TrackingVolumeNode); } void QmitkMITKIGTTrackingToolboxView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkMITKIGTTrackingToolboxViewControls; m_Controls->setupUi( parent ); //create connections connect( m_Controls->m_LoadTools, SIGNAL(clicked()), this, SLOT(OnLoadTools()) ); connect( m_Controls->m_Connect, SIGNAL(clicked()), this, SLOT(OnConnect()) ); connect( m_Controls->m_Disconnect, SIGNAL(clicked()), this, SLOT(OnDisconnect()) ); connect( m_Controls->m_StartTracking, SIGNAL(clicked()), this, SLOT(OnStartTracking()) ); connect( m_Controls->m_StopTracking, SIGNAL(clicked()), this, SLOT(OnStopTracking()) ); connect( m_TrackingTimer, SIGNAL(timeout()), this, SLOT(UpdateTrackingTimer())); connect( m_Controls->m_ChooseFile, SIGNAL(clicked()), this, SLOT(OnChooseFileClicked())); connect( m_Controls->m_StartLogging, SIGNAL(clicked()), this, SLOT(StartLogging())); connect( m_Controls->m_StopLogging, SIGNAL(clicked()), this, SLOT(StopLogging())); connect( m_Controls->m_configurationWidget, SIGNAL(TrackingDeviceSelectionChanged()), this, SLOT(OnTrackingDeviceChanged())); connect( m_Controls->m_VolumeSelectionBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(OnTrackingVolumeChanged(QString))); connect( m_Controls->m_ShowTrackingVolume, SIGNAL(clicked()), this, SLOT(OnShowTrackingVolumeChanged())); connect( m_Controls->m_AutoDetectTools, SIGNAL(clicked()), this, SLOT(OnAutoDetectTools())); connect( m_Controls->m_ResetTools, SIGNAL(clicked()), this, SLOT(OnResetTools())); connect( m_Controls->m_AddSingleTool, SIGNAL(clicked()), this, SLOT(OnAddSingleTool())); connect( m_Controls->m_NavigationToolCreationWidget, SIGNAL(NavigationToolFinished()), this, SLOT(OnAddSingleToolFinished())); connect( m_Controls->m_NavigationToolCreationWidget, SIGNAL(Canceled()), this, SLOT(OnAddSingleToolCanceled())); //initialize widgets m_Controls->m_configurationWidget->EnableAdvancedUserControl(false); m_Controls->m_TrackingToolsStatusWidget->SetShowPositions(true); m_Controls->m_TrackingToolsStatusWidget->SetTextAlignment(Qt::AlignLeft); //initialize tracking volume node m_TrackingVolumeNode = mitk::DataNode::New(); m_TrackingVolumeNode->SetName("TrackingVolume"); m_TrackingVolumeNode->SetOpacity(0.25); m_TrackingVolumeNode->SetBoolProperty("Backface Culling",true); mitk::Color red; red.SetRed(1); m_TrackingVolumeNode->SetColor(red); GetDataStorage()->Add(m_TrackingVolumeNode); //initialize buttons m_Controls->m_Connect->setEnabled(true); m_Controls->m_Disconnect->setEnabled(false); m_Controls->m_StartTracking->setEnabled(false); m_Controls->m_StopTracking->setEnabled(false); m_Controls->m_AutoDetectTools->setVisible(false); //only visible if tracking device is Aurora //Update List of available models for selected tool. std::vector Compatibles = mitk::GetDeviceDataForLine( m_Controls->m_configurationWidget->GetTrackingDevice()->GetType()); m_Controls->m_VolumeSelectionBox->clear(); for(int i = 0; i < Compatibles.size(); i++) { m_Controls->m_VolumeSelectionBox->addItem(Compatibles[i].Model.c_str()); } } } void QmitkMITKIGTTrackingToolboxView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkMITKIGTTrackingToolboxView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkMITKIGTTrackingToolboxView::OnLoadTools() { //read in filename QString filename = QFileDialog::getOpenFileName(NULL,tr("Open Tool Storage"), "/", tr("Tool Storage Files (*.IGTToolStorage)")); if (filename.isNull()) return; //read tool storage from disk std::string errorMessage = ""; mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(GetDataStorage()); + // try-catch block for exceptions + try + { m_toolStorage = myDeserializer->Deserialize(filename.toStdString()); - + } + catch(mitk::IGTException) + { + std::string errormessage = "Error during deserializing. Problems with file,please check the file?"; + QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); + return; + } + if(m_toolStorage->isEmpty()) { errorMessage = myDeserializer->GetErrorMessage(); MessageBox(errorMessage); return; } //update label Poco::Path myPath = Poco::Path(filename.toStdString()); //use this to seperate filename from path QString toolLabel = QString("Loaded Tools: ") + QString::number(m_toolStorage->GetToolCount()) + " Tools from " + myPath.getFileName().c_str(); m_Controls->m_toolLabel->setText(toolLabel); //update tool preview m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); } void QmitkMITKIGTTrackingToolboxView::OnResetTools() { m_toolStorage = NULL; m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); QString toolLabel = QString("Loaded Tools: "); m_Controls->m_toolLabel->setText(toolLabel); } void QmitkMITKIGTTrackingToolboxView::OnConnect() { //check if everything is ready to start tracking if (this->m_toolStorage.IsNull()) { MessageBox("Error: No Tools Loaded Yet!"); return; } else if (this->m_toolStorage->GetToolCount() == 0) { MessageBox("Error: No Way To Track Without Tools!"); return; } //build the IGT pipeline mitk::TrackingDevice::Pointer trackingDevice = this->m_Controls->m_configurationWidget->GetTrackingDevice(); //Get Tracking Volume Data mitk::TrackingDeviceData data = mitk::DeviceDataUnspecified; QString qstr = m_Controls->m_VolumeSelectionBox->currentText(); if ( (! qstr.isNull()) || (! qstr.isEmpty()) ) { std::string str = qstr.toStdString(); data = mitk::GetDeviceDataByName(str); //Data will be set later, after device generation } mitk::TrackingDeviceSourceConfigurator::Pointer myTrackingDeviceSourceFactory = mitk::TrackingDeviceSourceConfigurator::New(this->m_toolStorage,trackingDevice); m_TrackingDeviceSource = myTrackingDeviceSourceFactory->CreateTrackingDeviceSource(this->m_ToolVisualizationFilter); if (m_TrackingDeviceSource.IsNull()) { MessageBox(myTrackingDeviceSourceFactory->GetErrorMessage()); return; } //connect to device try { m_TrackingDeviceSource->Connect(); //Microservice registration: m_TrackingDeviceSource->RegisterAsMicroservice(); m_toolStorage->RegisterAsMicroservice(m_TrackingDeviceSource->GetMicroserviceID()); } catch (...) //todo: change to mitk::IGTException { MessageBox("Error while starting the tracking device!"); return; } //enable/disable Buttons m_Controls->m_Disconnect->setEnabled(true); m_Controls->m_StartTracking->setEnabled(true); m_Controls->m_StopTracking->setEnabled(false); m_Controls->m_Connect->setEnabled(false); DisableOptionsButtons(); DisableTrackingConfigurationButtons(); m_Controls->m_configurationWidget->ConfigurationFinished(); m_Controls->m_TrackingControlLabel->setText("Status: connected"); } void QmitkMITKIGTTrackingToolboxView::OnDisconnect() { if (m_tracking) this->OnStopTracking(); m_TrackingDeviceSource->Disconnect(); m_TrackingDeviceSource->UnRegisterMicroservice(); //ToolStorages unregisters automatically //enable/disable Buttons m_Controls->m_Disconnect->setEnabled(false); m_Controls->m_StartTracking->setEnabled(false); m_Controls->m_StopTracking->setEnabled(false); m_Controls->m_Connect->setEnabled(true); EnableOptionsButtons(); EnableTrackingConfigurationButtons(); m_Controls->m_configurationWidget->Reset(); m_Controls->m_TrackingControlLabel->setText("Status: disconnected"); } void QmitkMITKIGTTrackingToolboxView::OnStartTracking() { try { m_TrackingDeviceSource->StartTracking(); } catch (...) //todo: change to mitk::IGTException { MessageBox("Error while starting the tracking device!"); return; } m_TrackingTimer->start(1000/(m_Controls->m_UpdateRate->value())); m_Controls->m_TrackingControlLabel->setText("Status: tracking"); //connect the tool visualization widget for(int i=0; iGetNumberOfOutputs(); i++) { m_Controls->m_TrackingToolsStatusWidget->AddNavigationData(m_TrackingDeviceSource->GetOutput(i)); } m_Controls->m_TrackingToolsStatusWidget->ShowStatusLabels(); if (m_Controls->m_ShowToolQuaternions->isChecked()) {m_Controls->m_TrackingToolsStatusWidget->SetShowQuaternions(true);} else {m_Controls->m_TrackingToolsStatusWidget->SetShowQuaternions(false);} //show tracking volume this->OnTrackingVolumeChanged(m_Controls->m_VolumeSelectionBox->currentText()); //enable/disable Buttons m_Controls->m_Disconnect->setEnabled(true); m_Controls->m_StartTracking->setEnabled(false); m_Controls->m_StopTracking->setEnabled(true); m_Controls->m_Connect->setEnabled(false); m_tracking = true; this->GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::OnStopTracking() { if (!m_tracking) return; m_TrackingTimer->stop(); m_TrackingDeviceSource->StopTracking(); m_Controls->m_TrackingControlLabel->setText("Status: connected"); if (m_logging) StopLogging(); m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); m_tracking = false; //enable/disable Buttons m_Controls->m_Disconnect->setEnabled(true); m_Controls->m_StartTracking->setEnabled(true); m_Controls->m_StopTracking->setEnabled(false); m_Controls->m_Connect->setEnabled(false); this->GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::OnTrackingDeviceChanged() { mitk::TrackingDeviceType Type = m_Controls->m_configurationWidget->GetTrackingDevice()->GetType(); // Code to enable/disable device specific buttons if (Type == mitk::NDIAurora) //Aurora { m_Controls->m_AutoDetectTools->setVisible(true); m_Controls->m_AddSingleTool->setEnabled(false); } else //Polaris or Microntracker { m_Controls->m_AutoDetectTools->setVisible(false); m_Controls->m_AddSingleTool->setEnabled(true); } // Code to select appropriate tracking volume for current type std::vector Compatibles = mitk::GetDeviceDataForLine(Type); m_Controls->m_VolumeSelectionBox->clear(); for(int i = 0; i < Compatibles.size(); i++) { m_Controls->m_VolumeSelectionBox->addItem(Compatibles[i].Model.c_str()); } } void QmitkMITKIGTTrackingToolboxView::OnTrackingVolumeChanged(QString qstr) { if (qstr.isNull()) return; if (qstr.isEmpty()) return; if (m_Controls->m_ShowTrackingVolume->isChecked()) { mitk::TrackingVolumeGenerator::Pointer volumeGenerator = mitk::TrackingVolumeGenerator::New(); std::string str = qstr.toStdString(); mitk::TrackingDeviceData data = mitk::GetDeviceDataByName(str); volumeGenerator->SetTrackingDeviceData(data); volumeGenerator->Update(); mitk::Surface::Pointer volumeSurface = volumeGenerator->GetOutput(); m_TrackingVolumeNode->SetData(volumeSurface); GlobalReinit(); } } void QmitkMITKIGTTrackingToolboxView::OnShowTrackingVolumeChanged() { if (m_Controls->m_ShowTrackingVolume->isChecked()) { OnTrackingVolumeChanged(m_Controls->m_VolumeSelectionBox->currentText()); GetDataStorage()->Add(m_TrackingVolumeNode); } else { GetDataStorage()->Remove(m_TrackingVolumeNode); GlobalReinit(); } } void QmitkMITKIGTTrackingToolboxView::OnAutoDetectTools() { if (m_Controls->m_configurationWidget->GetTrackingDevice()->GetType() == mitk::NDIAurora) { DisableTrackingConfigurationButtons(); mitk::NDITrackingDevice::Pointer currentDevice = dynamic_cast(m_Controls->m_configurationWidget->GetTrackingDevice().GetPointer()); currentDevice->OpenConnection(); currentDevice->StartTracking(); mitk::NavigationToolStorage::Pointer autoDetectedStorage = mitk::NavigationToolStorage::New(this->GetDataStorage()); for (int i=0; iGetToolCount(); i++) { //create a navigation tool with sphere as surface std::stringstream toolname; toolname << "AutoDetectedTool" << i; mitk::NavigationTool::Pointer newTool = mitk::NavigationTool::New(); newTool->SetSerialNumber(dynamic_cast(currentDevice->GetTool(i))->GetSerialNumber()); newTool->SetIdentifier(toolname.str()); newTool->SetTrackingDeviceType(mitk::NDIAurora); mitk::DataNode::Pointer newNode = mitk::DataNode::New(); mitk::Surface::Pointer mySphere = mitk::Surface::New(); vtkSphereSource *vtkData = vtkSphereSource::New(); vtkData->SetRadius(3.0f); vtkData->SetCenter(0.0, 0.0, 0.0); vtkData->Update(); mySphere->SetVtkPolyData(vtkData->GetOutput()); vtkData->Delete(); newNode->SetData(mySphere); newNode->SetName(toolname.str()); newTool->SetDataNode(newNode); autoDetectedStorage->AddTool(newTool); } //save detected tools m_toolStorage = autoDetectedStorage; //update label QString toolLabel = QString("Loaded Tools: ") + QString::number(m_toolStorage->GetToolCount()) + " Tools (Auto Detected)"; m_Controls->m_toolLabel->setText(toolLabel); //update tool preview m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); currentDevice->StopTracking(); currentDevice->CloseConnection(); EnableTrackingConfigurationButtons(); if (m_toolStorage->GetToolCount()>0) { //ask the user if he wants to save the detected tools QMessageBox msgBox; switch(m_toolStorage->GetToolCount()) { case 1: msgBox.setText("Found one tool!"); break; default: msgBox.setText("Found " + QString::number(m_toolStorage->GetToolCount()) + " tools!"); } msgBox.setInformativeText("Do you want to save this tools as tool storage, so you can load them again?"); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); int ret = msgBox.exec(); if (ret == 16384) //yes { //ask the user for a filename QString fileName = QFileDialog::getSaveFileName(NULL, tr("Save File"),"/",tr("*.IGTToolStorage")); //check for empty filename if(fileName == "") {return;} mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New(); - if (!mySerializer->Serialize(fileName.toStdString(),m_toolStorage)) MessageBox(mySerializer->GetErrorMessage()); + + //when Serialize method is used exceptions are thrown, need to be adapted + //try-catch block for exception handling in Serializer + try + { + mySerializer->Serialize(fileName.toStdString(),m_toolStorage); + } + catch(mitk::IGTException) + { + std::string errormessage = "Error during serialization. Please check the Zip file."; + QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str());} return; } - else if (ret == 65536) //no + else if (ret == 65536) //no { return; } } } } void QmitkMITKIGTTrackingToolboxView::MessageBox(std::string s) { QMessageBox msgBox; msgBox.setText(s.c_str()); msgBox.exec(); } void QmitkMITKIGTTrackingToolboxView::UpdateTrackingTimer() { m_ToolVisualizationFilter->Update(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); if (m_logging) { this->m_loggingFilter->Update(); m_loggedFrames = this->m_loggingFilter->GetRecordCounter(); this->m_Controls->m_LoggedFramesLabel->setText("Logged Frames: "+QString::number(m_loggedFrames)); //check if logging stopped automatically if((m_loggedFrames>1)&&(!m_loggingFilter->GetRecording())){StopLogging();} } m_Controls->m_TrackingToolsStatusWidget->Refresh(); } void QmitkMITKIGTTrackingToolboxView::OnChooseFileClicked() { QString filename = QFileDialog::getSaveFileName(NULL,tr("Choose Logging File"), "/", "*.*"); if (filename == "") return; this->m_Controls->m_LoggingFileName->setText(filename); } + void QmitkMITKIGTTrackingToolboxView::StartLogging() { if (!m_logging) { //initialize logging filter m_loggingFilter = mitk::NavigationDataRecorder::New(); m_loggingFilter->SetRecordingMode(mitk::NavigationDataRecorder::NormalFile); if (m_Controls->m_xmlFormat->isChecked()) m_loggingFilter->SetOutputFormat(mitk::NavigationDataRecorder::xml); else if (m_Controls->m_csvFormat->isChecked()) m_loggingFilter->SetOutputFormat(mitk::NavigationDataRecorder::csv); - m_loggingFilter->SetFileName(m_Controls->m_LoggingFileName->text().toStdString().c_str()); + std::string filename = m_Controls->m_LoggingFileName->text().toStdString().c_str(); + // this part has been changed in order to prevent crash of the program + if(!filename.empty()) + m_loggingFilter->SetFileName(filename); + else if(filename.empty()){ + std::string errormessage = "File name has not been set, please set the file name"; + mitkThrowException(mitk::IGTIOException)<SetFileName(filename); + } + if (m_Controls->m_LoggingLimit->isChecked()){m_loggingFilter->SetRecordCountLimit(m_Controls->m_LoggedFramesLimit->value());} //connect filter for(int i=0; iGetNumberOfOutputs(); i++){m_loggingFilter->AddNavigationData(m_ToolVisualizationFilter->GetOutput(i));} - //start filter + //start filter with try-catch block for exceptions + try + { m_loggingFilter->StartRecording(); + } + catch(mitk::IGTException) + { + std::string errormessage = "Error during start recording. Recorder already started recording?"; + QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); + m_loggingFilter->StopRecording(); + return; + } //update labels / logging variables this->m_Controls->m_LoggingLabel->setText("Logging ON"); this->m_Controls->m_LoggedFramesLabel->setText("Logged Frames: 0"); m_loggedFrames = 0; m_logging = true; DisableLoggingButtons(); - } } + } + + void QmitkMITKIGTTrackingToolboxView::StopLogging() { if (m_logging) { //update label this->m_Controls->m_LoggingLabel->setText("Logging OFF"); m_loggingFilter->StopRecording(); m_logging = false; EnableLoggingButtons(); } } void QmitkMITKIGTTrackingToolboxView::OnAddSingleTool() { QString Identifier = "Tool#"; if (m_toolStorage.IsNotNull()) Identifier += QString::number(m_toolStorage->GetToolCount()); else Identifier += "0"; m_Controls->m_NavigationToolCreationWidget->Initialize(GetDataStorage(),Identifier.toStdString()); m_Controls->m_NavigationToolCreationWidget->SetTrackingDeviceType(m_Controls->m_configurationWidget->GetTrackingDevice()->GetType(),false); m_Controls->m_TrackingToolsWidget->setCurrentIndex(1); } void QmitkMITKIGTTrackingToolboxView::OnAddSingleToolFinished() { m_Controls->m_TrackingToolsWidget->setCurrentIndex(0); if (this->m_toolStorage.IsNull()) m_toolStorage = mitk::NavigationToolStorage::New(GetDataStorage()); m_toolStorage->AddTool(m_Controls->m_NavigationToolCreationWidget->GetCreatedTool()); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); QString toolLabel = QString("Loaded Tools: "); } void QmitkMITKIGTTrackingToolboxView::OnAddSingleToolCanceled() { m_Controls->m_TrackingToolsWidget->setCurrentIndex(0); } void QmitkMITKIGTTrackingToolboxView::GlobalReinit() { // get all nodes that have not set "includeInBoundingBox" to false mitk::NodePredicateNot::Pointer pred = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("includeInBoundingBox", mitk::BoolProperty::New(false))); mitk::DataStorage::SetOfObjects::ConstPointer rs = this->GetDataStorage()->GetSubset(pred); // calculate bounding geometry of these nodes mitk::TimeSlicedGeometry::Pointer bounds = this->GetDataStorage()->ComputeBoundingGeometry3D(rs, "visible"); // initialize the views to the bounding geometry mitk::RenderingManager::GetInstance()->InitializeViews(bounds); } void QmitkMITKIGTTrackingToolboxView::DisableLoggingButtons() { m_Controls->m_StartLogging->setEnabled(false); m_Controls->m_LoggingFileName->setEnabled(false); m_Controls->m_ChooseFile->setEnabled(false); m_Controls->m_LoggingLimit->setEnabled(false); m_Controls->m_LoggedFramesLimit->setEnabled(false); m_Controls->m_csvFormat->setEnabled(false); m_Controls->m_xmlFormat->setEnabled(false); m_Controls->m_StopLogging->setEnabled(true); } void QmitkMITKIGTTrackingToolboxView::EnableLoggingButtons() { m_Controls->m_StartLogging->setEnabled(true); m_Controls->m_LoggingFileName->setEnabled(true); m_Controls->m_ChooseFile->setEnabled(true); m_Controls->m_LoggingLimit->setEnabled(true); m_Controls->m_LoggedFramesLimit->setEnabled(true); m_Controls->m_csvFormat->setEnabled(true); m_Controls->m_xmlFormat->setEnabled(true); m_Controls->m_StopLogging->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::DisableOptionsButtons() { m_Controls->m_ShowTrackingVolume->setEnabled(false); m_Controls->m_UpdateRate->setEnabled(false); m_Controls->m_ShowToolQuaternions->setEnabled(false); m_Controls->m_OptionsUpdateRateLabel->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::EnableOptionsButtons() { m_Controls->m_ShowTrackingVolume->setEnabled(true); m_Controls->m_UpdateRate->setEnabled(true); m_Controls->m_ShowToolQuaternions->setEnabled(true); m_Controls->m_OptionsUpdateRateLabel->setEnabled(true); } void QmitkMITKIGTTrackingToolboxView::EnableTrackingConfigurationButtons() { m_Controls->m_AutoDetectTools->setEnabled(true); if (m_Controls->m_configurationWidget->GetTrackingDevice()->GetType() != mitk::NDIAurora) m_Controls->m_AddSingleTool->setEnabled(true); m_Controls->m_LoadTools->setEnabled(true); m_Controls->m_ResetTools->setEnabled(true); } void QmitkMITKIGTTrackingToolboxView::DisableTrackingConfigurationButtons() { m_Controls->m_AutoDetectTools->setEnabled(false); if (m_Controls->m_configurationWidget->GetTrackingDevice()->GetType() != mitk::NDIAurora) m_Controls->m_AddSingleTool->setEnabled(false); m_Controls->m_LoadTools->setEnabled(false); m_Controls->m_ResetTools->setEnabled(false); }