Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
mitkFileSeriesReader.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 
13 #include "mitkFileSeriesReader.h"
14 #include <itkImageFileReader.h>
15 #include <itksys/Directory.hxx>
16 #include <itksys/SystemTools.hxx>
17 #include <map>
18 
20 {
21  typedef std::vector<std::string> StringContainer;
22  typedef std::map<unsigned int, std::string> SortedStringContainer;
23 
24  if (m_FileName == "")
25  {
26  throw itk::ImageFileReaderException(__FILE__, __LINE__, "FileName must be non-empty");
27  }
28  // MITK_INFO << "FileName: "<< m_FileName <<", FilePrefix: "<< m_FilePrefix << ", FilePattern: "<< m_FilePattern <<
29  // std::endl;
30 
31  // determine begin and end idexes of the last digit sequence in the
32  // filename from the sample file name
33  // Therefore, walk backwards from the end of the filename until
34  // a number is found. The string in front of the number is the prefix,
35  // the string after the number is the extension.
36  std::string basename, path;
37  path = itksys::SystemTools::GetFilenamePath(m_FileName);
38  basename = itksys::SystemTools::GetFilenameName(m_FileName);
39 
40  unsigned int digitBegin = 0;
41  unsigned int digitEnd = 0;
42  bool digitFound = false;
43  for (unsigned int i = basename.length() - 1;; --i)
44  {
45  char character = basename[i];
46  if (character >= '0' && character <= '9')
47  {
48  if (!digitFound)
49  {
50  digitEnd = i;
51  digitBegin = i;
52  digitFound = true;
53  }
54  else
55  digitBegin = i;
56  }
57  else
58  {
59  // end of digit series found, jump out of loop!
60  if (digitFound)
61  break;
62  }
63  if (i == 0)
64  break;
65  }
66 
67  //
68  // if there is no digit in the filename, then we have a problem
69  // no matching filenames can be identified!
70  //
71  if (!digitFound)
72  {
73  itkWarningMacro("Filename contains no digit!");
74  return false;
75  }
76 
77  //
78  // determine prefix and extension start and length
79  //
80  unsigned int prefixBegin = 0;
81  unsigned int prefixLength = digitBegin;
82  unsigned int extensionBegin = digitEnd + 1;
83  unsigned int extensionLength = (digitEnd == basename.length() - 1 ? 0 : basename.length() - 1 - digitEnd);
84  unsigned int numberLength = digitEnd - digitBegin + 1;
85 
86  //
87  // extract prefix and extension
88  //
89  std::string prefix = "";
90  if (prefixLength != 0)
91  prefix = basename.substr(prefixBegin, prefixLength);
92  std::string extension = "";
93  if (extensionLength != 0)
94  extension = basename.substr(extensionBegin, extensionLength);
95 
96  //
97  // print debug information
98  //
99  /*
100  MITK_INFO << "digitBegin : " << digitBegin << std::endl;
101  MITK_INFO << "digitEnd : " << digitEnd << std::endl;
102  MITK_INFO << "number of digits: " << numberLength << std::endl;
103  MITK_INFO << "prefixBegin : " << prefixBegin << std::endl;
104  MITK_INFO << "prefixLength : " << prefixLength << std::endl;
105  MITK_INFO << "prefix : " << prefix << std::endl;
106  MITK_INFO << "extensionBegin : " << extensionBegin << std::endl;
107  MITK_INFO << "extensionLength : " << extensionLength << std::endl;
108  MITK_INFO << "extension : " << extension << std::endl;
109  */
110  if ((prefixLength + extensionLength + numberLength) != basename.length())
111  {
112  throw itk::ImageFileReaderException(
113  __FILE__, __LINE__, "prefixLength + extensionLength + numberLength != basenameLength");
114  }
115 
116  //
117  // Load Directory
118  //
119  std::string directory = itksys::SystemTools::GetFilenamePath(m_FileName);
120  itksys::Directory itkDir;
121  if (!itkDir.Load(directory.c_str()))
122  {
123  itkWarningMacro(<< "Directory " << directory << " cannot be read!");
124  return false;
125  }
126 
127  //
128  // Get a list of all files in the directory
129  //
130  StringContainer unmatchedFiles;
131  // unsigned long i;
132  for (unsigned long i = 0; i < itkDir.GetNumberOfFiles(); i++)
133  {
134  // Only read files
135  std::string filename = directory + "/" + itkDir.GetFile(i);
136  if (itksys::SystemTools::FileIsDirectory(filename.c_str()))
137  continue;
138 
139  // store the filenames without path
140  unmatchedFiles.push_back(itkDir.GetFile(i));
141  }
142 
143  //
144  // Match the file list against the file prefix and extension,
145  // the result should be only the files that should be read
146  //
147  StringContainer matchedFiles;
148  for (auto it = unmatchedFiles.begin(); it != unmatchedFiles.end(); ++it)
149  {
150  bool prefixMatch = false;
151  bool extensionMatch = false;
152 
153  // check if the file prefix matches the current file
154  if (prefixLength != 0)
155  prefixMatch = (it->find(prefix) == prefixBegin); // check if prefix is found
156  else
157  prefixMatch = (((*it)[0] >= '0') && ((*it)[0] <= '9')); // check if filename begins with digit
158 
159  // check if the file extension matches the current file
160  if (extensionLength != 0)
161  extensionMatch = (it->find(extension) == it->length() - extensionLength); // check if prefix is found
162  else
163  extensionMatch =
164  (((*it)[it->length() - 1] >= '0') && ((*it)[it->length() - 1] <= '9')); // check if filename ends with digit
165 
166  if (prefixMatch && extensionMatch)
167  {
168  matchedFiles.push_back(*it);
169  }
170  }
171  if (matchedFiles.size() == 0)
172  {
173  itkWarningMacro(<< "Sorry, none of the files matched the prefix!");
174  return false;
175  }
176 
177  //
178  // parse the file names from back to front for digits
179  // and convert them to a number. Store the filename and number
180  // in a SortedStringContainer
181  //
182  SortedStringContainer sortedFiles;
183  for (auto it = matchedFiles.begin(); it != matchedFiles.end(); ++it)
184  {
185  // parse the filename starting from pos digitBegin until we reach a non-digit
186  // or the end of filename
187  std::string number = "";
188  std::string currentFilename(*it);
189  for (unsigned int i = digitBegin; i < currentFilename.length(); ++i)
190  {
191  char character = currentFilename[i];
192  // do we have a digit?
193  if (character >= '0' && character <= '9')
194  number += character;
195  else
196  break; // end of digit series found, jump out of loop!
197  }
198  if (number.length() == 0)
199  {
200  // The file is not numbered, this is an error!
201  // Nevertheless, we try the next files.
202  itkWarningMacro(<< "The filename " << *it
203  << "does not contain a valid digit sequence but matches prefix and extension. Skipping file!");
204  }
205  else
206  {
207  if ((number.length() + prefix.length() + extension.length()) != it->length())
208  {
209  itkWarningMacro(
210  "The file "
211  << *it
212  << " matches prefix and extension, but the string in beteen is not a single digit-sequence. Skipping file!");
213  }
214  else
215  {
216  // convert the number string into an integer and
217  // insert the filname (including directory) into the SortedStringContainer
218  unsigned int num = atoi(number.c_str());
219  sortedFiles.insert(std::make_pair(num, directory + "/" + *it));
220  }
221  }
222  }
223  if (sortedFiles.size() == 0)
224  {
225  itkWarningMacro(<< "Sorry, no numbered files found, I can't load anything...");
226  return false;
227  }
228 
229  //
230  // Convert the sorted string container in a plain sorted vector of strings;
231  //
232  m_MatchedFileNames.clear();
233  m_MatchedFileNames.resize(sortedFiles.size());
234  unsigned long index = 0;
235  for (auto it = sortedFiles.begin(); it != sortedFiles.end(); ++it, ++index)
236  {
237  m_MatchedFileNames[index] = it->second;
238  MITK_INFO << "Added " << it->second << " to the set of matched files!" << std::endl;
239  }
240  return true;
241 }
242 
244 {
245  return m_MatchedFileNames;
246 }
247 
249 {
250 }
251 
253 {
254 }
virtual MatchedFileNames GetMatchedFileNames()
#define MITK_INFO
Definition: mitkLogMacros.h:18
std::vector< std::string > MatchedFileNames
MatchedFileNames m_MatchedFileNames