fw4spl
DicomSeriesDBWriter.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2018.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #include "fwGdcmIO/helper/DicomSeriesDBWriter.hpp"
8 
9 #include "fwGdcmIO/helper/DicomAnonymizer.hpp"
10 #include "fwGdcmIO/helper/DicomSeriesWriter.hpp"
11 
12 #include <fwJobs/Aggregator.hpp>
13 #include <fwJobs/Job.hpp>
14 #include <fwJobs/Observer.hpp>
15 
16 #include <fwMedData/DicomSeries.hpp>
17 #include <fwMedData/Series.hpp>
18 #include <fwMedData/SeriesDB.hpp>
19 
20 #include <fwServices/registry/ActiveWorkers.hpp>
21 
22 #include <fwZip/WriteDirArchive.hpp>
23 #include <fwZip/WriteZipArchive.hpp>
24 
25 namespace fwGdcmIO
26 {
27 
28 namespace helper
29 {
30 
31 //------------------------------------------------------------------------------
32 
34  ::fwData::location::enableFolder< ::fwDataIO::writer::IObjectWriter >(this),
35  ::fwData::location::enableSingleFile< ::fwDataIO::writer::IObjectWriter >(this),
36  m_aggregator(::fwJobs::Aggregator::New("Writing Dicom series")),
37  m_enableZippedArchive(false)
38 
39 {
40 }
41 
42 //------------------------------------------------------------------------------
43 
45 {
46 }
47 
48 //------------------------------------------------------------------------------
49 
51 {
52  return "";
53 }
54 
55 //------------------------------------------------------------------------------
56 
58 {
59  return m_aggregator;
60 }
61 
62 //------------------------------------------------------------------------------
63 
64 void DicomSeriesDBWriter::setAnonymizer(const DicomAnonymizer::sptr& anonymizer)
65 {
66  m_anonymizer = anonymizer;
67 }
68 
69 //------------------------------------------------------------------------------
70 
71 void DicomSeriesDBWriter::setProducer(std::string producer)
72 {
73  m_producer = producer;
74 }
75 
76 //------------------------------------------------------------------------------
77 
79 {
80  m_enableZippedArchive = enable;
81 }
82 //------------------------------------------------------------------------------
83 
84 std::string getSubPath(int index)
85 {
86  std::stringstream ss;
87  ss << std::setfill('0') << std::setw(3) << index;
88  return ss.str();
89 }
90 
91 //------------------------------------------------------------------------------
92 
94 {
95  ::fwMedData::SeriesDB::csptr seriesDB = this->getConcreteObject();
96  SLM_ASSERT("Unable to retrieve associated SeriesDB", seriesDB);
97 
98  ::fwZip::IWriteArchive::sptr writeArchive;
99 
100  if(m_enableZippedArchive)
101  {
102  ::fwZip::WriteZipArchive::sptr writeZipArchive = ::fwZip::WriteZipArchive::New(this->getFile(), m_producer);
103 
104  writeArchive = writeZipArchive;
105  }
106  else
107  {
108  writeArchive = ::fwZip::WriteDirArchive::New(this->getFolder());
109  }
110 
111  const auto nbSeries = seriesDB->getContainer().size();
112  int processedSeries = 0;
113 
114  for(::fwMedData::Series::sptr series: seriesDB->getContainer())
115  {
116  const ::fwMedData::DicomSeries::sptr& dicomSeries = ::fwMedData::DicomSeries::dynamicCast(series);
117 
118  ::fwJobs::Job::sptr job = ::fwJobs::Job::New("Write Dicom series", [&, dicomSeries](::fwJobs::Job& runningJob)
119  {
120  if(!runningJob.cancelRequested())
121  {
122  m_anonymizer->resetIndex();
123 
124  ::fwGdcmIO::helper::DicomSeriesWriter::sptr writer = ::fwGdcmIO::helper::DicomSeriesWriter::New();
125  writer->setObject(dicomSeries);
126  writer->setAnonymizer(m_anonymizer);
127  writer->setOutputArchive(writeArchive, nbSeries > 1 ? getSubPath(processedSeries++) : "");
128 
129  runningJob.addCancelHook([&](::fwJobs::IJob& subJob)
130  {
131  writer->getJob()->cancel();
132  }
133  );
134 
135  writer->getJob()->addDoneWorkHook([&](::fwJobs::IJob& subJob, std::uint64_t oldWork)
136  {
137  runningJob.doneWork(subJob.getDoneWorkUnits());
138  });
139 
140  try
141  {
142  writer->write();
143  }
144  catch(std::exception& e)
145  {
146  runningJob.log(std::string("Failed to write series :\n") + e.what());
147  }
148  catch(...)
149  {
150  runningJob.log("An unexpected error occurred while writing series");
151  }
152  }
153  },
155 
156  m_aggregator->addCancelHook([&](::fwJobs::IJob& subJob)
157  {
158  job->cancel();
159  }
160  );
161  m_aggregator->add(job);
162  }
163 
164  auto futureAG = m_aggregator->run();
165 
166  futureAG.wait();
167 }
168 
169 //------------------------------------------------------------------------------
170 } // namespace helper
171 } // namespace fwGdcmIO
ILocation::PathType getFolder()
Get folder filesystem path.
Definition: Folder.hpp:99
FWJOBS_API void log(const std::string &message)
Log a message.
Definition: IJob.cpp:305
FWGDCMIO_API void write() override
Write the image series in DICOM format.
FWJOBS_API void doneWork(std::uint64_t units)
Setter on done work units.
Definition: IJob.cpp:379
FWGDCMIO_API void enableZippedArchive(bool enable)
Enable Zip output format.
This class is an interface for class managing job.
Definition: IJob.hpp:28
This namespace fwDataIO contains reader and writer for several framework&#39;s data.
virtual std::shared_ptr< const DataType > getConcreteObject() const
m_object getter.
Key class used to restrict access to Object construction. See http://www.drdobbs.com/184402053.
The namespace fwGdcmIO contains reader, writer and helper for dicom data.
std::shared_ptr< ::fwJobs::Aggregator > sptr
Aggregator container type.
Definition: Aggregator.hpp:39
FWJOBS_API const bool & cancelRequested() const
Returns the job canceling status.
Definition: IJob.cpp:52
virtual FWGDCMIO_API ~DicomSeriesDBWriter()
Construtor/Destructor.
This class encapsulate a task that will report it&#39;s progression The embeded task will be run at most ...
Definition: Job.hpp:30
FWJOBS_API std::uint64_t getDoneWorkUnits() const
Getter on the number of done work units.
Definition: IJob.cpp:71
FWGDCMIO_API std::string extension() override
Return an empty string.
FWGDCMIO_API void setProducer(std::string producer)
Set Producer.
#define SLM_ASSERT(message, cond)
work like &#39;assert&#39; from &#39;cassert&#39;, with in addition a message logged by spylog (with FATAL loglevel) ...
Definition: spyLog.hpp:308
static FWSERVICES_API::fwThread::Worker::sptr getDefaultWorker()
Get the default registered worker.
FWJOBS_API void addCancelHook(JobCancelHook callback)
Add cancel callback to sequence for cancel hook.
Definition: IJob.cpp:134
static FWJOBS_API sptr New(const std::string &name, Task task, const std::shared_ptr< ::fwThread::Worker > &worker=nullptr)
Construct a new job and return a smart pointer of it.
Definition: Job.cpp:25
Contains the representation of the data objects used in the framework.
FWGDCMIO_API DicomSeriesDBWriter(::fwDataIO::writer::IObjectWriter::Key key)
Construtor/Destructor.
This namespace fwJobs provides jobs management.
std::shared_ptr< ::fwJobs::Job > sptr
Task type.
Definition: Job.hpp:36
FWGDCMIO_API std::shared_ptr< ::fwJobs::Aggregator > getAggregator()
Get job Aggregator.
FWGDCMIO_API void setAnonymizer(const std::shared_ptr< helper::DicomAnonymizer > &anonymizer)
Set anonymizer (if anonymization required)