diff --git a/Modules/Classification/DataCollection/DataHolder/mitkDataCollection.h b/Modules/Classification/DataCollection/DataHolder/mitkDataCollection.h index a7529d84d2..50d9591777 100644 --- a/Modules/Classification/DataCollection/DataHolder/mitkDataCollection.h +++ b/Modules/Classification/DataCollection/DataHolder/mitkDataCollection.h @@ -1,288 +1,290 @@ /*=================================================================== 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. ===================================================================*/ -#pragma warning (disable : 4996) +#ifdef _MSC_VER +# pragma warning (disable : 4996) +#endif #ifndef mitkDataCollection_H_ #define mitkDataCollection_H_ //#include //#include //#include "itkObjectFactory.h" //#include "mitkCommon.h" #include #include #include #include /** * \brief DataCollection - Class to facilitate loading/accessing structured data * * Data is grouped into a collection that may contain further (sub) collections or images. * * Exemplary structure * * Collection (e.g. Patient) * | * |-- Sub-Collection1 (e.g. follow-up 1) * | | * | |-- DataItem (e.g. T1) * | |-- DataItem (e.g. T2) * | * |-- Sub-Collection2 (e.g. follow-up 2) * | | * | |-- DataItem (e.g. T1) * | |-- DataItem (e.g. T2) * */ namespace mitk { class MITKDATACOLLECTION_EXPORT DataCollection : public BaseData { public: mitkClassMacro(DataCollection, BaseData) itkFactorylessNewMacro(Self) itkCloneMacro(Self) // Needed methods from Basedata virtual void UpdateOutputInformation(); virtual void SetRequestedRegionToLargestPossibleRegion(); virtual bool RequestedRegionIsOutsideOfTheBufferedRegion(); virtual bool VerifyRequestedRegion(); virtual void SetRequestedRegion(const itk::DataObject *); void Init(std::string name); /** * @brief AddData Add a data item * @param data Images/Fibers/DataCollections * @param name name that allows identifying this data (e.g. a category T2, Segmentation , etc ...) * @param description * @return */ size_t AddData(DataObject::Pointer data, std::string name, std::string filePath = ""); /** * @brief SetName - Sets name of DataCollection * @param name */ void SetName(std::string name); std::string GetName() const; std::string GetDataFilePath(size_t index) const; /** * @brief NameToIndex - Get index from data item name * @param name * @return */ size_t NameToIndex(std::string name); /** * @brief IndexToName - Get name from index * @param index * @return */ std::string IndexToName(size_t index) const; /** * @brief HasElement - check if element with this name exists in collection * @param name * @return */ bool HasElement(std::string name); /** * @brief HasElement - check if element with this index exists in collection * @param index * @return */ bool HasElement(size_t index); /** * @brief Size - number of data items in collection * @return */ size_t Size() const; /** * @brief SetData - set/update data item by index * @param data * @param index */ void SetData(itk::DataObject::Pointer data, size_t index); /** * @brief SetData - set/update data item by name * @param data * @param name */ void SetData(itk::DataObject::Pointer data, std::string name); /** * @brief GetData Get original data by index * * To ensure a mitk::Image is returned use \ref mitk::GetMitkImage * * @param index * @return */ itk::DataObject::Pointer GetData(size_t index); /** * @brief GetData Get original data by name * * To ensure a mitk::Image is returned use \ref mitk::GetMitkImage * * @param name * @return */ itk::DataObject::Pointer GetData(std::string name); /** * @brief GetMitkImage - casts data to mitk::Image and returns it * * \note returns nullptr is object is no mitk::Image or itk::Image * * @param index * @return */ mitk::Image::Pointer GetMitkImage(size_t index); /** * @brief GetMitkImage - casts data to mitk::Image and returns it * * \note returns nullptr is object is no mitk::Image or itk::Image * * @param name * @return */ mitk::Image::Pointer GetMitkImage(std::string name); /** * @brief GetMitkImage - casts data to privided itk::Image pointer */ template ImageType GetItkImage(size_t index, ImageType* itkImage); /** * @brief GetMitkImage - casts data to privided itk::Image pointer */ template ImageType GetItkImage(std::string name, ImageType* itkImage); itk::DataObject::Pointer& operator[](size_t index); itk::DataObject::Pointer& operator[](std::string &name); /** * @brief SetNameForIndex - sets name for given data item by index * @param index * @param name */ void SetNameForIndex(size_t index, std::string &name); /** * @brief SetXMLFile - sets xml file to which data collection is saved */ void SetXMLFile(std::string absoluteXMlFile); /** * @brief SetXMLFile - gets xml file to which data collection is supposed to be saved */ std::string GetXMLFile(); /** * @brief SetParent - sets the parent collection * @param parent */ void SetParent(mitk::DataCollection* parent); /** * @brief GetParent - returns the parent collection if available else null is returned * @return */ mitk::DataCollection* GetParent(); /** * @brief RemoveIndex - removes element at index * @param index * @return */ bool RemoveIndex(size_t index); /** * @brief RemoveElement - removes element with name * @param name * @return */ bool RemoveElement(std::string& name); /** * @brief Clear - clears the data collection */ void Clear(); /** * @brief GetDataNode - returns data node containing data at index * @param index * @return */ mitk::DataNode::Pointer GetDataNode(size_t index); /** * @brief GetDataNode - returns data node containing data with name * @param name * @return */ mitk::DataNode::Pointer GetDataNode(std::string name); /** * @brief GetProbabilityMap - returns vectorimage generated out of images with names in the probabilityNamesVector * @param probabilityNamesVector * @return */ mitk::Image::Pointer GetProbabilityMap(std::vector probabilityNamesVector); protected: DataCollection(); virtual ~DataCollection(); private: // DATA std::string m_Name; std::vector m_DataVector; std::vector m_NameVector; std::vector m_FilePathVector; std::map m_DataNames; mitk::DataCollection * m_Parent; std::string m_XMLFile; // is only filled for the hightest layer when loading a data collection }; } // end namespace #endif diff --git a/Modules/Classification/DataCollection/ReaderWriter/mitkCollectionReader.cpp b/Modules/Classification/DataCollection/ReaderWriter/mitkCollectionReader.cpp index 4c365a7df0..0a4296f875 100644 --- a/Modules/Classification/DataCollection/ReaderWriter/mitkCollectionReader.cpp +++ b/Modules/Classification/DataCollection/ReaderWriter/mitkCollectionReader.cpp @@ -1,390 +1,392 @@ /*=================================================================== 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. ===================================================================*/ -#pragma warning (disable : 4996) +#ifdef _MSC_VER +# pragma warning (disable : 4996) +#endif #include "mitkCollectionReader.h" #include #include //#include #include //XML StateMachine Tags // Objects const std::string COLLECTION = "col"; const std::string SUBCOLLECTION = "subcol"; const std::string DATA = "data"; const std::string ITEM = "item"; // Properties const std::string NAME = "name"; const std::string ID = "id"; const std::string FILEPATH = "description"; const std::string LINK = "link"; static std::string GetName(std::string fileName,std::string suffix) { fileName = QFileInfo(QString::fromStdString(fileName)).fileName().toStdString(); return fileName.substr(0,fileName.length() -suffix.length()-9); // 8 = date length } static std::string GetDate(std::string fileName,std::string suffix) { fileName = QFileInfo(QString::fromStdString(fileName)).fileName().toStdString(); fileName = fileName.substr(fileName.length() - suffix.length()-8,8); // 8 = date length fileName.insert(6,"-"); fileName.insert(4,"-"); return fileName; } mitk::CollectionReader::CollectionReader() : m_Collection(nullptr), m_SubCollection(nullptr), m_DataItemCollection(nullptr), m_ColIgnore(false), m_ItemIgnore(false) { } mitk::CollectionReader::~CollectionReader() { this->Clear(); } /** * @brief Loads the xml file filename and generates the necessary instances. **/ mitk::DataCollection::Pointer mitk::CollectionReader::LoadCollection(const std::string& xmlFileName) { QDir fileName = QFileInfo(xmlFileName.c_str()).absoluteDir(); m_BaseDir = fileName.path().toStdString() + QDir::separator().toLatin1(); this->SetFileName(xmlFileName.c_str()); this->Parse(); if (m_Collection.IsNotNull()) m_Collection->SetXMLFile(xmlFileName); return m_Collection; } void mitk::CollectionReader::AddDataElementIds(std::vector dataElemetIds) { m_SelectedDataItemIds.insert( m_SelectedDataItemIds.end(), dataElemetIds.begin(), dataElemetIds.end() ); } void mitk::CollectionReader::AddSubColIds(std::vector subColIds) { m_SelectedSubColIds.insert( m_SelectedSubColIds.end(), subColIds.begin(), subColIds.end() ); } void mitk::CollectionReader::SetDataItemNames(std::vector itemNames) { m_SelectedDataItemNames = itemNames; } void mitk::CollectionReader::ClearDataElementIds() { m_SelectedDataItemIds.clear(); } void mitk::CollectionReader::ClearSubColIds() { m_SelectedSubColIds.clear(); } void mitk::CollectionReader::Clear() { m_DataItemCollection = nullptr; m_SubCollection = nullptr; m_Collection = nullptr; } mitk::DataCollection::Pointer mitk::CollectionReader::FolderToCollection(std::string folder, std::vector suffixes,std::vector seriesNames, bool allowGaps) { // Parse folder and look up all data, // after sanitation only fully available groups are included (that is all suffixes are found) FileListType fileList = SanitizeFileList(GenerateFileLists(folder, suffixes, allowGaps)); if (fileList.size() <= 0) return nullptr; DataCollection::Pointer collection = DataCollection::New(); collection->SetName(GetName(fileList.at(0).at(0),suffixes.at(0))); for (unsigned int k=0; k < fileList.at(0).size(); ++k) // all groups have the same amount of items, so looking at 0 is ok. { DataCollection::Pointer subCollection = DataCollection::New(); for (unsigned int i=0; i< suffixes.size(); ++i) { Image::Pointer image = IOUtil::LoadImage(fileList.at(i).at(k)); subCollection->AddData(image.GetPointer(),seriesNames.at(i), fileList.at(i).at(k)); } std::string sDate = GetDate(fileList.at(0).at(k),suffixes.at(0)); collection->AddData(subCollection.GetPointer(),sDate,"--"); } return collection; } void mitk::CollectionReader::StartElement(const char* elementName, const char **atts) { std::string name(elementName); if (name == COLLECTION) { m_Collection = DataCollection::New(); std::string colName = ReadXMLStringAttribut(NAME, atts); m_Collection->SetName(colName); } else if (name == SUBCOLLECTION) { m_ColIgnore = false; m_ItemIgnore = false; std::string subColName = ReadXMLStringAttribut(NAME, atts); std::string subColId = ReadXMLStringAttribut(ID, atts); if (m_SelectedSubColIds.size() > 0 && std::find(m_SelectedSubColIds.begin(), m_SelectedSubColIds.end(), subColId) == m_SelectedSubColIds.end() ) { // a) a selection list is provided AND b) the item is not in the list m_ColIgnore = true; return; } // Create subcollection m_SubCollection = DataCollection::New(); m_SubCollection->Init(subColName); } else if (name == DATA) { if (m_ColIgnore) return; std::string dataId = ReadXMLStringAttribut(ID, atts); if (m_SelectedDataItemIds.size() > 0 && std::find(m_SelectedDataItemIds.begin(), m_SelectedDataItemIds.end(), dataId) == m_SelectedDataItemIds.end() ) { // a) a selection list is provided AND b) the item is not in the list m_ItemIgnore = true; return; } m_ItemIgnore = false; std::string dataName = ReadXMLStringAttribut(NAME, atts); m_DataItemCollection = DataCollection::New(); m_DataItemCollection->Init(dataName); } else if (name == ITEM) { if (m_ColIgnore || m_ItemIgnore) return; std::string relativeItemLink = ReadXMLStringAttribut(LINK, atts); std::string itemLink = m_BaseDir + relativeItemLink; std::string itemName = ReadXMLStringAttribut(NAME, atts); // if item names are provided and name is not in list, do not load it if (m_SelectedDataItemNames.size() != 0 && std::find(m_SelectedDataItemNames.begin(), m_SelectedDataItemNames.end(), itemName) == m_SelectedDataItemNames.end() ) return; // Populate Sub-Collection Image::Pointer image = IOUtil::LoadImage(itemLink); if (image.IsNotNull()) m_DataItemCollection->AddData(image.GetPointer(),itemName,relativeItemLink); else MITK_ERROR << "File could not be loaded: " << itemLink << ". Wihtin Sub-Collection " << m_SubCollection->GetName() << ", within " << m_DataItemCollection->GetName() ; } else MITK_WARN<< "Malformed description ? -- unknown tag: " << name; } void mitk::CollectionReader::EndElement(const char* elementName) { std::string name(elementName); if (name == SUBCOLLECTION) { if (m_SubCollection.IsNull()) return; if (m_ColIgnore || m_SubCollection->Size() == 0) return; m_Collection->AddData(m_SubCollection.GetPointer(),m_SubCollection->GetName()); m_SubCollection = DataCollection::New(); } if (name == DATA) { if (m_DataItemCollection.IsNull()) return; if (m_DataItemCollection->Size() == 0) return; m_SubCollection->AddData(m_DataItemCollection.GetPointer(),m_DataItemCollection->GetName()); m_DataItemCollection = DataCollection::New(); } } std::string mitk::CollectionReader::ReadXMLStringAttribut(std::string name, const char** atts) { if (atts) { const char** attsIter = atts; while (*attsIter) { if (name == *attsIter) { attsIter++; return *attsIter; } attsIter++; attsIter++; } } return std::string(); } bool mitk::CollectionReader::ReadXMLBooleanAttribut(std::string name, const char** atts) { std::string s = ReadXMLStringAttribut(name, atts); std::transform(s.begin(), s.end(), s.begin(), ::toupper); if (s == "TRUE") return true; else return false; } int mitk::CollectionReader::ReadXMLIntegerAttribut(std::string name, const char** atts) { std::string s = ReadXMLStringAttribut(name, atts); return atoi(s.c_str()); } mitk::CollectionReader::FileListType mitk::CollectionReader::GenerateFileLists(std::string folder, std::vector suffixes, bool allowGaps) { FileListType fileList; QString qFolder = QString::fromStdString(folder); if (!QFileInfo(qFolder).isDir()) { MITK_ERROR << "Folder does not exist."; return fileList; } // Add vector for each suffix for (unsigned int i=0; i< suffixes.size(); ++i) { std::vector list; fileList.push_back(list); } // if gaps are allowed, file names are build up from reference file (first suffix) // else all lists a file, file by file with regular sorting of the files, // if one suffix has more/less images than the others loading is aborted if (allowGaps) { QDir parseDir; parseDir.setFilter(QDir::Files); parseDir.setPath(qFolder); QStringList filterMorph; filterMorph << "*" + QString::fromStdString( suffixes.at(0) ); parseDir.setNameFilters( filterMorph ); QFileInfoList qFileList = parseDir.entryInfoList(); // now populate lists with files names, non-existing files will be marked with an empty string for (int i = 0; i < qFileList.size(); ++i) { std::string baseFileName = qFileList.at(i).absoluteFilePath().toStdString(); fileList.at(0).push_back( baseFileName ); //check for different suffixes for (unsigned int suffNo=1; suffNo < suffixes.size(); ++suffNo) { std::string derivedFileName = baseFileName.substr(0,baseFileName.length() -suffixes.at(0).length()) + suffixes.at(suffNo); // checking if file exists if (QFileInfo(QString::fromStdString(derivedFileName)).isFile()) fileList.at(suffNo).push_back(derivedFileName); else fileList.at(suffNo).push_back(""); } } } else { int numberOfFiles=-1; for (unsigned int i=0; i< suffixes.size(); ++i) { QDir parseDir; parseDir.setFilter(QDir::Files); parseDir.setPath(qFolder); QStringList filterMorph; filterMorph << "*" + QString::fromStdString( suffixes.at(i) ); parseDir.setNameFilters( filterMorph ); QFileInfoList qFileList = parseDir.entryInfoList(); if (numberOfFiles == -1) numberOfFiles = qFileList.size(); if (numberOfFiles != qFileList.size() ) { MITK_ERROR << "Series contain different number of images. Loading aborting."; fileList.clear(); break; } for (int fileNo=0; fileNo indexRemoval; // Parse through all items and check for empty strings, if one occurs mark this index // for removal. int modalities = list.size(); int timeSteps = list.at(0).size(); MITK_INFO << "Modalities " << modalities; MITK_INFO << "TimeSteps " << timeSteps; if (timeSteps == 0) MITK_ERROR << "No files found. Fatal."; for (int listIndex = 0 ; listIndex < timeSteps; listIndex++) { for (int modalityIndex = 0 ; modalityIndex < modalities; modalityIndex++) { if (list.at(modalityIndex).at(listIndex) == "") { MITK_INFO << "Marked Index " << listIndex << " for removal."; indexRemoval.push_back(listIndex); break; } } } for (int listIndex = indexRemoval.size()-1 ; listIndex >= 0; --listIndex) { for (int i = 0 ; i < modalities; i++) { list.at(i).erase(list.at(i).begin()+indexRemoval.at(listIndex)) ; } } MITK_INFO << "Time Steps after sanitizing: " << list.at(0).size(); return list; } diff --git a/Modules/Classification/DataCollection/ReaderWriter/mitkCollectionWriter.cpp b/Modules/Classification/DataCollection/ReaderWriter/mitkCollectionWriter.cpp index 0bd5b170cb..626cc40e3c 100755 --- a/Modules/Classification/DataCollection/ReaderWriter/mitkCollectionWriter.cpp +++ b/Modules/Classification/DataCollection/ReaderWriter/mitkCollectionWriter.cpp @@ -1,418 +1,420 @@ /*=================================================================== 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. ===================================================================*/ -#pragma warning (disable : 4996) +#ifdef _MSC_VER +# pragma warning (disable : 4996) +#endif #include "mitkCollectionWriter.h" #include #include "mitkImageCast.h" #include "itkNrrdImageIO.h" #include "itkImageFileWriter.h" #include "mitkCoreObjectFactory.h" #include #include #include //XML StateMachine Tags // Objects const std::string COLLECTION = "col"; const std::string SUBCOLLECTION = "subcol"; const std::string DATA = "data"; const std::string ITEM = "item"; // Properties const std::string NAME = "name"; const std::string ID = "id"; const std::string FILEPATH = "filepath"; const std::string LINK = "link"; static std::string GetName(std::string fileName,std::string suffix, bool longName = false) { fileName = QFileInfo(QString::fromStdString(fileName)).fileName().toStdString(); if (longName) return fileName.substr(0,fileName.length() -suffix.length()-11); // 10 = date length else return fileName.substr(0,fileName.length() -suffix.length()-9); // 8 = date length } static std::string GetDate(std::string fileName,std::string suffix, bool longName = false) { fileName = QFileInfo(QString::fromStdString(fileName)).fileName().toStdString(); if (longName) fileName = fileName.substr(fileName.length() - suffix.length()-10,10); // 8 = date length else fileName = fileName.substr(fileName.length() - suffix.length()-8,8); // 8 = date length if (!longName) { fileName.insert(6,"-"); fileName.insert(4,"-"); } return fileName; } bool mitk::CollectionWriter::ExportCollectionToFolder(DataCollection *dataCollection, std::string xmlFile, std::vector filter) { // Quick and Dirty: Assumes three level DataCollection QDir fileName = QFileInfo(xmlFile.c_str()).absoluteDir(); std::string outputFolder = fileName.path().toStdString() + QDir::separator().toLatin1(); QDir baseFolder(outputFolder.c_str()); baseFolder.mkpath(outputFolder.c_str()); std::ofstream xmlFileStream; xmlFileStream.open (xmlFile.c_str()); xmlFileStream << " \n"; xmlFileStream << "<" << COLLECTION << " " << NAME << "=\"" << dataCollection->GetName() << "\" >\n"; unsigned int subColId = 0; unsigned int dataId = 0; QDir dir(QString::fromStdString(outputFolder)); for (size_t i = 0 ; i < dataCollection->Size(); ++i) { // Write Subcollection tag xmlFileStream << " <" << SUBCOLLECTION << " " << NAME << "=\"" << dataCollection->IndexToName(i) << "\" " << FILEPATH << "=\"" << dataCollection->GetDataFilePath(i) << "\" id=\"Col" << subColId << "\" >\n"; // Create Sub-Folder dir.mkpath(QString::fromStdString(dataCollection->IndexToName(i))); // Herein create data folders DataCollection* subCollections = dynamic_cast (dataCollection->GetData(i).GetPointer()); if (subCollections == nullptr) { MITK_ERROR<< "mitk::CollectionWriter::SaveCollectionToFolder: Container is illformed. Aborting"; return false; } for (size_t d = 0; d < subCollections->Size(); d++ ) { // Create Sub Paths QString subPath = QString::fromStdString(dataCollection->IndexToName(i))+"/"+QString::fromStdString(subCollections->IndexToName(d)); dir.mkpath(subPath); xmlFileStream << " <" << DATA << " " << NAME << "=\"" << subCollections->IndexToName(d) << "\" " << FILEPATH << "=\"" << subCollections->GetDataFilePath(d) << "\" id=\"Data" << dataId << "\" >\n"; DataCollection* itemCollections = dynamic_cast (subCollections->GetData(d).GetPointer()); if (itemCollections == nullptr) { MITK_ERROR<< "mitk::CollectionWriter::SaveCollectionToFolder: Container is illformed. Aborting"; return false; } for (size_t s = 0; s < itemCollections->Size(); s++) { if (filter.size() > 0) { bool isSelected = false; for (size_t f = 0; f < filter.size(); f++) { if (filter.at(f) == itemCollections->IndexToName(s) ) { isSelected = true; break; } } if (isSelected == false) continue; } - Image* image = dynamic_cast (itemCollections->GetData(s).GetPointer()); + QString fileName = dir.path() + dir.separator() + subPath + dir.separator() + QString::fromStdString(dataCollection->IndexToName(i)) + "_" + QString::fromStdString(subCollections->IndexToName(d)) + "_" + QString::fromStdString(itemCollections->IndexToName(s)); try { fileName += ".nrrd"; Image::Pointer image = itemCollections->GetMitkImage(s).GetPointer(); - IOUtil::SaveImage(image,fileName.toStdString()); + IOUtil::Save(image, fileName.toStdString()); } catch( const std::exception& e) { MITK_ERROR << "Caught exception: " << e.what(); } std::string relativeFilename = baseFolder.relativeFilePath(fileName).toStdString(); xmlFileStream << " <" << ITEM << " " << NAME << "=\"" <IndexToName(s) << "\" " << FILEPATH << "=\"" << "\" " << LINK << "=\"" << relativeFilename << "\" />\n"; } xmlFileStream << " \n"; dataId++; } xmlFileStream << " \n"; subColId++; } xmlFileStream << "\n"; xmlFileStream.flush(); xmlFileStream.close(); return true; } bool mitk::CollectionWriter::ExportCollectionToFolder(mitk::DataCollection *dataCollection, std::string xmlFile) { std::vector mods; return ExportCollectionToFolder(dataCollection,xmlFile, mods); } bool mitk::CollectionWriter::SaveCollection(mitk::DataCollection *dataCollection, std::vector filter, std::string xmlFile) { QDir origFilename = QFileInfo(dataCollection->GetXMLFile().c_str()).absoluteDir(); QString originalFolder = origFilename.path() + QDir::separator(); if (xmlFile == "") xmlFile = dataCollection->GetXMLFile(); QDir fileName = QFileInfo(xmlFile.c_str()).absoluteDir(); std::string outputFolder = fileName.path().toStdString() + QDir::separator().toLatin1(); QDir baseFolder(outputFolder.c_str()); std::ofstream xmlFileStream; xmlFileStream.open (xmlFile.c_str()); xmlFileStream << " \n"; xmlFileStream << "<" << COLLECTION << " " << NAME << "=\"" << dataCollection->GetName() << "\" >\n"; unsigned int subColId = 0; unsigned int dataId = 0; QDir dir(QString::fromStdString(outputFolder)); for (size_t i = 0 ; i < dataCollection->Size(); ++i) { // Write Subcollection tag xmlFileStream << " <" << SUBCOLLECTION << " " << NAME << "=\"" << dataCollection->IndexToName(i) << "\" " << FILEPATH << "=\"" << dataCollection->GetDataFilePath(i) << "\" id=\"Col" << subColId << "\" >\n"; // Create Sub-Folder dir.mkpath(QString::fromStdString(dataCollection->IndexToName(i))); // Herein create data folders DataCollection* subCollections = dynamic_cast (dataCollection->GetData(i).GetPointer()); if (subCollections == nullptr) { MITK_ERROR<< "mitk::CollectionWriter::SaveCollectionToFolder: Container is illformed. Aborting"; return false; } for (size_t d = 0; d < subCollections->Size(); d++ ) { // Create Sub Paths QString subPath = QString::fromStdString(dataCollection->IndexToName(i))+"/"+QString::fromStdString(subCollections->IndexToName(d)); dir.mkpath(subPath); xmlFileStream << " <" << DATA << " " << NAME << "=\"" << subCollections->IndexToName(d) << "\" " << FILEPATH << "=\"" << subCollections->GetDataFilePath(d) << "\" id=\"Data" << dataId << "\" >\n"; DataCollection* itemCollections = dynamic_cast (subCollections->GetData(d).GetPointer()); if (itemCollections == nullptr) { MITK_ERROR<< "mitk::CollectionWriter::SaveCollectionToFolder: Container is illformed. Aborting"; return false; } for (size_t s = 0; s < itemCollections->Size(); s++) { if (filter.size() > 0) { bool isSelected = false; for (size_t f = 0; f < filter.size(); f++) { if (filter.at(f) == itemCollections->IndexToName(s) ) { isSelected = true; break; } } if (isSelected == false) continue; } - Image* image = dynamic_cast (itemCollections->GetData(s).GetPointer()); + QString fileName; bool fullName = false; if (itemCollections->GetDataFilePath(s) != "") { fileName = originalFolder + QString::fromStdString(itemCollections->GetDataFilePath(s)); fullName = true; MITK_INFO << "original path: " << itemCollections->GetDataFilePath(s) ; } else fileName = dir.path() + dir.separator() + subPath + dir.separator() + QString::fromStdString(dataCollection->IndexToName(i)) + "_" + QString::fromStdString(subCollections->IndexToName(d)) + "_" + QString::fromStdString(itemCollections->IndexToName(s)); try { if (!fullName) fileName += ".nrrd"; Image::Pointer image = itemCollections->GetMitkImage(s).GetPointer(); - IOUtil::SaveImage(image,fileName.toStdString()); + IOUtil::Save(image,fileName.toStdString()); } catch( const std::exception& e) { MITK_ERROR << "Caught exception: " << e.what(); } std::string relativeFilename =baseFolder.relativeFilePath(fileName).toStdString(); xmlFileStream << " <" << ITEM << " " << NAME << "=\"" <IndexToName(s) << "\" " << FILEPATH << "=\"" << "\" " << LINK << "=\"" << relativeFilename << "\" />\n"; } xmlFileStream << " \n"; dataId++; } xmlFileStream << " \n"; subColId++; } xmlFileStream << "\n"; xmlFileStream.flush(); xmlFileStream.close(); return true; } bool mitk::CollectionWriter::FolderToXml(std::string folder, std::string collectionType, std::string xmlFile, std::vector filter, std::vector seriesNames) { // 1) Parse for folders QDir parseDir; parseDir.setFilter( QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot); parseDir.setPath(QString::fromStdString(folder)); QFileInfoList qFileList = parseDir.entryInfoList(); std::ofstream xmlFileStream; xmlFileStream.open (xmlFile.c_str()); xmlFileStream << " \n"; xmlFileStream << "<" << COLLECTION << " " << NAME << "=\"" << "GEN" << "\" >\n"; unsigned int dataId = 0; // now populate lists with files names, non-existing files will be marked with an empty string for (int i = 0; i < qFileList.size(); ++i) { // 2) For Each sub folder construct collectionType sub-folder std::string baseFolder = qFileList.at(i).absoluteFilePath().toStdString() + QDir::separator().toLatin1() + collectionType; MITK_INFO << "Processing : " << baseFolder; if (!QFileInfo(QString::fromStdString(baseFolder)).isDir()) { MITK_WARN << "Not a valid folder, skipping."; continue; } // 3) Parse each sub folder and extend XML file // Parse folder and look up all data, // after sanitation only fully available groups are included (that is all suffixes are found) CollectionReader::FileListType fileList = CollectionReader::SanitizeFileList(CollectionReader::GenerateFileLists(baseFolder, filter,true)); if (fileList.size() <= 0 || fileList.at(0).size() <= 0) continue; // Write Subcollection tag // try to extract date out of filename std::string name = GetName(fileList.at(0).at(0),filter.at(0)); xmlFileStream << " <" << SUBCOLLECTION << " " << NAME << "=\"" << name << "\" " << FILEPATH << "=\"\" id=\"Col" << i << "\" >\n"; for (unsigned int k=0; k < fileList.at(0).size(); ++k) // all groups have the same amount of items, so looking at 0 is ok. { std::string strDate = GetDate(fileList.at(0).at(k),filter.at(0)); xmlFileStream << " <" << DATA << " " << NAME << "=\"" << strDate << "\" " << " id=\"Data" << dataId << "\" >\n"; dataId++; for (unsigned int i=0; i< filter.size(); ++i) { std::string fileName = fileList.at(i).at(k); xmlFileStream << " <" << ITEM << " " << NAME << "=\"" << seriesNames.at(i) << "\" " << LINK << "=\"" << fileName << "\" />\n"; } xmlFileStream << " \n" ; } xmlFileStream << " \n"; } xmlFileStream << "\n"; xmlFileStream.flush(); xmlFileStream.close(); return true; } bool mitk::CollectionWriter::SingleFolderToXml(std::string folder, std::string xmlFile, std::vector filter, std::vector seriesNames, bool longDate, int skipUntil, float months) { std::ofstream xmlFileStream; xmlFileStream.open (xmlFile.c_str()); xmlFileStream << " \n"; xmlFileStream << "<" << COLLECTION << " " << NAME << "=\"" << "GEN" << "\" >\n"; unsigned int dataId = 0; // 1) // Parse folder and look up all data, // after sanitation only fully available groups are included (that is all suffixes are found) CollectionReader::FileListType fileList = CollectionReader::SanitizeFileList(CollectionReader::GenerateFileLists(folder, filter,true)); // Write Subcollection tag // try to extract date out of filename std::string name = GetName(fileList.at(0).at(0),filter.at(0),longDate); xmlFileStream << " <" << SUBCOLLECTION << " " << NAME << "=\"" << name << "\" " << FILEPATH << "=\"\" id=\"Col" << 0 << "\" >\n"; for (unsigned int k=skipUntil; k < fileList.at(0).size(); ++k) // all groups have the same amount of items, so looking at 0 is ok. { std::string strDate = GetDate(fileList.at(0).at(k),filter.at(0),true); xmlFileStream << " <" << DATA << " " << NAME << "=\"" << strDate << "\" " << " id=\"Data" << dataId << "\" >\n"; dataId++; for (unsigned int i=0; i< filter.size(); ++i) { std::string fileName = fileList.at(i).at(k); xmlFileStream << " <" << ITEM << " " << NAME << "=\"" << seriesNames.at(i) << "\" " << LINK << "=\"" << fileName << "\" />\n"; } // size_t ind = GetIndexForinXMonths(fileList,months,k,filter); // xmlFileStream << " <" << ITEM << " " << NAME << "=\"TARGET\" " << LINK << "=\"" << fileList.at(filter.size()-1).at(ind) << "\" />\n"; xmlFileStream << " \n" ; // check if target still exists for next step if (GetIndexForinXMonths(fileList,months,k+1,filter)== 0) break; } xmlFileStream << " \n"; xmlFileStream << "\n"; xmlFileStream.flush(); xmlFileStream.close(); return true; } size_t mitk::CollectionWriter::GetIndexForinXMonths(mitk::CollectionReader::FileListType fileList,float months, size_t curIndex,std::vector filter) { std::string strDate0 = GetDate(fileList.at(0).at(curIndex),filter.at(0),true); int year0 =std::atoi(strDate0.substr(0,4).c_str()); int month0 =std::atoi(strDate0.substr(5,2).c_str()); int day0 = std::atoi(strDate0.substr(8,2).c_str()); size_t bestIndex = 0; int bestFit = 1e5; for (size_t i=curIndex+1; i < fileList.at(0).size(); ++i) { std::string strDate = GetDate(fileList.at(0).at(i),filter.at(0),true); int year =std::atoi(strDate.substr(0,4).c_str()); int month =std::atoi(strDate.substr(5,2).c_str()); int day = std::atoi(strDate.substr(8,2).c_str()); int fit = std::fabs((months * 30 ) - (((year-year0)*360) +((month-month0)*30) + (day-day0))); // days difference from x months if (fit < bestFit) { bestFit = fit; bestIndex = i; } } return bestIndex; } diff --git a/Modules/Classification/DataCollection/Testing/mitkDataCollectionImageIteratorTest.cpp b/Modules/Classification/DataCollection/Testing/mitkDataCollectionImageIteratorTest.cpp index 9b8ac72430..045b9d4d56 100644 --- a/Modules/Classification/DataCollection/Testing/mitkDataCollectionImageIteratorTest.cpp +++ b/Modules/Classification/DataCollection/Testing/mitkDataCollectionImageIteratorTest.cpp @@ -1,166 +1,166 @@ /*=================================================================== 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 #include #include #include "mitkNumericTypes.h" class mitkDataCollectionTestClass { private: mitk::Image::Pointer im1; mitk::Image::Pointer im2; mitk::Image::Pointer im3; mitk::Image::Pointer im4; mitk::DataCollection::Pointer dataCol1; mitk::DataCollection::Pointer dataCol2; mitk::DataCollection::Pointer col1; public: mitk::DataCollection::Pointer m_Collection; void Init() { im1 = mitk::ImageGenerator::GenerateRandomImage(2,2,2,1,2,2,2,1,0); im2 = mitk::ImageGenerator::GenerateRandomImage(3,3,3,1,3,3,3,3,2); im3 = mitk::ImageGenerator::GenerateRandomImage(4,4,4,1,4,4,4,5,4); im4 = mitk::ImageGenerator::GenerateRandomImage(5,5,5,1,5,5,5,7,6); dataCol1 = mitk::DataCollection::New(); dataCol2 = mitk::DataCollection::New(); dataCol1->AddData(im1.GetPointer(),"T1"); dataCol1->AddData(im2.GetPointer(),"T2"); dataCol2->AddData(im3.GetPointer(),"T1"); dataCol2->AddData(im4.GetPointer(),"T2"); col1 = mitk::DataCollection::New(); col1->SetName("GnaBla"); col1->AddData(dataCol1.GetPointer(), "0001"); col1->AddData(dataCol2.GetPointer(), "0002"); m_Collection = mitk::DataCollection::New(); m_Collection->SetName("DummyCollection"); m_Collection->AddData(col1.GetPointer(), "C1"); } void IteratorReachesEnd() { Init(); mitk::DataCollectionSingleImageIterator iter(m_Collection, "T1"); int count = 0; while ( ! iter.IsAtEnd()) { ++iter; ++count; } MITK_TEST_CONDITION_REQUIRED(count == 2, "Number of Iterations match number of elements"); } void IteratorGivesRightFirstImage() { Init(); mitk::DataCollectionSingleImageIterator iter(m_Collection, "T1"); int spacing = iter.GetImage()->GetSpacing()[0]; MITK_INFO << "Spacing: " << spacing; MITK_TEST_CONDITION_REQUIRED(spacing == 2, "Image is the first image (Checked by Spacing)"); } void IteratorGivesRightSecondImage() { Init(); mitk::DataCollectionSingleImageIterator iter(m_Collection, "T1"); ++iter; int spacing = iter.GetImage()->GetSpacing()[0]; MITK_INFO << "Spacing: " << spacing; MITK_TEST_CONDITION_REQUIRED(spacing == 4, "Image is the second image (Checked by Spacing)"); } void AddingImageAtFirstPositionIsPossible() { Init(); mitk::DataCollectionSingleImageIterator iter(m_Collection, "T1"); mitk::Image::Pointer im = mitk::ImageGenerator::GenerateRandomImage(6,6,6,1,6,6,6,9,8); itk::Image::Pointer itkImage; mitk::CastToItkImage(im,itkImage); iter.AddImage(itkImage,"T3"); itk::DataObject::Pointer obj = (dynamic_cast (col1->GetData("0001").GetPointer()))->GetData("T3"); int spacing = dynamic_cast *> (obj.GetPointer())->GetSpacing()[0]; // MITK_INFO << "Spacing: " << spacing; MITK_TEST_CONDITION_REQUIRED(spacing == 6, "Image is the first image (Checked by Spacing)"); } void AddingImageAtSecondPositionIsPossible() { Init(); mitk::DataCollectionSingleImageIterator iter(m_Collection, "T1"); ++iter; mitk::Image::Pointer im = mitk::ImageGenerator::GenerateRandomImage(6,6,6,1,6,6,6,9,8); itk::Image::Pointer itkImage; mitk::CastToItkImage(im,itkImage); iter.AddImage(itkImage,"T3"); itk::DataObject::Pointer obj = (dynamic_cast (col1->GetData("0002").GetPointer()))->GetData("T3"); int spacing = dynamic_cast *> (obj.GetPointer())->GetSpacing()[0]; // MITK_INFO << "Spacing: " << spacing; MITK_TEST_CONDITION_REQUIRED(spacing == 6, "Image is the first image (Checked by Spacing)"); } }; -int mitkDataCollectionImageIteratorTest(int argc, char* argv[]) +int mitkDataCollectionImageIteratorTest(int, char**) { MITK_TEST_BEGIN("mitkDataCollectionImageIteratorTest"); //MITK_TEST_CONDITION_REQUIRED(true,"Here we test our condition"); mitkDataCollectionTestClass test; test.IteratorReachesEnd(); test.IteratorGivesRightFirstImage(); //test.IteratorGivesRightSecondImage(); // TODO: activate this test again as soon as bug 18365 is fixed. test.AddingImageAtFirstPositionIsPossible(); test.AddingImageAtSecondPositionIsPossible(); MITK_TEST_END(); } diff --git a/Modules/Classification/DataCollection/Utilities/mitkCollectionStatistic.cpp b/Modules/Classification/DataCollection/Utilities/mitkCollectionStatistic.cpp index ade1d7b4a9..e60d36159c 100644 --- a/Modules/Classification/DataCollection/Utilities/mitkCollectionStatistic.cpp +++ b/Modules/Classification/DataCollection/Utilities/mitkCollectionStatistic.cpp @@ -1,501 +1,500 @@ #include #include // DataCollection Stuff #include //stl stuff #include #include #include mitk::CollectionStatistic::CollectionStatistic() : m_GroundTruthValueToIndexMapper(nullptr) , m_TestValueToIndexMapper(nullptr) { } mitk::CollectionStatistic::~CollectionStatistic() { m_GroundTruthValueToIndexMapper = nullptr; m_TestValueToIndexMapper = nullptr; } void mitk::CollectionStatistic::SetCollection(mitk::DataCollection::Pointer collection) { m_Collection = collection; } mitk::DataCollection::Pointer mitk::CollectionStatistic::GetCollection() { return m_Collection; } void mitk::CollectionStatistic::SetClassCount (size_t count) { m_ClassCount = count; } size_t mitk::CollectionStatistic::GetClassCount() { return m_ClassCount; } void mitk::CollectionStatistic::SetGoldName(std::string name) { m_GroundTruthName = name; } std::string mitk::CollectionStatistic::GetGoldName() { return m_GroundTruthName; } void mitk::CollectionStatistic::SetTestName(std::string name) { m_TestName = name; } std::string mitk::CollectionStatistic::GetTestName() { return m_TestName; } void mitk::CollectionStatistic::SetGroundTruthValueToIndexMapper(const ValueToIndexMapper* mapper) { m_GroundTruthValueToIndexMapper = mapper; } const mitk::ValueToIndexMapper* mitk::CollectionStatistic::GetGroundTruthValueToIndexMapper(void) const { return m_GroundTruthValueToIndexMapper; } void mitk::CollectionStatistic::SetTestValueToIndexMapper(const ValueToIndexMapper* mapper) { m_TestValueToIndexMapper = mapper; } const mitk::ValueToIndexMapper* mitk::CollectionStatistic::GetTestValueToIndexMapper(void) const { return m_TestValueToIndexMapper; } int mitk::CollectionStatistic::IsInSameVirtualClass(unsigned char gold, unsigned char test) { int resultClass = -1; - for (int i = 0; i < m_ConnectionGold.size(); ++i) + for (std::size_t i = 0; i < m_ConnectionGold.size(); ++i) { if (m_ConnectionGold[i] == gold && m_ConnectionTest[i] == test) { resultClass = m_ConnectionClass[i]; break; } } return resultClass; } bool mitk::CollectionStatistic::Update() { if (m_GroundTruthValueToIndexMapper == nullptr) { MITK_ERROR << "m_GroundTruthValueToIndexMapper is nullptr"; return false; } if (m_TestValueToIndexMapper == nullptr) { MITK_ERROR << "m_TestValueToIndexMapper is nullptr"; return false; } - typedef itk::Image ImageType; DataCollectionImageIterator goldIter(m_Collection, m_GroundTruthName); DataCollectionImageIterator testIter(m_Collection, m_TestName); DataCollectionImageIterator maskIter(m_Collection, m_MaskName); int index = 0; while (!goldIter.IsAtEnd()) { std::size_t imageIndex = goldIter.GetImageIndex(); if (m_ImageClassStatistic.size() <= imageIndex) { MITK_INFO << "New Image: " << goldIter.GetFilePrefix(); m_ImageNames.push_back(goldIter.GetFilePrefix()); StatisticData statData; m_ImageStatistic.push_back(statData); DataVector data; - for (int i = 0; i < m_ClassCount; ++i) + for (std::size_t i = 0; i < m_ClassCount; ++i) { StatisticData stat; data.push_back(stat); } m_ImageClassStatistic.push_back(data); } if (maskIter.GetVoxel() <= 0) { ++goldIter; ++testIter; ++maskIter; continue; } ++index; unsigned char goldClass = m_GroundTruthValueToIndexMapper->operator()(goldIter.GetVoxel()); unsigned char testClass = m_TestValueToIndexMapper->operator()(testIter.GetVoxel()); if (goldClass == testClass) // True Positive { m_ImageStatistic[imageIndex].m_TruePositive += 1; - for (int i = 0; i < m_ClassCount; ++i) + for (std::size_t i = 0; i < m_ClassCount; ++i) { if (goldClass == i) // For the detected class it is a true positive { m_ImageClassStatistic[imageIndex][i].m_TruePositive += 1; } else // for all other classes than the detected it is a true negative { m_ImageClassStatistic[imageIndex][i].m_TrueNegative += 1; } } } else // No True Positive { m_ImageStatistic[imageIndex].m_FalseNegative += 1; m_ImageStatistic[imageIndex].m_FalsePositive += 1; - for (int i = 0; i < m_ClassCount; ++i) + for (std::size_t i = 0; i < m_ClassCount; ++i) { if (goldClass == i) // For the class in Goldstandard it is a false negative { m_ImageClassStatistic[imageIndex][i].m_FalseNegative += 1; } else if ( testClass == i) // For the test class it is a false positive { m_ImageClassStatistic[imageIndex][i].m_FalsePositive += 1; } else // For all other it is a true negative { m_ImageClassStatistic[imageIndex][i].m_TrueNegative += 1; } } } ++goldIter; ++testIter; ++maskIter; } MITK_INFO << "Evaluated " << index << " points"; return true; } void mitk::CollectionStatistic::Print(std::ostream& out, std::ostream& sout, bool withHeader, std::string label) { assert(m_ImageClassStatistic.size() > 0); assert(m_ImageClassStatistic[0].size() == m_ClassCount); if (withHeader) { sout << "Label;ImageName;"; - for (int i = 0; i < m_ClassCount; ++i) + for (std::size_t i = 0; i < m_ClassCount; ++i) { sout << "DICE-Class-"<< i << ";"; sout << "Jaccard-Class-"<< i << ";"; sout << "Sensitivity-Class-"<< i << ";"; sout << "Specificity-Class-"<< i << ";"; sout << "TP-Class-"<< i << ";"; sout << "TN-Class-"<< i << ";"; sout << "FP-Class-"<< i << ";"; sout << "FN-Class-"<< i << ";"; } sout << "DICE-MEAN"<< ";"; sout << "Jaccard-MEAN"<< ";"; sout << "Sensitivity-MEAN"<< ";"; sout << "Specificity-MEAN"<< ";"; sout << "TP-MEAN"<< ";"; sout << "TN-MEAN"<< ";"; sout << "FP-MEAN"<< ";"; sout << "FN-MEAN"<< ";"; sout << "DICE-WMEAN"<< ";"; sout << "Jaccard-WMEAN"<< ";"; sout << "Sensitivity-WMEAN"<< ";"; sout << "Specificity-WMEAN"<< ";"; sout << "TP-WMEAN"<< ";"; sout << "TN-WMEAN"<< ";"; sout << "FP-WMEAN"<< ";"; sout << "FN-WMEAN"<< ";"; sout << "COMPLETE-TRUE/FALSE"<< ";"; sout << "COMPLETE-TRUES"<< ";"; sout << "COMPLETE_FALSE"<< ";"; sout << std::endl; } out << std::setprecision(5); MITK_INFO << "m_ImageClassStatistic.size(): " << m_ImageClassStatistic.size(); - for (int i = 0; i < m_ImageClassStatistic.size(); ++i) + for (std::size_t i = 0; i < m_ImageClassStatistic.size(); ++i) { sout << label << ";"<< m_ImageNames[i]<<";"; StatisticData meanStat; StatisticData wMeanStat; double pointsSum = 0; out << "======================================================== Image " << std::setw(3) << i << " ========================================================" << std::endl; out << " Image ID : " << m_ImageNames[i] < mitk::CollectionStatistic::GetStatisticData(unsigned char c) const { std::vector statistics; for (size_t i = 0; i < m_ImageClassStatistic.size(); i++) { statistics.push_back(m_ImageClassStatistic[i][c]); } return statistics; } void mitk::CollectionStatistic::ComputeRMSD() { assert(m_ClassCount == 2); assert(m_GroundTruthValueToIndexMapper != nullptr); assert(m_TestValueToIndexMapper != nullptr); DataCollectionImageIterator groundTruthIter(m_Collection, m_GroundTruthName); DataCollectionImageIterator testIter(m_Collection, m_TestName); DataCollectionImageIterator maskIter(m_Collection, m_MaskName); typedef itk::Image LabelImage; typedef itk::Image ImageType; typedef itk::SignedDanielssonDistanceMapImageFilter DistanceMapFilterType; typedef itk::ConstantBoundaryCondition BoundaryConditionType; typedef itk::ConstShapedNeighborhoodIterator ConstNeighborhoodIteratorType; // Build up 6-neighborhood. Diagonal voxel are maybe not considered for distance map computation. // So 6-neighborhood avoids inconsistencies. ConstNeighborhoodIteratorType::OffsetType offset0 = {{ 0, 0, -1}}; ConstNeighborhoodIteratorType::OffsetType offset1 = {{ 0, 0, 1}}; ConstNeighborhoodIteratorType::OffsetType offset2 = {{ 0, -1, 0}}; ConstNeighborhoodIteratorType::OffsetType offset3 = {{ 0, 1, 0}}; ConstNeighborhoodIteratorType::OffsetType offset4 = {{-1, 0, 0}}; ConstNeighborhoodIteratorType::OffsetType offset5 = {{ 1, 0, 0}}; const int outsideVal = 17; itk::NeighborhoodIterator::RadiusType radius; radius.Fill(1); BoundaryConditionType bc; // if a neighborhood voxel is outside of the image region a default value is returned bc.SetConstant(outsideVal); ConstNeighborhoodIteratorType neighborhoodIter; ImageType::Pointer distanceImage; std::vector* currentImageStatistics = nullptr; unsigned int distanceBorderSamples = 0; double totalBorderRMSDistance = 0; int previousImageIndex = -1; while (!testIter.IsAtEnd()) { int currentImageIndex = testIter.GetImageIndex(); // prepare data for next image if (previousImageIndex != currentImageIndex) { previousImageIndex = currentImageIndex; currentImageStatistics = &(m_ImageClassStatistic.at(currentImageIndex)); distanceBorderSamples = 0; totalBorderRMSDistance = 0; // generate distance map from gold standard image DistanceMapFilterType::Pointer distanceMapFilter = DistanceMapFilterType::New(); distanceMapFilter->SetInput(groundTruthIter.GetImageIterator().GetImage()); distanceMapFilter->SetUseImageSpacing(true); distanceMapFilter->Update(); distanceImage = distanceMapFilter->GetOutput(); neighborhoodIter = ConstNeighborhoodIteratorType(radius, testIter.GetImageIterator().GetImage(), testIter.GetImageIterator().GetImage()->GetRequestedRegion()); neighborhoodIter.OverrideBoundaryCondition(&bc); // configure 6-neighborhood neighborhoodIter.ActivateOffset(offset0); neighborhoodIter.ActivateOffset(offset1); neighborhoodIter.ActivateOffset(offset2); neighborhoodIter.ActivateOffset(offset3); neighborhoodIter.ActivateOffset(offset4); neighborhoodIter.ActivateOffset(offset5); } unsigned char testClass = m_TestValueToIndexMapper->operator()(testIter.GetVoxel()); if ( maskIter.GetVoxel() > 0 && testClass != 0) { // check if it is a border voxel neighborhoodIter.SetLocation(testIter.GetImageIterator().GetIndex()); bool border = false; ConstNeighborhoodIteratorType::ConstIterator iter; for (iter = neighborhoodIter.Begin(); !iter.IsAtEnd(); iter++) { if (iter.Get() == outsideVal) { continue; } if (m_TestValueToIndexMapper->operator()(iter.Get()) != 1 ) { border = true; break; } } if (border) { double currentDistance = distanceImage->GetPixel(testIter.GetImageIterator().GetIndex()); totalBorderRMSDistance += currentDistance * currentDistance; ++distanceBorderSamples; // update immediately, so the final value is set after the iterator of the last image has reached the end double rmsd = std::sqrt(totalBorderRMSDistance / (double) distanceBorderSamples); currentImageStatistics->at(1).m_RMSD = rmsd; } } ++groundTruthIter; ++testIter; ++maskIter; } } diff --git a/Modules/Classification/DataCollection/Utilities/mitkCostingStatistic.cpp b/Modules/Classification/DataCollection/Utilities/mitkCostingStatistic.cpp index 23484f3ed5..1fc4db1a46 100644 --- a/Modules/Classification/DataCollection/Utilities/mitkCostingStatistic.cpp +++ b/Modules/Classification/DataCollection/Utilities/mitkCostingStatistic.cpp @@ -1,196 +1,196 @@ #include #include #include #include // DataCollection Stuff #include //stl stuff #include static void EnsureDataImageInCollection(mitk::DataCollection::Pointer collection, std::string origin, std::string target) { typedef itk::Image FeatureImage; typedef itk::Image LabelImage; if (collection->HasElement(origin)) { LabelImage::Pointer originImage = dynamic_cast(collection->GetData(origin).GetPointer()); MITK_INFO << "Creating new Element"; if (!collection->HasElement(target) && originImage.IsNotNull()) { MITK_INFO << "New image necessary"; FeatureImage::Pointer image = FeatureImage::New(); image->SetRegions(originImage->GetLargestPossibleRegion()); image->SetSpacing(originImage->GetSpacing()); image->SetOrigin(originImage->GetOrigin()); image->SetDirection(originImage->GetDirection()); image->Allocate(); collection->AddData(dynamic_cast(image.GetPointer()),target,""); } } for (std::size_t i = 0; i < collection->Size();++i) { mitk::DataCollection* newCol = dynamic_cast(collection->GetData(i).GetPointer()); if (newCol != 0) { EnsureDataImageInCollection(newCol, origin, target); } } } static void EnsureLabelImageInCollection(mitk::DataCollection::Pointer collection, std::string origin, std::string target) { typedef itk::Image FeatureImage; typedef itk::Image LabelImage; if (collection->HasElement(origin)) { LabelImage::Pointer originImage = dynamic_cast(collection->GetData(origin).GetPointer()); MITK_INFO << "Creating new Element"; if (!collection->HasElement(target) && originImage.IsNotNull()) { MITK_INFO << "New image necessary"; FeatureImage::Pointer image = FeatureImage::New(); image->SetRegions(originImage->GetLargestPossibleRegion()); image->SetSpacing(originImage->GetSpacing()); image->SetOrigin(originImage->GetOrigin()); image->SetDirection(originImage->GetDirection()); image->Allocate(); collection->AddData(dynamic_cast(image.GetPointer()),target,""); } } for (std::size_t i = 0; i < collection->Size();++i) { mitk::DataCollection* newCol = dynamic_cast(collection->GetData(i).GetPointer()); if (newCol != 0) { EnsureLabelImageInCollection(newCol, origin, target); } } } void mitk::CostingStatistic::SetCollection(mitk::DataCollection::Pointer collection) { m_Collection = collection; } mitk::DataCollection::Pointer mitk::CostingStatistic::GetCollection() { return m_Collection; } bool mitk::CostingStatistic::UpdateCollection() { EnsureDataImageInCollection(m_Collection, m_MaskName, m_CombinedProbabilityA); EnsureDataImageInCollection(m_Collection, m_MaskName, m_CombinedProbabilityB); EnsureLabelImageInCollection(m_Collection, m_MaskName, m_CombinedLabelName); std::vector > iterProbA; std::vector > iterProbB; - for (int i = 0; i < m_ProbabilityClassA.size(); ++i) + for (std::size_t i = 0; i < m_ProbabilityClassA.size(); ++i) { DataCollectionImageIterator iter(m_Collection, m_ProbabilityClassA[i]); iterProbA.push_back(iter); } - for (int i = 0; i < m_ProbabilityClassB.size(); ++i) + for (std::size_t i = 0; i < m_ProbabilityClassB.size(); ++i) { DataCollectionImageIterator iter(m_Collection, m_ProbabilityClassB[i]); iterProbB.push_back(iter); } DataCollectionImageIterator iterCombineA(m_Collection, m_CombinedProbabilityA); DataCollectionImageIterator iterCombineB(m_Collection, m_CombinedProbabilityB); DataCollectionImageIterator iterMask(m_Collection, m_MaskName); while (!iterMask.IsAtEnd()) { if (iterMask.GetVoxel() > 0) { double probA = 0; double probB = 0; - for (int i = 0; i < iterProbA.size(); ++i) + for (std::size_t i = 0; i < iterProbA.size(); ++i) { probA += iterProbA[i].GetVoxel(); } - for (int i = 0; i < iterProbB.size(); ++i) + for (std::size_t i = 0; i < iterProbB.size(); ++i) { probB += iterProbB[i].GetVoxel(); } iterCombineA.SetVoxel(probA * 100); iterCombineB.SetVoxel(probB * 100); } else { iterCombineA.SetVoxel(0.0); iterCombineB.SetVoxel(0.0); } ++iterCombineA; ++iterCombineB; ++iterMask; - for (int i = 0; i < iterProbA.size(); ++i) + for (std::size_t i = 0; i < iterProbA.size(); ++i) { ++(iterProbA[i]); } - for (int i = 0; i < iterProbB.size(); ++i) + for (std::size_t i = 0; i < iterProbB.size(); ++i) { ++(iterProbB[i]); } } return 0; } bool mitk::CostingStatistic::CalculateClass(double threshold) { DataCollectionImageIterator iterMask(m_Collection, m_MaskName); DataCollectionImageIterator iterLabel(m_Collection, m_CombinedLabelName); DataCollectionImageIterator iterCombineA(m_Collection, m_CombinedProbabilityA); DataCollectionImageIterator iterCombineB(m_Collection, m_CombinedProbabilityB); while (!iterMask.IsAtEnd()) { if (iterMask.GetVoxel() > 0) { double probA = iterCombineA.GetVoxel() / (iterCombineA.GetVoxel() + iterCombineB.GetVoxel()); probA *= 100; iterLabel.SetVoxel(probA >= threshold ? 1 : 2); } else { iterLabel.SetVoxel(0); } ++iterMask; ++iterLabel; ++iterCombineA; ++iterCombineB; } return true; } bool mitk::CostingStatistic::WriteStatistic(std::ostream &out,std::ostream &sout, double stepSize, std::string shortLabel) { UpdateCollection(); for (double threshold = 0 ; threshold <= 100; threshold += stepSize) { CalculateClass(threshold); std::stringstream ss; ss << shortLabel << ";" << threshold; mitk::CollectionStatistic stat; stat.SetCollection(m_Collection); stat.SetClassCount(2); stat.SetGoldName("GTV"); stat.SetTestName(m_CombinedLabelName); stat.SetMaskName(m_MaskName); stat.Update(); stat.Print(out, sout,false, ss.str()); } return true; -} \ No newline at end of file +}