diff --git a/Modules/TumorInvasionAnalysis/src/ReaderWriter/mitkDiffusionCollectionReader.cpp b/Modules/TumorInvasionAnalysis/src/ReaderWriter/mitkDiffusionCollectionReader.cpp index 9c0def702a..14fa62d680 100644 --- a/Modules/TumorInvasionAnalysis/src/ReaderWriter/mitkDiffusionCollectionReader.cpp +++ b/Modules/TumorInvasionAnalysis/src/ReaderWriter/mitkDiffusionCollectionReader.cpp @@ -1,404 +1,406 @@ /*=================================================================== 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 "mitkDiffusionCollectionReader.h" #include #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::DiffusionCollectionReader::DiffusionCollectionReader() : m_Collection(nullptr), m_SubCollection(nullptr), m_DataItemCollection(nullptr), m_ColIgnore(false), m_ItemIgnore(false) { } mitk::DiffusionCollectionReader::~DiffusionCollectionReader() { this->Clear(); } /** * @brief Loads the xml file filename and generates the necessary instances. **/ mitk::DataCollection::Pointer mitk::DiffusionCollectionReader::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::DiffusionCollectionReader::AddDataElementIds(std::vector dataElemetIds) { m_SelectedDataItemIds.insert( m_SelectedDataItemIds.end(), dataElemetIds.begin(), dataElemetIds.end() ); } void mitk::DiffusionCollectionReader::AddSubColIds(std::vector subColIds) { m_SelectedSubColIds.insert( m_SelectedSubColIds.end(), subColIds.begin(), subColIds.end() ); } void mitk::DiffusionCollectionReader::SetDataItemNames(std::vector itemNames) { m_SelectedDataItemNames = itemNames; } void mitk::DiffusionCollectionReader::ClearDataElementIds() { m_SelectedDataItemIds.clear(); } void mitk::DiffusionCollectionReader::ClearSubColIds() { m_SelectedSubColIds.clear(); } void mitk::DiffusionCollectionReader::Clear() { m_DataItemCollection = nullptr; m_SubCollection = nullptr; m_Collection = nullptr; } mitk::DataCollection::Pointer mitk::DiffusionCollectionReader::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) { std::string fileName = fileList.at(i).at(k); if (fileName.find(".fib") >= fileName.length()) { Image::Pointer image = IOUtil::LoadImage(fileList.at(i).at(k)); subCollection->AddData(image.GetPointer(),seriesNames.at(i), fileList.at(i).at(k)); } else { subCollection->AddData(mitk::IOUtil::Load(fileName).at(0).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::DiffusionCollectionReader::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 if (itemLink.find(".fib") >= itemLink.length()) { 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 m_DataItemCollection->AddData(mitk::IOUtil::Load(itemLink).at(0).GetPointer(),itemName, relativeItemLink); } else MITK_WARN<< "Malformed description ? -- unknown tag: " << name; } void mitk::DiffusionCollectionReader::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::DiffusionCollectionReader::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::DiffusionCollectionReader::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::DiffusionCollectionReader::ReadXMLIntegerAttribut(std::string name, const char** atts) { std::string s = ReadXMLStringAttribut(name, atts); return atoi(s.c_str()); } mitk::DiffusionCollectionReader::FileListType mitk::DiffusionCollectionReader::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/TumorInvasionAnalysis/src/ReaderWriter/mitkDiffusionCollectionWriter.cpp b/Modules/TumorInvasionAnalysis/src/ReaderWriter/mitkDiffusionCollectionWriter.cpp index f373f3f0ff..ffcdafa978 100755 --- a/Modules/TumorInvasionAnalysis/src/ReaderWriter/mitkDiffusionCollectionWriter.cpp +++ b/Modules/TumorInvasionAnalysis/src/ReaderWriter/mitkDiffusionCollectionWriter.cpp @@ -1,462 +1,464 @@ /*=================================================================== 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 "mitkDiffusionCollectionWriter.h" #include #include #include #include "mitkImageCast.h" #include "mitkTensorImage.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::DiffusionCollectionWriter::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::DiffusionCollectionWriter::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::DiffusionCollectionWriter::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 { if (itemCollections->IndexToName(s) == "DTI" || itemCollections->IndexToName(s) == "DTIFWE") { fileName += ".dti"; IOUtil::Save(image,fileName.toStdString()); } else if (itemCollections->IndexToName(s) == "FIB") { fileName += ".fib"; FiberBundle* fib = dynamic_cast (itemCollections->GetData(s).GetPointer()); IOUtil::Save(fib, fileName.toStdString()); } else if (itemCollections->IndexToName(s) == "DWI") { fileName += ".dwi"; IOUtil::Save(image,fileName.toStdString()); } else { fileName += ".nrrd"; Image::Pointer image = itemCollections->GetMitkImage(s).GetPointer(); 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::DiffusionCollectionWriter::ExportCollectionToFolder(mitk::DataCollection *dataCollection, std::string xmlFile) { std::vector mods; return ExportCollectionToFolder(dataCollection,xmlFile, mods); } bool mitk::DiffusionCollectionWriter::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::DiffusionCollectionWriter::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::DiffusionCollectionWriter::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 (itemCollections->IndexToName(s) == "DTI" || itemCollections->IndexToName(s) == "DTIFWE") { if (!fullName) fileName += ".dti"; IOUtil::Save(image,fileName.toStdString()); } else if (itemCollections->IndexToName(s) == "FIB") { if (!fullName) fileName += ".fib"; FiberBundle* fib = dynamic_cast (itemCollections->GetData(s).GetPointer()); IOUtil::Save(fib, fileName.toStdString()); } else if (itemCollections->IndexToName(s) == "DWI") { if (!fullName) fileName += ".dwi"; IOUtil::Save(image,fileName.toStdString()); } else { if (!fullName) fileName += ".nrrd"; Image::Pointer image = itemCollections->GetMitkImage(s).GetPointer(); 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::DiffusionCollectionWriter::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) DiffusionCollectionReader::FileListType fileList = DiffusionCollectionReader::SanitizeFileList(DiffusionCollectionReader::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::DiffusionCollectionWriter::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) DiffusionCollectionReader::FileListType fileList = DiffusionCollectionReader::SanitizeFileList(DiffusionCollectionReader::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::DiffusionCollectionWriter::GetIndexForinXMonths(mitk::DiffusionCollectionReader::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/TumorInvasionAnalysis/test/mitkClassificationTest.cpp b/Modules/TumorInvasionAnalysis/test/mitkClassificationTest.cpp index 4fa06cebb0..a9f96f9ce7 100644 --- a/Modules/TumorInvasionAnalysis/test/mitkClassificationTest.cpp +++ b/Modules/TumorInvasionAnalysis/test/mitkClassificationTest.cpp @@ -1,107 +1,109 @@ /*=================================================================== 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 "mitkTestFixture.h" #include "mitkTestingMacros.h" #include "mitkCompareImageDataFilter.h" #include "mitkIOUtil.h" #include "mitkDataCollection.h" #include "mitkTumorInvasionClassification.h" #include "mitkDiffusionCollectionReader.h" #include "mitkDiffusionCollectionWriter.h" #include /** * @brief mitkClassificationTestSuite * * Tests mitkDecisionForest, mitkClassifyProgression, mitkDataCollection, mitkDiffusionCollectionReader * \warn Reference is compared to results computed based on random forests, which might be a source of random test fails * such sporadic fails do represent total fails, as the result is no longer consitently under the provided margin. * */ class mitkClassificationTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkClassificationTestSuite); MITK_TEST(TestClassification); CPPUNIT_TEST_SUITE_END(); public: /** * @brief Setup - Always call this method before each Test-case to ensure correct and new intialization of the used * members for a new test case. (If the members are not used in a test, the method does not need to be called). */ void setUp() {} void tearDown() {} void TestClassification() { size_t forestSize = 10; size_t treeDepth = 2; std::string train = GetTestDataFilePath("DiffusionImaging/ProgressionAnalysis/Classification/Train.xml"); std::string eval = GetTestDataFilePath("DiffusionImaging/ProgressionAnalysis/Classification/Test.xml"); std::vector modalities; modalities.push_back("MOD0"); modalities.push_back("MOD1"); mitk::DiffusionCollectionReader colReader; mitk::DataCollection::Pointer collection = colReader.LoadCollection(train); colReader.Clear(); // read evaluation collection mitk::DataCollection::Pointer evaluation = colReader.LoadCollection(eval); mitk::TumorInvasionClassification progression; progression.SetClassRatio(1); progression.SetTrainMargin(4, 0); progression.SetMaskID("MASK"); progression.SelectTrainingSamples(collection); progression.LearnProgressionFeatures(collection, modalities, forestSize, treeDepth); progression.PredictInvasion(evaluation, modalities); mitk::Image::Pointer refImage = mitk::IOUtil::LoadImage( GetTestDataFilePath("DiffusionImaging/ProgressionAnalysis/Classification/TESTING_RESULT.nrrd")); mitk::DataCollection *patCol = dynamic_cast(evaluation->GetData(0).GetPointer()); mitk::DataCollection *subCol = dynamic_cast(patCol->GetData(0).GetPointer()); mitk::Image::Pointer resultImage = subCol->GetMitkImage("RESULT"); // Test result against fixed reference. // Require more than 90% to be correct. // 10% margin due to // 1) unsure classification in transitional regions and // 2) stochastic training procedure // Total number of voxels 2400 -> 10% err -> 240 voxels margin mitk::CompareImageDataFilter::Pointer compareFilter = mitk::CompareImageDataFilter::New(); compareFilter->SetInput(0, refImage.GetPointer()); compareFilter->SetInput(1, resultImage); compareFilter->SetTolerance(.1); compareFilter->Update(); MITK_TEST_CONDITION_REQUIRED(compareFilter->GetResult(240), "Compare prediction results to reference image.") } }; MITK_TEST_SUITE_REGISTRATION(mitkClassification)