18 #ifndef MILXQTDICOMPLUGIN_H 19 #define MILXQTDICOMPLUGIN_H 23 #include <QDockWidget> 25 #include <itkImageSeriesReader.h> 26 #include <itkGDCMImageIO.h> 27 #include <itkGDCMSeriesFileNames.h> 28 #include <itkPolygonSpatialObject.h> 29 #include <itkGroupSpatialObject.h> 30 #include <itkSpatialObjectToImageFilter.h> 31 #if (ITK_VERSION_MAJOR > 3) //Review only members 32 #include <gdcmTypes.h> 33 #include <gdcmAttribute.h> 34 #include <gdcmReader.h> 35 #endif // (ITK_VERSION_MAJOR > 3) 37 #include <vtkPolyDataCollection.h> 42 #include "milxQtPluginInterface.h" 43 #include "milxQtImage.h" 44 #include "milxQtMain.h" 45 #include "milxQtManager.h" 59 typedef itk::GDCMImageIO ImageIOType;
60 typedef itk::MetaDataDictionary DictionaryType;
61 typedef itk::MetaDataObject< std::string > MetaDataStringType;
74 virtual QString
name();
119 virtual void SetInputCollection(vtkPolyDataCollection* collection, QStringList &filenames);
125 virtual void open(QString filename);
130 virtual void save(QString filename);
158 {
return Qt::LeftDockWidgetArea; }
166 #if (ITK_VERSION_MAJOR > 3) //Review only members 175 template<
class TImage>
176 static bool ExportDICOM_RT(
const std::string directoryPath,
const std::string rsFileName,
const std::string outPath,
typename itk::SmartPointer<TImage> &data, std::string &seriesName,
const bool reorient =
true);
177 #endif // (ITK_VERSION_MAJOR > 3) 218 void openStructureSet();
230 void showRSFileDialog();
231 void showInputFileDialog();
232 void showRTInputFileDialog();
233 void showOutputFileDialog();
234 void showRTOutputFileDialog();
235 void showInputFileDialogAnonymize();
236 void showOutputFileDialogAnonymize();
255 bool anonymizeDicomImage(
const std::string &input,
const QString &subject_output_folder,
const QString &rel_dir,
unsigned int index_subject,
unsigned int index_dicom,
bool &isFirst);
266 void makeFilename(
const QString &path, ImageIOType::Pointer gdcmImageIO,
unsigned int index, std::string &filename,
unsigned int index_subject);
274 void removeForbiddenChar(std::string &str,
char* charsToRemove);
276 void writeLog(QString &filename, std::string &output);
285 void getTagValue(ImageIOType::Pointer gdcmImageIO,
const std::string &tag, std::string & tag_value);
288 QPointer<milxQtMain> MainWindow;
301 QWizard wizardAnonymize;
302 QString inputDirectoryname;
303 QLineEdit *txtInputName;
304 QString outputDirectoryname;
305 QLineEdit *txtOutputName;
306 QString inputRTDirectoryname;
307 QLineEdit *txtRTInputName;
308 QString outputRTDirectoryname;
309 QLineEdit *txtRTOutputName;
311 QLineEdit *txtRSName;
312 QString inputAnonymizeDirectoryname;
313 QLineEdit *txtInputAnonymizeName;
314 QString outputAnonymizeDirectoryname;
315 QLineEdit *txtOutputAnonymizeName;
317 QString outputPrefix;
318 QLineEdit *txtOutputPrefix;
321 QLineEdit *txtOutputInitID;
323 QCheckBox *checkboxPreserveFolderArc;
324 QCheckBox *checkboxPatientName;
325 QCheckBox *checkboxPatientID;
326 QCheckBox *checkboxSeriesDate;
327 QCheckBox *checkboxSeriesTime;
328 QCheckBox *checkboxStudyID;
329 QCheckBox *checkboxStudyDesc;
330 QCheckBox *checkboxSeriesNumber;
331 QCheckBox *checkboxSequenceName;
332 QCheckBox *checkboxProtocolName;
333 QCheckBox *checkboxSeriesDescription;
335 QCheckBox *anonPatientInfo;
336 QCheckBox *anonPhysician;
337 QCheckBox *anonOperator;
338 QCheckBox *anonScanDate;
346 void createActions();
349 void createRTWizard();
350 void createConnections();
351 void createWizardAnonymise();
354 static inline void trim (std::string &str)
357 for (
unsigned int i = 0; i < str.length(); i++)
358 if (str[i] !=
' ') temp += str[i];
362 template<
class TImage>
363 static void resetImage(
typename itk::SmartPointer<TImage> imageSlice);
365 template<
class TImage,
class TSliceType>
366 static void mergeImages(
typename itk::SmartPointer<TSliceType> tempSlice,
typename itk::SmartPointer<TImage> finalImage,
int iRequiredSlice);
382 #if (ITK_VERSION_MAJOR > 3) //Review only members 383 template<
class TImage>
384 bool milxQtDICOMPlugin::ExportDICOM_RT(
const std::string directoryPath,
const std::string rsFileName,
const std::string outPath,
typename itk::SmartPointer<TImage> &data, std::string &seriesName,
const bool reorient)
386 typedef itk::ImageSeriesReader<TImage> ReaderType;
387 typedef itk::GDCMImageIO ImageIOType;
391 ImageIOType::Pointer gdcmIO = ImageIOType::New();
392 typename ReaderType::Pointer reader = ReaderType::New();
393 reader->SetImageIO( gdcmIO );
394 reader->SetFileNames( filenames );
395 reader->AddObserver(itk::ProgressEvent(), milx::ProgressUpdates);
400 catch (itk::ExceptionObject &excp)
402 std::cerr <<
"File Exception caught while reading series!" << std::endl;
403 std::cerr << excp << std::endl;
408 typedef itk::MetaDataObject< std::string > MetaDataStringType;
409 std::string series_type_id(
"0008|103e");
410 itk::MetaDataDictionary & dic = gdcmIO->GetMetaDataDictionary();
411 itk::MetaDataDictionary::ConstIterator series_type_itr = dic.Find(series_type_id);
413 std::string caseId =
"0010|0020";
414 itk::MetaDataDictionary::ConstIterator case_itr = dic.Find( caseId );
416 std::string echoNumber =
"0018|0086";
417 itk::MetaDataDictionary::ConstIterator echoNumber_itr = dic.Find( echoNumber );
419 MetaDataStringType::ConstPointer entryValue=
dynamic_cast<const MetaDataStringType *
>(series_type_itr->second.GetPointer());
422 seriesName = entryValue->GetMetaDataObjectValue();
423 std::cout <<
"Series: " << entryValue->GetMetaDataObjectValue() << std::endl;
425 MetaDataStringType::ConstPointer entryValue2=
dynamic_cast<const MetaDataStringType *
>(case_itr->second.GetPointer());
427 std::cout <<
"Case: " << entryValue2->GetMetaDataObjectValue() << std::endl;
428 MetaDataStringType::ConstPointer entryValue3;
429 if(dic.HasKey(echoNumber))
431 entryValue3 =
dynamic_cast<const MetaDataStringType *
>(echoNumber_itr->second.GetPointer());
432 std::cout <<
"Echo Number: " << entryValue3->GetMetaDataObjectValue() << std::endl;
435 data = reader->GetOutput();
436 qApp->processEvents();
439 typedef itk::Image< typename TImage::PixelType, 2 > ImageSliceType;
440 typename ImageSliceType::Pointer temp2Dimage = ImageSliceType::New();
442 gdcm::Reader RTreader;
443 RTreader.SetFileName( rsFileName.c_str() );
444 if( !RTreader.Read() )
446 std::cout <<
"Problem reading file: " << rsFileName << std::endl;
450 resetImage<TImage>(data);
453 typename TImage::RegionType inputRegion = data->GetLargestPossibleRegion();
454 typedef itk::ExtractImageFilter< TImage, ImageSliceType> FilterType;
455 typename FilterType::Pointer filter = FilterType::New();
456 typename TImage::SizeType size = inputRegion.GetSize();
458 typename TImage::IndexType start = inputRegion.GetIndex();
460 typename TImage::RegionType desiredRegion;
461 desiredRegion.SetSize( size );
462 desiredRegion.SetIndex( start );
463 filter->SetDirectionCollapseToIdentity();
464 filter->SetExtractionRegion( desiredRegion );
465 filter->SetInput( data );
466 filter->AddObserver(itk::ProgressEvent(), milx::ProgressUpdates);
468 temp2Dimage = filter->GetOutput();
471 const gdcm::DataSet& ds = RTreader.GetFile().GetDataSet();
472 std::cout <<
"Parsing: " << rsFileName << std::endl;
474 gdcm::MediaStorage ms;
475 ms.SetFromFile( RTreader.GetFile() );
476 std::cout <<
"media storage: " << ms << std::endl;
479 gdcm::Tag tssroisq(0x3006,0x0020);
480 if( !ds.FindDataElement( tssroisq ) )
482 std::cout <<
"Problem locating 0x3006,0x0020 - Is this a valid RT Struct file?" << std::endl;
485 gdcm::Tag troicsq(0x3006,0x0039);
486 if( !ds.FindDataElement( troicsq ) )
488 std::cout <<
"Problem locating 0x3006,0x0039 - Is this a valid RT Struct file?" << std::endl;
492 const gdcm::DataElement &roicsq = ds.GetDataElement( troicsq );
494 gdcm::SmartPointer<gdcm::SequenceOfItems> sqi = roicsq.GetValueAsSQ();
495 if( !sqi || !sqi->GetNumberOfItems() )
499 const gdcm::DataElement &ssroisq = ds.GetDataElement( tssroisq );
500 gdcm::SmartPointer<gdcm::SequenceOfItems> ssqi = ssroisq.GetValueAsSQ();
501 if( !ssqi || !ssqi->GetNumberOfItems() )
506 std::cout <<
"Number of structures found:" << sqi->GetNumberOfItems() << std::endl;
509 for(
unsigned int pd = 0; pd < sqi->GetNumberOfItems(); ++pd)
511 const gdcm::Item & item = sqi->GetItem(pd+1);
512 gdcm::Attribute<0x3006,0x0084> roinumber;
513 const gdcm::DataSet& nestedds = item.GetNestedDataSet();
514 roinumber.SetFromDataElement( nestedds.GetDataElement( roinumber.GetTag() ) );
516 qApp->processEvents();
519 unsigned int spd = 0;
520 gdcm::Item & sitem = ssqi->GetItem(spd+1);
521 gdcm::DataSet& snestedds = sitem.GetNestedDataSet();
523 gdcm::Attribute<0x3006,0x0022> sroinumber;
527 sitem = ssqi->GetItem(spd+1);
528 snestedds = sitem.GetNestedDataSet();
530 sroinumber.SetFromDataElement( snestedds.GetDataElement( sroinumber.GetTag() ) );
534 }
while ( sroinumber.GetValue() != roinumber.GetValue() );
536 gdcm::Tag stcsq(0x3006,0x0026);
537 if( !snestedds.FindDataElement( stcsq ) )
539 std::cout<<
"Did not find sttsq data el " << stcsq <<
" continuing..." << std::endl;
542 const gdcm::DataElement &sde = snestedds.GetDataElement( stcsq );
545 gdcm::Tag troidc(0x3006,0x002a);
546 gdcm::Attribute<0x3006,0x002a> color = {};
547 if( nestedds.FindDataElement( troidc) )
549 const gdcm::DataElement &decolor = nestedds.GetDataElement( troidc );
550 color.SetFromDataElement( decolor );
553 gdcm::Tag tcsq(0x3006,0x0040);
554 if( !nestedds.FindDataElement( tcsq ) )
558 const gdcm::DataElement& csq = nestedds.GetDataElement( tcsq );
560 gdcm::SmartPointer<gdcm::SequenceOfItems> sqi2 = csq.GetValueAsSQ();
561 if( !sqi2 || !sqi2->GetNumberOfItems() )
563 std::cout <<
"csq: " << csq << std::endl;
564 std::cout <<
"sqi2: " << *sqi2 << std::endl;
565 std::cout<<
"Did not find sqi2 or no. items == 0 " << sqi2->GetNumberOfItems() <<
" continuing..." << std::endl;
568 unsigned int nitems = sqi2->GetNumberOfItems();
569 std::cout <<
"Structure " << pd <<
". Number of regions: " << nitems << std::endl;
570 std::string str_currentOrgan(sde.GetByteValue()->GetPointer(), sde.GetByteValue()->GetLength());
573 trim (str_currentOrgan);
574 std::cout << pd <<
". Structure name: " << str_currentOrgan << std::endl;
577 typename TImage::PointType point;
578 typename TImage::IndexType pixelIndex;
579 typedef itk::PolygonSpatialObject<2> PolygonType;
580 typedef itk::SpatialObjectPoint<2> PolygonPointType;
581 PolygonType::PointListType pointList ;
583 PolygonType::Pointer polygon = PolygonType::New();;
584 typedef itk::GroupSpatialObject<2> GroupType;
585 typedef itk::SpatialObjectToImageFilter<GroupType, ImageSliceType> SpatialObjectToImageFilterType;
586 GroupType::Pointer group = GroupType::New();
587 typename SpatialObjectToImageFilterType::Pointer imageFilter =SpatialObjectToImageFilterType::New();
588 int iPointsOutsideBoundary = 0;
589 int iCurrentSlice = 0;
590 for(
unsigned int i = 0; i < nitems; ++i)
592 const gdcm::Item & item2 = sqi2->GetItem(i+1);
594 const gdcm::DataSet& nestedds2 = item2.GetNestedDataSet();
596 gdcm::Tag tcontourdata(0x3006,0x0050);
597 const gdcm::DataElement & contourdata = nestedds2.GetDataElement( tcontourdata );
599 qApp->processEvents();
602 gdcm::Attribute<0x3006,0x0050> at;
603 at.SetFromDataElement( contourdata );
604 const double* pts = at.GetValues();
605 unsigned int npts = at.GetNumberOfValues() / 3;
607 for(
unsigned int j = 0; j < npts * 3; j+=3)
614 if (!(data->TransformPhysicalPointToIndex( point, pixelIndex )))
617 iPointsOutsideBoundary++;
620 p.SetPosition(pixelIndex[0] ,pixelIndex[1],pixelIndex[2]);
625 pointList.push_back(p);
629 iCurrentSlice = pixelIndex[2];
632 std::cout <<
"Inserting region with " << pointList.size() <<
" points into slice: " << iCurrentSlice << std::endl;
634 resetImage<ImageSliceType>(temp2Dimage);
637 group->AddSpatialObject(polygon);
641 polygon->SetPoints(pointList);
642 imageFilter->SetInput(group);
643 imageFilter->SetSize(temp2Dimage->GetLargestPossibleRegion().GetSize());
644 imageFilter->AddObserver(itk::ProgressEvent(), milx::ProgressUpdates);
645 imageFilter->Update();
646 temp2Dimage=imageFilter->GetOutput();
648 catch( itk::ExceptionObject & err )
650 std::cerr <<
"Problem setting polygon->SetPoints for this region (non-planar)" << std::endl;
651 std::cerr << err << std::endl;
655 mergeImages<TImage>(temp2Dimage, data, iCurrentSlice);
658 group->RemoveSpatialObject(polygon);
662 if (iPointsOutsideBoundary > 0)
664 std::cout <<
" --" << iPointsOutsideBoundary <<
" contour points detected outside image boundary. Please check the output volume. " ;
665 iPointsOutsideBoundary=0;
669 std::string strNewVolume = outPath +
"/";
670 strNewVolume += str_currentOrgan;
671 strNewVolume +=
".nii.gz";
674 milx::File::WriteImageUsingITK<TImage>(strNewVolume, data);
676 resetImage<TImage>(data);
682 #endif // (ITK_VERSION_MAJOR > 3) 684 template<
class TImage>
685 void milxQtDICOMPlugin::resetImage(
typename itk::SmartPointer<TImage> imageSlice)
687 itk::ImageRegionIterator<TImage> imageIt(imageSlice, imageSlice->GetLargestPossibleRegion()) ;
689 while(!imageIt.IsAtEnd())
696 template<
class TImage,
class TSliceType>
697 void milxQtDICOMPlugin::mergeImages(
typename itk::SmartPointer<TSliceType> tempSlice,
typename itk::SmartPointer<TImage> finalImage,
int iRequiredSlice )
699 typename TImage::PixelType pixelValue =0;
700 typename TImage::IndexType pixelIndex;
701 typename TSliceType::IndexType sliceIndex;
702 int iX = finalImage->GetLargestPossibleRegion().GetSize()[0];
703 int iY = finalImage->GetLargestPossibleRegion().GetSize()[1];
706 if (iRequiredSlice>0)
708 for (
int i=0;i<iX;i++)
709 for (
int j=0;j<iY;j++)
716 pixelValue = tempSlice->GetPixel(sliceIndex);
717 pixelIndex[2] = iRequiredSlice;
721 finalImage->SetPixel(pixelIndex, finalImage->GetPixel(pixelIndex) ^ (pixelValue != 0));
722 qApp->processEvents();
727 #endif // MILXQTDICOMPLUGIN_H
virtual void postStartTasks()
Tasks to complete after running or starting the thread. [Implement this].
QPointer< milxQtManager > manager
Manager widget.
virtual bool hasCollectionSupport()
Does the plugin support collections (PolyData collection etc.). [Implement this in your plugin]...
QAction * actionOpenSeries
open series action
QPointer< QDockWidget > dock
Dock widget.
virtual QDockWidget * dockWidget()=0
Return the dock widget (if one is provided by plugin). [Implement this in your plugin].
virtual QString saveFileSupport()=0
Get the file support string for saving (extension wildcard list). [Implement this in your plugin]...
virtual milxQtImage * imageResult()=0
Get the image result. The result can then be displayed in milxQtMain etc.[Implement this in your plug...
virtual void preStartTasks()
Tasks to complete before running or starting the thread. [Implement this].
The interface for the DICOM plugin for milxQt.
This file defines all the defines, aliases and frequently used functions and variables.
This class represents the MILX Qt Render Window Display object using QVTK.
virtual QStringList saveExtensions()=0
Get a list of supported file format extensions. [Implement this in your plugin].
static std::vector< std::string > GetDICOMSeriesFilenames(const std::string directoryPath, const std::string seriesName, bool recursive=false)
Returns the filenames for a given UID/Series name for a given directory.
This class represents the MILX Qt Image Display object using VTK.
virtual QStringList openExtensions()=0
Get a list of supported file format extensions. [Implement this in your plugin].
virtual void update()
Update the plugin. [Implement this in your plugin].
virtual void loadExtension()=0
Load the extension. [Implement this in your plugin].
QAction * actionTags
open series action
virtual QString name()=0
Get the Name of the plugin. [Implement this in your plugin].
This class represents the MILX Qt Model/Mesh Display object using VTK.
virtual Qt::DockWidgetArea dockDefaultArea()
Return the default dock widget area (if one is provided by plugin). [Implement this in your plugin]...
virtual void SetInputCollection(vtkPolyDataCollection *collection, QStringList &filenames)=0
Pass a collection to internal plugin class. [Implement this in your plugin].
virtual bool hasOpenSupport()
Does the plugin support opening files? [Implement this in your plugin].
The interface for any plugins that can be made for milxQtMain.
QAction * actionAnonymize
Anonymize action.
virtual bool isPluginWindow(QWidget *window)=0
Is the window provided a plugin generated window? In this case a milxQtShapeModel window...
virtual milxQtModel * modelResult()=0
Get the model result. The result can then be displayed in milxQtMain etc. [Implement this in your plu...
QMenu * menuDICOM
DICOM menu.
virtual milxQtRenderWindow * genericResult()=0
Get the generic result, which is a milxQtRenderWindow. The result can then be displayed in milxQtMain...
virtual QString openFileSupport()=0
Get the file support string for opening (extension wildcard list). [Implement this in your plugin]...
virtual void open(QString filename)=0
Open the file using the plugin. [Implement this in your plugin].
#define MILXQT_PLUGIN_EXPORT
Define Windows Plugin DLL importing.
QAction * actionConvertStructure
convert RT action
QAction * actionConvert
convert action
virtual void save(QString filename)=0
Save the result as a file using the plugin. [Implement this in your plugin].
virtual bool hasSaveSupport()
Does the plugin support opening files? [Implement this in your plugin].