7 #include "fwGdcmIO/helper/DicomDir.hpp" 9 #include "fwGdcmIO/helper/DicomDataReader.hxx" 11 #include <fwCore/exceptionmacros.hpp> 14 #include <fwJobs/IJob.hpp> 15 #include <fwJobs/Observer.hpp> 17 #include <fwLog/Logger.hpp> 19 #include <fwMedData/DicomSeries.hpp> 21 #include <boost/algorithm/string.hpp> 22 #include <boost/filesystem/operations.hpp> 23 #include <boost/lexical_cast.hpp> 24 #include <boost/regex.h> 26 #include <gdcmMediaStorage.h> 27 #include <gdcmReader.h> 37 ::boost::filesystem::path current = root;
39 while(::boost::filesystem::exists(current))
41 ::boost::filesystem::path dicomDirPath = current /
"dicomdir";
42 if(::boost::filesystem::exists(dicomDirPath) && !::boost::filesystem::is_directory(dicomDirPath))
47 dicomDirPath = current /
"DICOMDIR";
48 if(::boost::filesystem::exists(dicomDirPath) && !::boost::filesystem::is_directory(dicomDirPath))
53 current = current.parent_path();
56 return ::boost::filesystem::path();
62 void processDirInformation(const ::boost::filesystem::path& dicomdir,
63 const ::boost::filesystem::path& rootDicomDirPath,
64 ::fwMedData::DicomSeries::sptr currentSeries,
65 std::map < std::string, ::fwMedData::DicomSeries::sptr >& dicomSeriesMap,
66 const ::fwLog::Logger::sptr& logger,
67 std::function<
void(std::uint64_t) >& progress,
68 std::function<
bool() >& cancel,
72 SLM_ASSERT(
"You must specify a valid dicomdir.", ::boost::filesystem::exists(dicomdir)
73 && !::boost::filesystem::is_directory(dicomdir));
76 ::gdcm::Reader reader;
77 reader.SetFileName(dicomdir.string().c_str());
83 const ::gdcm::File& gdcmFile = reader.GetFile();
84 const ::gdcm::DataSet& dataset = gdcmFile.GetDataSet();
87 ::gdcm::MediaStorage mediaStorage;
88 mediaStorage.SetFromFile(gdcmFile);
89 if(mediaStorage != ::gdcm::MediaStorage::MediaStorageDirectoryStorage )
96 const ::gdcm::FileMetaInformation& fileMetaInformation = gdcmFile.GetHeader();
97 const std::string& mediaStorageSOP =
98 ::fwGdcmIO::helper::DicomDataReader::getTagValue< 0x0002, 0x0002 >(fileMetaInformation);
100 if (mediaStorageSOP != ::gdcm::MediaStorage::GetMSString(::gdcm::MediaStorage::MediaStorageDirectoryStorage))
102 SLM_ERROR(
"This file is not a DICOMDIR");
107 typedef std::set<gdcm::DataElement> DataElementSet;
108 typedef DataElementSet::const_iterator ConstIterator;
110 for(ConstIterator it = dataset.GetDES().begin(); it != dataset.GetDES().end(); ++it)
113 if (it->GetTag() == ::gdcm::Tag(0x0004, 0x1220))
115 ::gdcm::SmartPointer< ::gdcm::SequenceOfItems > sequence = it->GetValueAsSQ();
116 ptotal +=
static_cast<double>(sequence->GetNumberOfItems());
118 for(
unsigned int index = 1; index <= sequence->GetNumberOfItems(); ++index)
121 ::gdcm::Item& item = sequence->GetItem(index);
124 const std::string recordType =
125 ::fwGdcmIO::helper::DicomDataReader::getTagValue< 0x0004, 0x1430 >(item.GetNestedDataSet());
128 std::string refFileID =
129 ::fwGdcmIO::helper::DicomDataReader::getTagValue< 0x0004, 0x1500 >(item.GetNestedDataSet());
131 if(recordType ==
"IMAGE")
134 std::string file = ::fwGdcmIO::helper::DicomDataReader::getTagValue< 0x0004, 0x1500 >(
135 item.GetNestedDataSet());
136 std::replace( file.begin(), file.end(),
'\\',
'/');
137 SLM_WARN_IF(
"Dicom instance doesn't have a referenced file id.", file.empty());
139 const ::boost::filesystem::path path = rootDicomDirPath / file;
140 OSLM_WARN_IF(
"Unable to find path :" << path, !::boost::filesystem::exists(path));
141 OSLM_WARN_IF(
"Dicomdir is badly formatted. Skipping path :" << path, !currentSeries);
143 if(!currentSeries || file.empty())
145 logger->warning(
"DICOMDIR file is badly formatted. Instances may be missing");
147 else if(::boost::filesystem::exists(path))
149 auto instanceNumber = ::boost::lexical_cast<
unsigned int>(
151 0x0013 >(item.GetNestedDataSet()));
152 currentSeries->addDicomPath(instanceNumber, path);
156 logger->warning(
"Unable to retrieve file :" + path.string());
162 if(recordType ==
"SERIES")
164 const std::string& seriesUID =
165 ::fwGdcmIO::helper::DicomDataReader::getTagValue< 0x0020, 0x000e >(item.GetNestedDataSet());
166 if(dicomSeriesMap.find(seriesUID) == dicomSeriesMap.end())
168 ::fwMedData::DicomSeries::sptr series = ::fwMedData::DicomSeries::New();
169 series->setInstanceUID(seriesUID);
170 dicomSeriesMap[seriesUID] = series;
173 currentSeries = dicomSeriesMap[seriesUID];
176 std::replace(refFileID.begin(), refFileID.end(),
'\\',
'/');
177 auto refFilePath = dicomdir.parent_path() / refFileID;
178 if(refFileID !=
"" && ::boost::filesystem::exists(refFilePath))
180 processDirInformation(refFilePath, rootDicomDirPath, currentSeries,
181 dicomSeriesMap, logger, progress, cancel, p, ptotal);
190 if( cancel && cancel() )
204 const ::fwLog::Logger::sptr& logger,
205 std::function<
void(std::uint64_t) > progress,
206 std::function<
bool() > cancel)
208 SLM_ASSERT(
"You must specify a valid dicomdir.", ::boost::filesystem::exists(dicomdir)
209 && !::boost::filesystem::is_directory(dicomdir));
212 ::gdcm::Reader reader;
213 reader.SetFileName(dicomdir.string().c_str());
219 const ::gdcm::File& gdcmFile = reader.GetFile();
220 const ::gdcm::DataSet& dataset = gdcmFile.GetDataSet();
223 ::gdcm::MediaStorage mediaStorage;
224 mediaStorage.SetFromFile(gdcmFile);
225 if(mediaStorage != ::gdcm::MediaStorage::MediaStorageDirectoryStorage )
227 SLM_ERROR(
"This file is not a DICOMDIR");
232 const ::gdcm::FileMetaInformation& fileMetaInformation = gdcmFile.GetHeader();
233 const std::string& mediaStorageSOP =
234 ::fwGdcmIO::helper::DicomDataReader::getTagValue< 0x0002, 0x0002 >(fileMetaInformation);
236 if (mediaStorageSOP != ::gdcm::MediaStorage::GetMSString(::gdcm::MediaStorage::MediaStorageDirectoryStorage))
238 SLM_ERROR(
"This file is not a DICOMDIR");
243 typedef std::set<gdcm::DataElement> DataElementSet;
244 typedef DataElementSet::const_iterator ConstIterator;
252 for(ConstIterator it = dataset.GetDES().begin(); it != dataset.GetDES().end(); ++it)
255 if (it->GetTag() == ::gdcm::Tag(0x0004, 0x1220))
257 ::gdcm::SmartPointer< ::gdcm::SequenceOfItems > sequence = it->GetValueAsSQ();
259 ptotal +=
static_cast<double>(sequence->GetNumberOfItems());
269 std::map < std::string, ::fwMedData::DicomSeries::sptr > dicomSeriesMap;
270 processDirInformation(dicomdir, dicomdir.parent_path(),
nullptr, dicomSeriesMap,
271 logger, progress, cancel, p, ptotal);
273 if( cancel && cancel() )
278 for(
auto entry : dicomSeriesMap)
280 auto series = entry.second;
281 const size_t size = series->getDicomContainer().size();
284 series->setNumberOfInstances(size);
285 seriesDB.push_back(series);
289 logger->critical(
"Unable to retrieve instances for this series : " + series->getInstanceUID());
static std::string getTagValue(const ::gdcm::DataSet &dataset, const std::string &charset="", const ::fwLog::Logger::sptr &logger=nullptr)
Return a string from a tag found in dataset. An empty string returned means the tag is not found or e...
static FWGDCMIO_API::boost::filesystem::path findDicomDir(const ::boost::filesystem::path &root)
Find the DICOMDIR file in the parent arborescence.
The namespace fwGdcmIO contains reader, writer and helper for dicom data.
#define SLM_ERROR(message)
#define SLM_ASSERT(message, cond)
work like 'assert' from 'cassert', with in addition a message logged by spylog (with FATAL loglevel) ...
#define OSLM_WARN_IF(message, cond)
static FWGDCMIO_API void retrieveDicomSeries(const ::boost::filesystem::path &dicomdir, std::vector< std::shared_ptr< ::fwMedData::DicomSeries > > &seriesDB, const std::shared_ptr< ::fwLog::Logger > &logger, std::function< void(std::uint64_t) > progress=nullptr, std::function< bool() > cancel=nullptr)
Create DicomSeries from information stored in DICOMDIR.
This file defines SpyLog macros. These macros are used to log messages to a file or to the console du...
#define SLM_WARN_IF(message, cond)