<commit_before>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#ifndef mitkDicomSeriesReader_h
#define mitkDicomSeriesReader_h

#include "mitkDataNode.h"
#include "mitkConfig.h"

#ifdef MITK_USE_GDCMIO
  #include <itkGDCMImageIO.h>
#else
  #include <itkDICOMImageIO2.h>
#endif

#include <itkImageSeriesReader.h>
#include <itkCommand.h>

#include <gdcmConfigure.h>

#if GDCM_MAJOR_VERSION >= 2
  #include <gdcmDataSet.h>
  #include <gdcmRAWCodec.h>
  #include <gdcmSorter.h>
  #include <gdcmScanner.h>
  #include <gdcmPixmapReader.h>
  #include <gdcmStringFilter.h>
#endif


namespace mitk
{

/** 
 \brief Central DICOM image loading class for MITK.

 \section DicomSeriesReader_usage Usage
 
 The DICOM series is specified through an enumeration of all files contained in it.

 A method for the creation of file name enumerations of all series contained in
 a particular directory is also provided.

 After loading the series, the generated DataNode is not named. The caller is
 responsible for given the node a name.

  Example:

\code

 // only directory known here: /home/me/dicom

 DicomSeriesReader::UidFileNamesMap allImageBlocks = DicomSeriesReader::GetSeries("/home/me/dicom/");

 // file now divided into groups of identical image size, orientation, spacing, etc.
 // each of these lists should be loadable as an mitk::Image.

 // optional step: sorting (this is also done by LoadDicomSeries if not explicitly suppressed)
 DicomSeriesReader::StringContainer seriesToLoad = allImageBlocks[...]; // decide for yourself
  
 DicomSeriesReader::StringContainer oneBlockSorted = DicomSeriesReader::SortSeriesSlices( seriesToLoad );

 // final step: load into DataNode (can result in 3D+t image)
 DataNode::Pointer node = DicomSeriesReader::LoadDicomSeries( oneBlockSorted ); // would sort again, but we could set the sort flag to false

 Image::Pointer image = dynamic_cast<mitk::Image*>( node->GetData() );
\endcode

TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO
 <b>Necessary changes (bug 7285)</b>

 * GetSeries should by default
   * sort slices
   * determine if slice groups contain gaps (this is only done fast if slices are sorted previously)
     of if slices are not equally spaced
     * if gap, split into two parts 
     * if non-continous: split into continuous groups
       * this is a little tricky: create (all?) possible sortings, then determine the one with minimum number of groups
 * If somebody demands it, this check could be explicitly disabled by a flag
 * The SortSeriesSlices method can be removed (take care of existing callers), since this is done by GetSeries
 * LoadDicomSeries changes
   * remove parameter "bool sort" (now expected to be done previously)

 * handle titled geometries!
   * ImageSeriesReader will definitely calculate a wrong spacing
   * either we load each slice separately
   * or ...?
TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO
 
 \section DicomSeriesReader_sorting Sorting into 3D+t blocks

 TODO: describe strategy of sorting images into blocks of 3D image stacks
<commit_msg>Sketch solution for 3D+t loading<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#ifndef mitkDicomSeriesReader_h
#define mitkDicomSeriesReader_h

#include "mitkDataNode.h"
#include "mitkConfig.h"

#ifdef MITK_USE_GDCMIO
  #include <itkGDCMImageIO.h>
#else
  #include <itkDICOMImageIO2.h>
#endif

#include <itkImageSeriesReader.h>
#include <itkCommand.h>

#include <gdcmConfigure.h>

#if GDCM_MAJOR_VERSION >= 2
  #include <gdcmDataSet.h>
  #include <gdcmRAWCodec.h>
  #include <gdcmSorter.h>
  #include <gdcmScanner.h>
  #include <gdcmPixmapReader.h>
  #include <gdcmStringFilter.h>
#endif


namespace mitk
{

/** 
 \brief Central DICOM image loading class for MITK.

 \section DicomSeriesReader_usage Usage
 
 The DICOM series is specified through an enumeration of all files contained in it.

 A method for the creation of file name enumerations of all series contained in
 a particular directory is also provided.

 After loading the series, the generated DataNode is not named. The caller is
 responsible for given the node a name.

  Example:

\code

 // only directory known here: /home/me/dicom

 DicomSeriesReader::UidFileNamesMap allImageBlocks = DicomSeriesReader::GetSeries("/home/me/dicom/");

 // file now divided into groups of identical image size, orientation, spacing, etc.
 // each of these lists should be loadable as an mitk::Image.

 // optional step: sorting (this is also done by LoadDicomSeries if not explicitly suppressed)
 DicomSeriesReader::StringContainer seriesToLoad = allImageBlocks[...]; // decide for yourself
  
 DicomSeriesReader::StringContainer oneBlockSorted = DicomSeriesReader::SortSeriesSlices( seriesToLoad );

 // final step: load into DataNode (can result in 3D+t image)
 DataNode::Pointer node = DicomSeriesReader::LoadDicomSeries( oneBlockSorted ); // would sort again, but we could set the sort flag to false

 Image::Pointer image = dynamic_cast<mitk::Image*>( node->GetData() );
\endcode

TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO
 <b>Necessary changes (bug 7285)</b>

 * GetSeries should by default
   * sort slices
   * determine if slice groups contain gaps (this is only done fast if slices are sorted previously)
     of if slices are not equally spaced
     * if gap, split into two parts 
     * if non-continous: split into continuous groups
       * this is a little tricky: create (all?) possible sortings, then determine the one with minimum number of groups
 * If somebody demands it, this check could be explicitly disabled by a flag
 * The SortSeriesSlices method can be removed (take care of existing callers), since this is done by GetSeries
 * LoadDicomSeries changes
   * remove parameter "bool sort" (now expected to be done previously)

 * handle titled geometries!
   * ImageSeriesReader will definitely calculate a wrong spacing
   * either we load each slice separately
   * or ...?


 3D+t handling:
  * the "block sorting" in GetSeries will separate images that occupy the identical position in space
    * this process will keep the initial sorting that organized slices by 1. position 2. acquisition time
    * i.e. after block sorting, there are multiple blocks that cover identical positions and 
      have identical properties regarding orientation, dimensions, spacing etc.
  * depending on arguments passed to GetSeries, it will attempt to group as many image blocks as possible to
    a single, large 3D+t image group (default behavior is to do this).
  * LoadDicomSeries expects(!) that the filenames passed either form a valid 3D block or a 3D+t block
    as sorted by GetSeries()

  * TODO later, when dicom tags are loaded for each mitk::Image slice, there should be a verification
    step for correct positions (optional if time-consuming)

TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO
 
 \section DicomSeriesReader_sorting Sorting into 3D+t blocks

 TODO: describe strategy of sorting images into blocks of 3D image stacks

{'fraction_non_alphanumeric': 0.09978096860550012, 'fraction_numerical': 0.003042102701387199, 'mean_word_length': 4.519811954331766, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2959645', 'n_tokens_mistral': 2304, 'n_tokens_neox': 2169, 'n_words': 963}