7 #include "fwDcmtkIO/SeriesDBReader.hpp" 9 #include "fwDcmtkIO/helper/Codec.hpp" 10 #include "fwDcmtkIO/helper/DicomDir.hpp" 11 #include "fwDcmtkIO/helper/DicomSearch.hpp" 12 #include "fwDcmtkIO/reader/ImageStorageReader.hpp" 14 #include <fwDataIO/reader/registry/macros.hpp> 16 #include <fwDcmtkTools/Dictionary.hpp> 18 #include <fwDicomIOFilter/composite/CTImageStorageDefaultComposite.hpp> 19 #include <fwDicomIOFilter/exceptions/FilterFailure.hpp> 20 #include <fwDicomIOFilter/helper/Filter.hpp> 21 #include <fwDicomIOFilter/splitter/SOPClassUIDSplitter.hpp> 23 #include <fwMedData/Equipment.hpp> 24 #include <fwMedData/ImageSeries.hpp> 25 #include <fwMedData/ModelSeries.hpp> 26 #include <fwMedData/Patient.hpp> 27 #include <fwMedData/SeriesDB.hpp> 28 #include <fwMedData/Study.hpp> 30 #include <fwMedDataTools/helper/SeriesDB.hpp> 32 #include <dcmtk/config/osconfig.h> 33 #include <dcmtk/dcmdata/dcdeftag.h> 34 #include <dcmtk/dcmdata/dcfilefo.h> 35 #include <dcmtk/dcmdata/dcistrmb.h> 36 #include <dcmtk/dcmnet/diutil.h> 46 ::
fwData::location::enableFolder< IObjectReader >(this),
47 ::
fwData::location::enableMultiFiles< IObjectReader >(this),
48 m_isDicomdirActivated(false)
61 SeriesDBReader::~SeriesDBReader()
69 SeriesDBReader::FilenameContainerType SeriesDBReader::getFilenames()
71 FilenameContainerType filenames;
72 if(::fwData::location::have < ::fwData::location::Folder, ::fwDataIO::reader::IObjectReader > (
this))
75 if(!m_isDicomdirActivated || (m_isDicomdirActivated &&
82 else if(::fwData::location::have < ::fwData::location::MultiFiles, ::fwDataIO::reader::IObjectReader > (
this))
84 for(::boost::filesystem::path file: this->
getFiles())
86 filenames.push_back(file.string());
100 FilenameContainerType filenames = this->getFilenames();
103 this->addSeries(filenames);
106 if(!m_dicomFilterType.empty())
108 ::fwDicomIOFilter::IFilter::sptr filter = ::fwDicomIOFilter::factory::New(m_dicomFilterType);
109 SLM_ASSERT(
"Failed to instantiate filter of type '" + m_dicomFilterType +
"'.", filter);
114 for(::fwMedData::DicomSeries::csptr series: m_dicomSeriesContainer)
116 this->convertDicomSeries(series);
122 void SeriesDBReader::readFromDicomSeriesDB(::fwMedData::SeriesDB::csptr dicomSeriesDB,
123 ::fwServices::IService::sptr notifier)
126 for(const ::fwMedData::Series::csptr& series : dicomSeriesDB->getContainer())
128 ::fwMedData::DicomSeries::csptr dicomSeries = ::fwMedData::DicomSeries::dynamicCast(series);
129 OSLM_ASSERT(
"Trying to read a series which is not a DicomSeries.", dicomSeries);
130 this->convertDicomSeries(dicomSeries, notifier);
136 void SeriesDBReader::readDicomSeries()
142 FilenameContainerType filenames = this->getFilenames();
145 this->addSeries(filenames);
148 for(::fwMedData::DicomSeries::sptr series: m_dicomSeriesContainer)
150 seriesDBHelper.
add(series);
156 bool SeriesDBReader::isDicomDirAvailable()
158 std::vector<std::string> filenames;
160 return result && !filenames.empty();
165 void SeriesDBReader::addSeries(
const std::vector< std::string >& filenames)
167 for(
const std::string& filename : filenames)
169 DcmFileFormat fileFormat;
170 OFCondition status = fileFormat.loadFile(filename.c_str());
171 FW_RAISE_IF(
"Unable to read the file: \""+filename+
"\"", status.bad());
173 DcmDataset* dataset = fileFormat.getDataset();
176 this->createSeries(dataset, filename);
180 for(const ::fwMedData::DicomSeries::sptr& series : m_dicomSeriesContainer)
183 series->setNumberOfInstances(series->getDicomContainer().size());
186 const auto& bufferObj = series->getDicomContainer().begin()->second;
187 const size_t buffSize = bufferObj->getSize();
189 char* buffer =
static_cast< char*
>( lock.
getBuffer() );
191 DcmInputBufferStream is;
192 is.setBuffer(buffer, offile_off_t(buffSize));
196 DcmFileFormat fileFormat;
197 fileFormat.transferInit();
198 if (!fileFormat.read(is).good())
200 FW_RAISE(
"Unable to read Dicom file '"<< bufferObj->getStreamInfo().fsFile.string() <<
"'");
203 fileFormat.loadAllDataIntoMemory();
204 fileFormat.transferEnd();
206 DcmDataset* dataset = fileFormat.getDataset();
209 ::fwMedData::Patient::sptr patient = this->createPatient(dataset);
210 ::fwMedData::Study::sptr study = this->createStudy(dataset);
211 ::fwMedData::Equipment::sptr equipment = this->createEquipment(dataset);
214 series->setPatient(patient);
215 series->setStudy(study);
216 series->setEquipment(equipment);
222 ::fwMedData::Patient::sptr SeriesDBReader::createPatient(DcmDataset* dataset)
224 ::fwMedData::Patient::sptr result;
228 dataset->findAndGetOFStringArray(DCM_PatientID, data);
229 ::std::string patientID = data.c_str();
232 if(m_patientMap.find(patientID) == m_patientMap.end())
234 result = ::fwMedData::Patient::New();
235 m_patientMap[patientID] = result;
238 result->setPatientId(patientID);
241 dataset->findAndGetOFStringArray(DCM_PatientName, data);
242 result->setName(data.c_str());
245 dataset->findAndGetOFStringArray(DCM_PatientBirthDate, data);
246 result->setBirthdate(data.c_str());
249 dataset->findAndGetOFStringArray(DCM_PatientSex, data);
250 result->setSex(data.c_str());
255 result = m_patientMap[patientID];
263 ::fwMedData::Study::sptr SeriesDBReader::createStudy(DcmDataset* dataset)
265 ::fwMedData::Study::sptr result;
269 dataset->findAndGetOFStringArray(DCM_StudyInstanceUID, data);
270 ::std::string studyID = data.c_str();
273 if(m_studyMap.find(studyID) == m_studyMap.end())
275 result = ::fwMedData::Study::New();
276 m_studyMap[studyID] = result;
279 result->setInstanceUID(studyID);
282 dataset->findAndGetOFStringArray(DCM_StudyDate, data);
283 result->setDate(data.c_str());
286 dataset->findAndGetOFStringArray(DCM_StudyTime, data);
287 result->setTime(data.c_str());
290 dataset->findAndGetOFStringArray(DCM_ReferringPhysicianName, data);
291 result->setReferringPhysicianName(data.c_str());
294 dataset->findAndGetOFStringArray(DCM_StudyDescription, data);
295 result->setDescription(data.c_str());
298 dataset->findAndGetOFStringArray(DCM_PatientAge, data);
299 result->setPatientAge(data.c_str());
304 result = m_studyMap[studyID];
312 ::fwMedData::Equipment::sptr SeriesDBReader::createEquipment(DcmDataset* dataset)
314 ::fwMedData::Equipment::sptr result;
318 dataset->findAndGetOFStringArray(DCM_InstitutionName, data);
319 ::std::string institutionName = data.c_str();
322 if(m_equipmentMap.find(institutionName) == m_equipmentMap.end())
324 result = ::fwMedData::Equipment::New();
325 m_equipmentMap[institutionName] = result;
328 result->setInstitutionName(institutionName);
333 result = m_equipmentMap[institutionName];
341 void SeriesDBReader::createSeries(DcmDataset* dataset,
const std::string& filename)
343 ::fwMedData::DicomSeries::sptr series = ::fwMedData::DicomSeries::sptr();
347 dataset->findAndGetOFStringArray(DCM_SeriesInstanceUID, data);
348 std::string seriesInstanceUID = data.c_str();
351 for(const ::fwMedData::DicomSeries::sptr& dicomSeries : m_dicomSeriesContainer)
353 if(dicomSeries->getInstanceUID() == seriesInstanceUID)
355 series = dicomSeries;
363 series = ::fwMedData::DicomSeries::New();
364 m_dicomSeriesContainer.push_back(series);
367 series->setInstanceUID(seriesInstanceUID);
370 dataset->findAndGetOFStringArray(DCM_Modality, data);
371 series->setModality(data.c_str());
374 dataset->findAndGetOFStringArray(DCM_SeriesDate, data);
375 series->setDate(data.c_str());
378 dataset->findAndGetOFStringArray(DCM_SeriesTime, data);
379 series->setTime(data.c_str());
382 dataset->findAndGetOFStringArray(DCM_SeriesDescription, data);
383 series->setDescription(data.c_str());
386 std::vector<std::string> performingPhysiciansName;
387 for(
int i = 0; dataset->findAndGetOFString(DCM_PerformingPhysicianName, data, i).good(); ++i)
389 performingPhysiciansName.push_back(data.c_str());
391 series->setPerformingPhysiciansName(performingPhysiciansName);
395 dataset->findAndGetOFStringArray(DCM_SOPClassUID, data);
396 ::fwMedData::DicomSeries::SOPClassUIDContainerType sopClassUIDContainer = series->getSOPClassUIDs();
397 sopClassUIDContainer.insert(data.c_str());
398 series->setSOPClassUIDs(sopClassUIDContainer);
401 const std::size_t instanceNumber = series->getDicomContainer().size();
402 series->addDicomPath(instanceNumber, filename);
407 void SeriesDBReader::convertDicomSeries(::fwMedData::DicomSeries::csptr dicomSeries,
408 ::fwServices::IService::sptr notifier)
412 ::fwMedData::Series::sptr result = ::fwMedData::Series::sptr();
414 ::fwMedData::DicomSeries::SOPClassUIDContainerType sopClassUIDContainer = dicomSeries->getSOPClassUIDs();
415 FW_RAISE_IF(
"The series contains several SOPClassUIDs. Try to apply a filter in order to split the series.",
416 sopClassUIDContainer.size() != 1);
417 std::string sopClassUID = sopClassUIDContainer.begin()->c_str();
419 const SupportedSOPClassContainerType::iterator bIt = m_supportedSOPClassContainer.begin();
420 const SupportedSOPClassContainerType::iterator eIt = m_supportedSOPClassContainer.end();
422 if(m_supportedSOPClassContainer.empty() || std::find(bIt, eIt, sopClassUID) != eIt)
425 result = reader.
read(dicomSeries);
431 seriesDBHelper.
add(result);
435 OSLM_WARN(
"\""+sopClassUID+
"\" SOPClassUID is not supported.");
447 SeriesDBReader::DicomSeriesContainerType& SeriesDBReader::getDicomSeries()
449 return m_dicomSeriesContainer;
ILocation::PathType getFolder()
Get folder filesystem path.
#define OSLM_ASSERT(message, cond)
work like 'assert' from 'cassert', with in addition a message logged by spylog (with FATAL loglevel) ...
#define SLM_TRACE_FUNC()
Trace contextual function signature.
Reads DICOM data from a directory path in order to create a SeriesDB object.
static FWDCMTKIO_API void registerCodecs()
Load DICOM codec.
VTKGDCMIO_API void read() override
Reads DICOM data from configured path and fills SeriesDB object.
Key class used to restrict access to Object construction. See http://www.drdobbs.com/184402053.
static FWDCMTKIO_API bool readDicomDir(const ::boost::filesystem::path &root, std::vector< std::string > &dicomFiles)
Find Dicom instances in a DicomDir file.
base class for BufferObject Lock
static FWDICOMIOFILTER_API bool applyFilter(DicomSeriesContainerType &dicomSeriesContainer,::fwDicomIOFilter::IFilter::sptr filter, bool forcedApply=false, const ::fwLog::Logger::sptr &logger=::fwLog::Logger::New())
Apply a filter to the DicomSeries.
LockBase< T >::BufferType getBuffer() const
Returns BufferObject's buffer pointer.
#define OSLM_WARN(message)
Base class for Dicom instance reader.
#define SLM_ASSERT(message, cond)
work like 'assert' from 'cassert', with in addition a message logged by spylog (with FATAL loglevel) ...
static FWDCMTKIO_API void searchRecursively(const ::boost::filesystem::path &dirPath, std::vector< std::string > &dicomFiles)
Search Dicom files recursively.
virtual std::shared_ptr< DataType > getConcreteObject()
m_object getter.
virtual FWDCMTKIO_API::fwMedData::Series::sptr read(const ::fwMedData::DicomSeries::csptr &series)
Override.
static FWDCMTKIO_API void cleanup()
Clean up codec register.
fwDcmtkIO contains classes used to pull Dicom images from a pacs using dcmtk library.
ILocation::VectPathType getFiles()
Get file system paths.
Contains the representation of the data objects used in the framework.