7 #include "ioDicom/SSliceIndexDicomEditor.hpp" 9 #include <fwCom/Signal.hpp> 10 #include <fwCom/Signal.hxx> 11 #include <fwCom/Signals.hpp> 12 #include <fwCom/Slot.hpp> 13 #include <fwCom/Slots.hpp> 14 #include <fwCom/Slots.hxx> 16 #include <fwData/Array.hpp> 17 #include <fwData/Composite.hpp> 18 #include <fwData/Image.hpp> 19 #include <fwData/Integer.hpp> 21 #include <fwDataTools/fieldHelper/Image.hpp> 22 #include <fwDataTools/helper/Array.hpp> 23 #include <fwDataTools/helper/Composite.hpp> 25 #include <fwGui/dialog/MessageDialog.hpp> 27 #include <fwGuiQt/container/QtContainer.hpp> 29 #include <fwMedData/DicomSeries.hpp> 30 #include <fwMedData/ImageSeries.hpp> 31 #include <fwMedData/SeriesDB.hpp> 33 #include <fwMedDataTools/helper/SeriesDB.hpp> 35 #include <fwServices/macros.hpp> 36 #include <fwServices/registry/ActiveWorkers.hpp> 37 #include <fwServices/registry/ObjectService.hpp> 39 #include <fwThread/Timer.hpp> 41 #include <fwTools/System.hpp> 43 #include <boost/asio/placeholders.hpp> 44 #include <boost/filesystem/fstream.hpp> 45 #include <boost/filesystem/operations.hpp> 46 #include <boost/foreach.hpp> 48 #include <QApplication> 50 #include <QHBoxLayout> 51 #include <QMouseEvent> 60 const ::fwCom::Slots::SlotKeyType SSliceIndexDicomEditor::s_READ_IMAGE_SLOT =
"readImage";
61 const ::fwCom::Slots::SlotKeyType SSliceIndexDicomEditor::s_DISPLAY_MESSAGE_SLOT =
"displayErrorMessage";
84 ::fwRuntime::ConfigurationElement::sptr config =
m_configuration->findConfigurationElement(
"config");
85 SLM_ASSERT(
"The service ::ioDicom::SSliceIndexDicomEditor must have " 86 "a \"config\" element.", config);
91 ::boost::tie(success, m_dicomReaderType) = config->getSafeAttributeValue(
"dicomReader");
92 SLM_ASSERT(
"It should be a \"dicomReader\" tag in the ::ioDicom::SSliceIndexDicomEditor " 93 "config element.", success);
96 ::fwRuntime::ConfigurationElement::sptr readerConfig = config->findConfigurationElement(
"dicomReaderConfig");
98 (readerConfig && readerConfig->size() == 1) ? readerConfig->getElements()[0] :
nullptr;
101 std::string delayStr;
102 ::boost::tie(success, delayStr) = config->getSafeAttributeValue(
"delay");
105 m_delay = ::boost::lexical_cast< std::size_t >(delayStr);
116 ::fwGuiQt::container::QtContainer::sptr qtContainer = fwGuiQt::container::QtContainer::dynamicCast(getContainer());
118 QHBoxLayout* layout =
new QHBoxLayout();
120 ::fwMedData::DicomSeries::csptr dicomSeries = this->getInput< ::fwMedData::DicomSeries >(
"series");
121 SLM_ASSERT(
"DicomSeries should not be null !", dicomSeries);
122 m_numberOfSlices = dicomSeries->getNumberOfInstances();
125 m_sliceIndexSlider =
new QSlider(Qt::Horizontal);
126 layout->addWidget(m_sliceIndexSlider, 1);
127 m_sliceIndexSlider->setRange(0, static_cast<int>(m_numberOfSlices-1));
128 m_sliceIndexSlider->setValue(static_cast<int>(m_numberOfSlices/2));
131 m_sliceIndexLineEdit =
new QLineEdit();
132 layout->addWidget(m_sliceIndexLineEdit, 0);
133 m_sliceIndexLineEdit->setReadOnly(
true);
134 m_sliceIndexLineEdit->setMaximumWidth(80);
136 std::stringstream ss;
137 ss << m_sliceIndexSlider->value() <<
" / " << (m_numberOfSlices-1);
138 m_sliceIndexLineEdit->setText(std::string(ss.str()).c_str());
140 qtContainer->setLayout(layout);
143 QObject::connect(m_sliceIndexSlider, SIGNAL(valueChanged(
int)),
this, SLOT(changeSliceIndex(
int)));
146 m_tempSeriesDB = ::fwMedData::SeriesDB::New();
151 ::fwIO::IReader::sptr dicomReader;
152 dicomReader = ::fwIO::IReader::dynamicCast(srvFactory->create(m_dicomReaderType));
153 SLM_ASSERT(
"Unable to create a reader of type: \"" + m_dicomReaderType +
"\" in " 154 "::ioDicom::SSliceIndexDicomEditor.", dicomReader);
155 ::fwServices::OSR::registerService(m_tempSeriesDB, ::fwIO::s_DATA_KEY,
156 ::fwServices::IService::AccessType::INOUT, dicomReader);
160 dicomReader->setConfiguration(m_readerConfig);
163 dicomReader->configure();
164 dicomReader->start();
166 m_dicomReader = dicomReader;
169 m_axialIndex = ::fwData::Integer::New(0);
170 m_frontalIndex = ::fwData::Integer::New(0);
171 m_sagittalIndex = ::fwData::Integer::New(0);
174 std::chrono::milliseconds duration = std::chrono::milliseconds(m_delay);
175 m_delayTimer2->setFunction( [ = ]()
179 m_delayTimer2->setDuration(duration);
180 m_delayTimer2->setOneShot(
true);
193 if(!m_dicomReader.expired())
195 m_dicomReader.lock()->stop();
196 ::fwServices::OSR::unregisterService(m_dicomReader.lock());
200 QObject::disconnect(m_sliceIndexSlider, SIGNAL(valueChanged(
int)),
this, SLOT(changeSliceIndex(
int)));
215 _sstream <<
"SSliceIndexDicomEditor::info";
220 void SSliceIndexDicomEditor::changeSliceIndex(
int value)
223 std::stringstream ss;
224 ss << m_sliceIndexSlider->value() <<
" / " << (m_numberOfSlices-1);
225 m_sliceIndexLineEdit->setText(std::string(ss.str()).c_str());
228 m_delayTimer2->start();
237 ::fwMedData::DicomSeries::csptr dicomSeries = this->getInput< ::fwMedData::DicomSeries >(
"series");
238 SLM_ASSERT(
"DicomSeries should not be null !", dicomSeries);
241 size_t selectedSliceIndex =
static_cast<size_t>(m_sliceIndexSlider->value()) +
242 dicomSeries->getFirstInstanceNumber();
243 OSLM_TRACE(
"triggered new slice : " << selectedSliceIndex);
245 SLM_ERROR_IF(
"There is no instance available for selected slice index.",
246 !dicomSeries->isInstanceAvailable(selectedSliceIndex));
248 if(dicomSeries->isInstanceAvailable(selectedSliceIndex))
250 m_slotReadImage->asyncRun(selectedSliceIndex);
259 ::fwMedData::DicomSeries::csptr dicomSeries = this->getInput< ::fwMedData::DicomSeries >(
"series");
260 SLM_ASSERT(
"DicomSeries should not be null !", dicomSeries);
262 auto isModalitySupported = [](const ::fwMedData::Series::csptr& series )
264 return series->getModality() ==
"CT" ||
265 series->getModality() ==
"MR" ||
266 series->getModality() ==
"XA";
269 if( !isModalitySupported(dicomSeries) )
276 sDBTempohelper.
clear();
280 ::boost::filesystem::path tmpPath = path /
"tmp";
282 SLM_INFO(
"Create " + tmpPath.string());
283 ::boost::filesystem::create_directories(tmpPath);
285 const auto& binaries = dicomSeries->getDicomContainer();
286 auto iter = binaries.find(selectedSliceIndex);
287 OSLM_ASSERT(
"Index '"<<selectedSliceIndex<<
"' is not found in DicomSeries", iter != binaries.end());
289 const ::fwMemory::BufferObject::sptr bufferObj = iter->second;
290 const ::fwMemory::BufferObject::Lock lockerDest(bufferObj);
291 const char* buffer =
static_cast<char*
>(lockerDest.getBuffer());
292 const size_t size = bufferObj->getSize();
294 const ::boost::filesystem::path dest = tmpPath / std::to_string(selectedSliceIndex);
295 ::boost::filesystem::ofstream fs(dest, std::ios::binary|std::ios::trunc);
296 FW_RAISE_IF(
"Can't open '" << tmpPath <<
"' for write.", !fs.good());
298 fs.write(buffer, static_cast<long>(size));
302 m_dicomReader.lock()->setFolder(tmpPath);
303 if(!m_dicomReader.expired())
305 m_dicomReader.lock()->update();
307 if(m_dicomReader.expired() || m_dicomReader.lock()->isStopped())
318 ::fwMedData::ImageSeries::sptr imageSeries;
320 if(m_tempSeriesDB->getContainer().size() > 0)
322 auto series = *(m_tempSeriesDB->getContainer().begin());
323 if( isModalitySupported(series) )
325 imageSeries = ::fwMedData::ImageSeries::dynamicCast(series);
331 ::fwData::Image::sptr newImage = imageSeries->getImage();
335 m_frontalIndex->setValue(static_cast< int >(newSize[0]/2));
337 m_sagittalIndex->setValue(static_cast< int >(newSize[1]/2));
343 ::boost::system::error_code ec;
344 ::boost::filesystem::remove_all(path, ec);
345 SLM_ERROR_IF(
"remove_all error for path " + path.string() +
": " + ec.message(), ec.value());
356 messageBox.
setIcon(::fwGui::dialog::IMessageDialog::CRITICAL);
357 messageBox.
addButton(::fwGui::dialog::IMessageDialog::OK);
IODICOM_API SSliceIndexDicomEditor() noexcept
Constructor.
#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.
virtual FWGUI_API void setMessage(const std::string &msg) override
Set the message.
Defines the service interface managing the editor service for object.
IODICOM_API void info(std::ostream &_sstream) override
Override.
Defines the generic message box for IHM. Use the Delegate design pattern.
FWGUI_API void destroy()
Stops sub-views and toobar services. Destroys view, sub-views and toolbar containers.
IODICOM_API void triggerNewSlice()
Function called when a new slice must be displayed.
IODICOM_API void readImage(std::size_t selectedSliceIndex)
Read the selected image.
#define OSLM_TRACE(message)
#define SLM_WARN(message)
IODICOM_API void displayErrorMessage(const std::string &message) const
Display error message.
FWSERVICES_API void setOutput(const ::fwServices::IService::KeyType &key, const ::fwData::Object::sptr &object, size_t index=0)
Register an output object at a given key in the OSR, replacing it if it already exists.
virtual FWGUI_API void addButton(IMessageDialog::Buttons button) override
Add a button (OK, YES_NO, YES, NO, CANCEL)
This editor service is used to select a slice index and read the corresponding image on the local com...
virtual FWGUI_API IMessageDialog::Buttons show() override
Show the message box and return the clicked button.
virtual IODICOM_API void configuring() override
Configuring method. This method is used to configure the service.
#define SLM_ERROR_IF(message, cond)
ioDicom contains services used to deal with the DICOM standard.
#define SLM_ASSERT(message, cond)
work like 'assert' from 'cassert', with in addition a message logged by spylog (with FATAL loglevel) ...
virtual IODICOM_API void starting() override
Override.
::fwRuntime::ConfigurationElement::sptr m_configuration
Configuration element used to configure service internal state using a generic XML like structure TOD...
FWGUI_API void create()
Creates view, sub-views and toolbar containers. Manages sub-views and toobar services.
virtual FWGUI_API void setIcon(IMessageDialog::Icons icon) override
Set the icon (CRITICAL, WARNING, INFO or QUESTION)
IODICOM_API void updating() override
Override.
virtual IODICOM_API ~SSliceIndexDicomEditor() noexcept
Destructor.
static FWSERVICES_API ServiceFactory::sptr getDefault()
Return the unique Instance, create it if required at first access.
std::shared_ptr< ::fwThread::Worker > m_associatedWorker
Associated worker.
#define SLM_INFO(message)
::fwData::Array::SizeType SizeType
Image size type.
virtual FWGUI_API void setTitle(const std::string &title) override
Set the title of the message box.
FWGUI_API void initialize()
Initialize managers.
virtual IODICOM_API void stopping() override
Override.