Medical Imaging Interaction Toolkit  2018.4.99-3e3f1a6e
Medical Imaging Interaction Toolkit
mitkDICOMFileReaderSelector.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
16 
17 #include <usModuleContext.h>
18 #include <usGetModuleContext.h>
19 #include <usModuleResource.h>
20 #include <usModuleResourceStream.h>
21 #include <usModule.h>
22 
25 {
26 }
27 
30 {
31 }
32 
33 std::list<mitk::DICOMFileReader::Pointer>
36 {
37  return m_Readers;
38 }
39 
40 void
42 ::AddConfigsFromResources(const std::string& path)
43 {
44  const std::vector<us::ModuleResource> configs =
45  us::GetModuleContext()->GetModule()->FindResources( path, "*.xml", false );
46 
47  for ( auto iter = configs.cbegin(); iter != configs.cend(); ++iter )
48  {
49  us::ModuleResource resource = *iter;
50  if (resource.IsValid())
51  {
52  us::ModuleResourceStream stream(resource);
53 
54  // read all into string s
55  std::string s;
56 
57  stream.seekg(0, std::ios::end);
58  s.reserve(stream.tellg());
59  stream.seekg(0, std::ios::beg);
60 
61  s.assign((std::istreambuf_iterator<char>(stream)),
62  std::istreambuf_iterator<char>());
63 
64  this->AddConfig(s);
65  }
66  }
67 }
68 
69 void
72 {
73  if (resource.IsValid())
74  {
75  us::ModuleResourceStream stream(resource);
76 
77  // read all into string s
78  std::string s;
79 
80  stream.seekg(0, std::ios::end);
81  s.reserve(stream.tellg());
82  stream.seekg(0, std::ios::beg);
83 
84  s.assign((std::istreambuf_iterator<char>(stream)),
85  std::istreambuf_iterator<char>());
86 
87  this->AddConfig(s);
88  }
89 }
90 
91 void
93 ::AddConfigFromResource(const std::string& resourcename)
94 {
95  us::ModuleResource r = us::GetModuleContext()->GetModule()->GetResource(resourcename);
96  this->AddConfigFromResource(r);
97 }
98 
99 void
101 ::AddFileReaderCanditate(DICOMFileReader::Pointer reader)
102 {
103  if (reader.IsNotNull())
104  {
105  m_Readers.push_back( reader );
106  }
107 }
108 
109 void
112 {
113  //this->AddConfigsFromResources("configurations/3D");
114  // in this order of preference...
115  this->AddConfigFromResource("configurations/3D/instancenumber.xml");
116  this->AddConfigFromResource("configurations/3D/instancenumber_soft.xml");
117  this->AddConfigFromResource("configurations/3D/slicelocation.xml");
118  this->AddConfigFromResource("configurations/3D/imageposition.xml");
119  this->AddConfigFromResource("configurations/3D/imageposition_byacquisition.xml");
120  //this->AddConfigFromResource("configurations/3D/classicreader.xml"); // not the best choice in ANY of the images I came across
121 }
122 
123 void
126 {
127  this->AddConfigsFromResources("configurations/3DnT");
128 }
129 
130 void
132 ::AddConfig(const std::string& xmlDescription)
133 {
134  DICOMReaderConfigurator::Pointer configurator = DICOMReaderConfigurator::New();
135  DICOMFileReader::Pointer reader = configurator->CreateFromUTF8ConfigString(xmlDescription);
136 
137  if (reader.IsNotNull())
138  {
139  m_Readers.push_back( reader );
140  m_PossibleConfigurations.push_back(xmlDescription);
141  }
142  else
143  {
144  std::stringstream ss;
145  ss << "Could not parse reader configuration. Ignoring it.";
146  throw std::invalid_argument( ss.str() );
147  }
148 }
149 
150 void
152 ::AddConfigFile(const std::string& filename)
153 {
154  std::ifstream file(filename.c_str());
155  std::string s;
156 
157  file.seekg(0, std::ios::end);
158  s.reserve(file.tellg());
159  file.seekg(0, std::ios::beg);
160 
161  s.assign((std::istreambuf_iterator<char>(file)),
162  std::istreambuf_iterator<char>());
163 
164  this->AddConfig(s);
165 }
166 
167 void
170 {
171  m_InputFilenames = filenames;
172 }
173 
174 const mitk::StringList&
177 {
178  return m_InputFilenames;
179 }
180 
181 mitk::DICOMFileReader::Pointer
184 {
185  ReaderList workingCandidates;
186 
187  // do the tag scanning externally and just ONCE
188  DICOMGDCMTagScanner::Pointer gdcmScanner = DICOMGDCMTagScanner::New();
189  gdcmScanner->SetInputFiles( m_InputFilenames );
190 
191  // let all readers analyze the file set
192  for ( auto rIter = m_Readers.cbegin(); rIter != m_Readers.cend(); ++rIter )
193  {
194  gdcmScanner->AddTagPaths((*rIter)->GetTagsOfInterest());
195  }
196 
197  gdcmScanner->Scan();
198 
199  // let all readers analyze the file set
200  unsigned int readerIndex(0);
201  for ( auto rIter = m_Readers.cbegin(); rIter != m_Readers.cend(); ++readerIndex, ++rIter )
202  {
203  (*rIter)->SetInputFiles( m_InputFilenames );
204  (*rIter)->SetTagCache( gdcmScanner->GetScanCache() );
205  try
206  {
207  (*rIter)->AnalyzeInputFiles();
208  workingCandidates.push_back( *rIter );
209  MITK_INFO << "Reader " << readerIndex << " (" << (*rIter)->GetConfigurationLabel() << ") suggests " << (*rIter)->GetNumberOfOutputs() << " 3D blocks";
210  if ((*rIter)->GetNumberOfOutputs() == 1)
211  {
212  MITK_DEBUG << "Early out with reader #" << readerIndex << " (" << (*rIter)->GetConfigurationLabel() << "), less than 1 block is not possible";
213  return *rIter;
214  }
215  }
216  catch ( const std::exception& e )
217  {
218  MITK_ERROR << "Reader " << readerIndex << " (" << (*rIter)->GetConfigurationLabel() << ") threw exception during file analysis, ignoring this reader. Exception: " << e.what();
219  }
220  catch (...)
221  {
222  MITK_ERROR << "Reader " << readerIndex << " (" << (*rIter)->GetConfigurationLabel() << ") threw unknown exception during file analysis, ignoring this reader.";
223  }
224  }
225 
226  DICOMFileReader::Pointer bestReader;
227 
228  unsigned int minimumNumberOfOutputs = std::numeric_limits<unsigned int>::max();
229  readerIndex = 0;
230  unsigned int bestReaderIndex(0);
231  // select the reader with the minimum number of mitk::Images as output
232  for ( auto rIter = workingCandidates.cbegin(); rIter != workingCandidates.cend(); ++readerIndex, ++rIter )
233  {
234  const unsigned int thisReadersNumberOfOutputs = (*rIter)->GetNumberOfOutputs();
235  if ( thisReadersNumberOfOutputs > 0 // we don't count readers that don't actually produce output
236  && thisReadersNumberOfOutputs < minimumNumberOfOutputs )
237  {
238  minimumNumberOfOutputs = (*rIter)->GetNumberOfOutputs();
239  bestReader = *rIter;
240  bestReaderIndex = readerIndex;
241  }
242  }
243 
244  MITK_DEBUG << "Decided for reader #" << bestReaderIndex << " (" << bestReader->GetConfigurationLabel() << ")";
245  MITK_DEBUG << m_PossibleConfigurations[bestReaderIndex];
246 
247  return bestReader;
248 }
ReaderList GetAllConfiguredReaders() const
Return all the DICOMFileReaders that are currently used for selection by this class. The readers returned by this method depend on what config files have been added earlier (or which of the built-in readers have been loaded)
#define MITK_INFO
Definition: mitkLogMacros.h:18
void AddConfigFile(const std::string &filename)
Add a configuration as expected by DICOMReaderConfigurator. Configs can only be reset by instantiatin...
#define MITK_ERROR
Definition: mitkLogMacros.h:20
#define MITK_DEBUG
Definition: mitkLogMacros.h:22
const StringList & GetInputFiles() const
Input files.
std::list< DICOMFileReader::Pointer > ReaderList
void AddConfig(const std::string &xmlDescription)
Add a configuration as expected by DICOMReaderConfigurator. Configs can only be reset by instantiatin...
void SetInputFiles(StringList filenames)
Input files.
void AddConfigFromResource(const std::string &resourcename)
Module * GetModule() const
static T max(T x, T y)
Definition: svm.cpp:56
void AddConfigsFromResources(const std::string &path)
std::vector< std::string > StringList
void LoadBuiltIn3DnTConfigs()
Load 3D+t image creating configurations from the MITK module system (see us::Module::FindResources())...
DICOMFileReader::Pointer GetFirstReaderWithMinimumNumberOfOutputImages()
Execute the analysis and selection process. The first reader with a minimal number of outputs will be...
static ModuleContext * GetModuleContext()
Returns the module context of the calling module.
void LoadBuiltIn3DConfigs()
Load 3D image creating configurations from the MITK module system (see us::Module::FindResources()). For a default set of configurations, look into the directory Resources of the DICOMReader module.
void AddFileReaderCanditate(DICOMFileReader::Pointer reader)
Add a whole pre-configured reader to the selection process.