]> Creatis software - cpPlugins.git/commitdiff
Dicom series reader plugin added.
authorLeonardo Florez-Valencia <florez-l@javeriana.edu.co>
Fri, 23 Oct 2015 00:15:27 +0000 (19:15 -0500)
committerLeonardo Florez-Valencia <florez-l@javeriana.edu.co>
Fri, 23 Oct 2015 00:15:27 +0000 (19:15 -0500)
appli/ImageMPR/ImageMPR.cxx
appli/ImageMPR/ImageMPR.h
appli/ImageMPR/ImageMPR.ui
lib/cpPlugins/Interface/BaseMPRWindow.cxx
lib/cpPlugins/Interface/BaseMPRWindow.h
lib/cpPlugins/Plugins/IO/DicomSeriesReader.cxx [new file with mode: 0644]
lib/cpPlugins/Plugins/IO/DicomSeriesReader.h [new file with mode: 0644]
lib/cpPlugins/Plugins/IO/ImageReader.cxx

index ca29aaacf20080d69902a447d4f814567f3dad30..4b1a4c92156b593a97c10d48a91bbe7b7a0b5093 100644 (file)
@@ -20,6 +20,7 @@ ImageMPR( QWidget* parent )
 
   // Connect actions
   ImageMPR_ConnectAction( OpenImage );
+  ImageMPR_ConnectAction( OpenDICOMSeries );
   ImageMPR_ConnectAction( OpenSegmentation );
   ImageMPR_ConnectAction( OpenPolyData );
   ImageMPR_ConnectAction( SaveImage );
@@ -53,6 +54,15 @@ _aOpenImage( )
   this->m_ImageLoaded = this->m_UI->MPR->LoadImage( );
 }
 
+// -------------------------------------------------------------------------
+void ImageMPR::
+_aOpenDICOMSeries( )
+{
+  if( this->m_ImageLoaded != "" )
+    this->m_UI->MPR->ClearAll( );
+  this->m_ImageLoaded = this->m_UI->MPR->LoadDicomSeries( );
+}
+
 // -------------------------------------------------------------------------
 void ImageMPR::
 _aOpenSegmentation( )
index dabf4507cd0ef40964c8f843e1876f09add3ca8e..b1d43fff0c560c1a6c20bd270855da25d2536bb2 100644 (file)
@@ -150,6 +150,7 @@ public:
 
 private slots:
   void _aOpenImage( );
+  void _aOpenDICOMSeries( );
   void _aOpenSegmentation( );
   void _aOpenPolyData( );
   void _aSaveImage( );
index 7a292a252f49f314a45b1aa2698fca71013a9cb5..d37cab641b1a074ae23c5237f91cf9c27e32faa5 100644 (file)
@@ -32,7 +32,7 @@
      <x>0</x>
      <y>0</y>
      <width>718</width>
-     <height>25</height>
+     <height>27</height>
     </rect>
    </property>
    <widget class="QMenu" name="MenuOptionFile">
@@ -40,6 +40,7 @@
      <string>&amp;File</string>
     </property>
     <addaction name="aOpenImage"/>
+    <addaction name="aOpenDICOMSeries"/>
     <addaction name="aOpenSegmentation"/>
     <addaction name="aOpenPolyData"/>
     <addaction name="separator"/>
     <string>Ctrl+Shift+M</string>
    </property>
   </action>
+  <action name="aOpenDICOMSeries">
+   <property name="text">
+    <string>Open DICOM series</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+D</string>
+   </property>
+  </action>
  </widget>
  <layoutdefault spacing="6" margin="11"/>
  <customwidgets>
index 04bc870d6af69882164fa5b3ba1cfb36577bdca3..5f64d36a34c90e58b24ef983964997846398cf26 100644 (file)
@@ -207,6 +207,57 @@ LoadImage( )
   return( ret );
 }
 
+// -------------------------------------------------------------------------
+std::string cpPlugins::Interface::BaseMPRWindow::
+LoadDicomSeries( )
+{
+  std::string msg = "";
+  std::string ret = "";
+  if( this->m_DicomSeriesReader.IsNull( ) )
+    msg = "No valid DICOM series reader. Please load a valid plugin file.";
+
+  if( this->m_DicomSeriesReader->ExecConfigurationDialog( this ) )
+  {
+    this->Block( );
+    msg = this->m_DicomSeriesReader->Update( );
+    if( msg == "" )
+    {
+      TImage::Pointer image =
+        this->m_DicomSeriesReader->GetOutput< TImage >( "Output" );
+      if( this->m_Images.size( ) == 0 )
+        ret = image->GetName( );
+      else
+        ret = "Segmentation";
+      this->m_Images[ ret ] = image;
+      this->m_DicomSeriesReader->DisconnectOutputs( );
+      this->m_DicomSeriesReader->GetParameters( )->
+        ClearStringList( "FileNames" );
+      vtkImageData* vtk_id = image->GetVTK< vtkImageData >( );
+      if( vtk_id != NULL )
+      {
+        this->m_MPRObjects->AddImage( vtk_id );
+        /*
+          MementoState(m_state, this->m_Image);         
+          this->m_state++;
+        */
+      }
+      else
+        msg = "Read dicom series does not have a valid VTK converter.";
+    }
+    else
+      ret = "";
+
+  } // fi
+
+  // Show errors and return
+  this->Unblock( );
+  if( msg != "" )
+    QMessageBox::critical(
+      this, tr( "Error reading dicom series." ), tr( msg.c_str( ) )
+      );
+  return( ret );
+}
+
 // -------------------------------------------------------------------------
 std::string cpPlugins::Interface::BaseMPRWindow::
 LoadMesh( )
@@ -300,6 +351,8 @@ _UpdatePlugins( )
       this->m_MeshReader = o;
     else if( category == "MeshWriter" )
       this->m_MeshWriter = o;
+    else if( category == "DicomSeriesReader" )
+      this->m_DicomSeriesReader = o;
     else
       this->m_Filters[ category ].insert( name );
 
index 6799abe614c66e47b2b9b5c9e95060efa0d3a3bb..3395d21c25c6963cffe40c7d994092e3adc5c926 100644 (file)
@@ -80,6 +80,7 @@ namespace cpPlugins
       bool LoadPlugins( const std::string& fname );
       void LoadPlugins( );
       std::string LoadImage( );
+      std::string LoadDicomSeries( );
       std::string LoadMesh( );
 
       void ExecuteFilter(
@@ -133,6 +134,7 @@ namespace cpPlugins
       TProcessObject::Pointer m_ImageWriter;
       TProcessObject::Pointer m_MeshReader;
       TProcessObject::Pointer m_MeshWriter;
+      TProcessObject::Pointer m_DicomSeriesReader;
       TFilters m_Filters;
 
       TImages m_Images;
diff --git a/lib/cpPlugins/Plugins/IO/DicomSeriesReader.cxx b/lib/cpPlugins/Plugins/IO/DicomSeriesReader.cxx
new file mode 100644 (file)
index 0000000..99f19b0
--- /dev/null
@@ -0,0 +1,179 @@
+#include "DicomSeriesReader.h"
+
+#ifdef cpPlugins_Interface_QT4
+#include <queue>
+#include <map>
+#include <vector>
+
+#include <QDialogButtonBox>
+#include <QDir>
+#include <QFileDialog>
+#include <QGridLayout>
+#include <QLabel>
+#include <QTreeWidget>
+#include <QVBoxLayout>
+
+#endif // cpPlugins_Interface_QT4
+
+#include <itkGDCMSeriesFileNames.h>
+
+// -------------------------------------------------------------------------
+bool cpPlugins::IO::DicomSeriesReader::
+ExecConfigurationDialog( QWidget* parent )
+{
+  bool r = false;
+
+#ifdef cpPlugins_Interface_QT4
+
+  // DICOM series analyzer
+  itk::GDCMSeriesFileNames::GlobalWarningDisplayOff( );
+  itk::GDCMSeriesFileNames::Pointer series =
+    itk::GDCMSeriesFileNames::New( );
+
+  typedef std::map< std::string, TStringList > _TSeries;
+  typedef std::map< std::string, _TSeries > _TFilenames;
+  _TSeries found_series;
+  _TFilenames found_filenames;
+
+  // Show dialog and check if it was accepted
+  QFileDialog dialog( parent );
+  dialog.setFileMode( QFileDialog::DirectoryOnly );
+  dialog.setDirectory( QFileDialog::tr( "." ) );
+  if( dialog.exec( ) )
+  {
+    std::string dir_name = dialog.selectedFiles( ).begin( )->toStdString( );
+    std::queue< std::string > q;
+    q.push( dir_name );
+    while( !( q.empty( ) ) )
+    {
+      dir_name = q.front( );
+      q.pop( );
+
+      // Get DICOM information
+      series->SetUseSeriesDetails( true );
+      series->AddSeriesRestriction( "0008|0021" );
+      series->SetDirectory( dir_name );
+      const TStringList& seriesUID = series->GetSeriesUIDs( );
+      if( seriesUID.size( ) > 0 )
+      {
+        TStringList::const_iterator sIt = seriesUID.begin( );
+        for( ; sIt != seriesUID.end( ); ++sIt )
+        {
+          TStringList filenames = series->GetFileNames( *sIt );
+          if( filenames.size( ) > 0 )
+          {
+            found_series[ dir_name ].push_back( *sIt );
+            found_filenames[ dir_name ][ *sIt ] = filenames;
+
+          } // fi
+
+        } // rof
+
+      } // fi
+
+      // Update queue
+      QDir dir( dir_name.c_str( ) );
+      QFileInfoList contents = dir.entryInfoList( );
+      QFileInfoList::const_iterator i = contents.begin( );
+      for( ; i != contents.end( ); ++i )
+      {
+        if( i->isDir( ) )
+        {
+          std::string new_dir_name = i->absoluteFilePath( ).toStdString( );
+          if( new_dir_name.size( ) > dir_name.size( ) )
+            q.push( new_dir_name );
+
+        } // fi
+
+      } // rof
+
+    } // elihw
+
+  } // fi
+
+  // Show second dialog
+  if( found_series.size( ) > 0 )
+  {
+    QDialog* tree_dialog = new QDialog( parent );
+
+    QLabel* title = new QLabel( tree_dialog );
+    title->setText( "Choose a DICOM series" );
+    QGridLayout* mainLayout = new QGridLayout( tree_dialog );
+    QVBoxLayout* toolsLayout = new QVBoxLayout( );
+    toolsLayout->addWidget( title );
+    mainLayout->addLayout( toolsLayout, 0, 0, 1, 1 );
+
+    QTreeWidget* tree = new QTreeWidget( tree_dialog );
+    QList< QTreeWidgetItem* > tree_items;
+
+    _TSeries::const_iterator fsIt = found_series.begin( );
+    for( ; fsIt != found_series.end( ); ++fsIt )
+    {
+      QTreeWidgetItem* new_item =
+        new QTreeWidgetItem(
+          ( QTreeWidgetItem* )( NULL ), QStringList( fsIt->first.c_str( ) )
+          );
+      TStringList::const_iterator sId = fsIt->second.begin( );
+      for( ; sId != fsIt->second.end( ); ++sId )
+      {
+        QTreeWidgetItem* new_leaf =
+          new QTreeWidgetItem( new_item, QStringList( sId->c_str( ) ) );
+        new_item->addChild( new_leaf );
+
+      } // rof
+      tree_items.append( new_item );
+
+    } // rof
+    tree->insertTopLevelItems( 0, tree_items );
+    toolsLayout->addWidget( tree );
+
+    QDialogButtonBox* bb = new QDialogButtonBox(
+      QDialogButtonBox::Ok | QDialogButtonBox::Cancel
+      );
+    tree_dialog->connect( bb, SIGNAL( accepted( ) ), tree_dialog, SLOT( accept( ) ) );
+    tree_dialog->connect( bb, SIGNAL( rejected( ) ), tree_dialog, SLOT( reject( ) ) );
+    toolsLayout->addWidget( bb );
+
+    if( tree_dialog->exec( ) == 1 )
+    {
+      QTreeWidgetItem* item = tree->currentItem( );
+      QTreeWidgetItem* parent = item->parent( );
+      if( parent != NULL )
+      {
+        std::string serie_dir = parent->text( 0 ).toStdString( );
+        std::string serie_id = item->text( 0 ).toStdString( );
+
+        this->m_Parameters->ClearStringList( "FileNames" );
+        const TStringList& filenames = found_filenames[ serie_dir ][ serie_id ];
+        for( unsigned int f = 0; f < filenames.size( ); ++f )
+          this->m_Parameters->AddToStringList( "FileNames", filenames[ f ] );
+
+        r = true;
+
+      } // fi
+
+    } // fi
+
+  } // fi
+
+  itk::GDCMSeriesFileNames::GlobalWarningDisplayOn( );
+
+#endif // cpPlugins_Interface_QT4
+
+  return( r );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::IO::DicomSeriesReader::
+DicomSeriesReader( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::IO::DicomSeriesReader::
+~DicomSeriesReader( )
+{
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/Plugins/IO/DicomSeriesReader.h b/lib/cpPlugins/Plugins/IO/DicomSeriesReader.h
new file mode 100644 (file)
index 0000000..3bad459
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef __CPPLUGINS__PLUGINS__DICOMSERIESREADER__H__
+#define __CPPLUGINS__PLUGINS__DICOMSERIESREADER__H__
+
+#include <vector>
+
+#include <cpPlugins/IO/cpPluginsIO_Export.h>
+#include <cpPlugins/Plugins/IO/ImageReader.h>
+
+namespace itk
+{
+  class ImageIOBase;
+}
+
+namespace cpPlugins
+{
+  namespace IO
+  {
+    /**
+     */
+    class cpPluginsIO_EXPORT DicomSeriesReader
+      : public ImageReader
+    {
+    public:
+      typedef DicomSeriesReader               Self;
+      typedef ImageReader                     Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef Superclass::TParameters TParameters;
+      typedef Superclass::TStringList TStringList;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( DicomSeriesReader, ImageReader );
+      cpPlugins_Id_Macro(
+        cpPlugins::IO::DicomSeriesReader, "DicomSeriesReader"
+        );
+
+    public:
+      virtual bool ExecConfigurationDialog( QWidget* parent );
+
+    protected:
+      DicomSeriesReader( );
+      virtual ~DicomSeriesReader( );
+
+    private:
+      // Purposely not implemented
+      DicomSeriesReader( const Self& );
+      Self& operator=( const Self& );
+    };
+
+    // ---------------------------------------------------------------------
+    CPPLUGINS_INHERIT_PROVIDER( DicomSeriesReader );
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __CPPLUGINS__PLUGINS__DICOMSERIESREADER__H__
+
+// eof - $RCSfile$
index f544617e4685aa3245c144ee78a78f883c6493fe..d28b129dec2ebfa4bbac4598d9dec6fd39f25453 100644 (file)
@@ -1,8 +1,6 @@
 #include "ImageReader.h"
 #include <cpPlugins/Interface/Image.h>
 
-#include <set>
-
 #include <itkImageFileReader.h>
 #include <itkImageSeriesReader.h>
 
@@ -388,20 +386,15 @@ _RealGD( const TStringList& names )
   else if( names.size( ) > 1 )
   {
     // Read image series
-    std::set< std::string > ordered_names;
-    for( unsigned int i = 0; i < names.size( ); ++i )
-      ordered_names.insert( names[ i ] );
-
     typedef itk::ImageSeriesReader< I > _MR;
     _MR* reader = this->_CreateITK< _MR >( );
-    std::set< std::string >::const_iterator fnIt = ordered_names.begin( );
-    for( ; fnIt != ordered_names.end( ); ++fnIt )
-      reader->AddFileName( *fnIt );
+    for( unsigned int i = 0; i < names.size( ); ++i )
+      reader->AddFileName( names[ i ] );
     try
     {
       reader->Update( );
       out->SetITK< I >( reader->GetOutput( ) );
-      out->SetName( *( ordered_names.begin( ) ) );
+      out->SetName( names[ 0 ] );
     }
     catch( itk::ExceptionObject& err )
     {