20 #include <itkTimeProbesCollectorBase.h>
33 , m_FixTiltByShearing( true )
34 , m_DecimalPlacesForOrientation( decimalPlacesForOrientation )
35 , m_ExternalCache(false)
37 this->EnsureMandatorySortersArePresent( decimalPlacesForOrientation );
43 , m_FixTiltByShearing( false )
44 , m_SortingResultInProgress( other.m_SortingResultInProgress )
45 , m_Sorter( other.m_Sorter )
46 , m_EquiDistantBlocksSorter( other.m_EquiDistantBlocksSorter->
Clone() )
47 , m_NormalDirectionConsistencySorter( other.m_NormalDirectionConsistencySorter->
Clone() )
48 , m_ReplacedCLocales( other.m_ReplacedCLocales )
49 , m_ReplacedCinLocales( other.m_ReplacedCinLocales )
50 , m_DecimalPlacesForOrientation( other.m_DecimalPlacesForOrientation )
51 , m_TagCache( other.m_TagCache )
52 , m_ExternalCache(other.m_ExternalCache)
67 this->m_SortingResultInProgress = other.m_SortingResultInProgress;
68 this->m_Sorter = other.m_Sorter;
71 this->m_ReplacedCLocales = other.m_ReplacedCLocales;
72 this->m_ReplacedCinLocales = other.m_ReplacedCinLocales;
73 this->m_DecimalPlacesForOrientation = other.m_DecimalPlacesForOrientation;
74 this->m_TagCache = other.m_TagCache;
81 if (
const Self* otherSelf = dynamic_cast<const Self*>( &other ) )
83 if ( this->m_FixTiltByShearing == otherSelf->m_FixTiltByShearing
84 && *( this->m_EquiDistantBlocksSorter ) == *( otherSelf->m_EquiDistantBlocksSorter )
85 && ( fabs( this->m_DecimalPlacesForOrientation - otherSelf->m_DecimalPlacesForOrientation ) <
eps ) )
88 if ( this->m_Sorter.size() != otherSelf->m_Sorter.size() )
91 auto mySorterIter = this->m_Sorter.cbegin();
92 auto oSorterIter = otherSelf->m_Sorter.cbegin();
93 for ( ; mySorterIter != this->m_Sorter.cend() && oSorterIter != otherSelf->m_Sorter.cend();
94 ++mySorterIter, ++oSorterIter )
96 if ( !( **mySorterIter == **oSorterIter ) )
117 m_FixTiltByShearing = on;
122 return m_FixTiltByShearing;
128 m_EquiDistantBlocksSorter->SetAcceptTwoSlicesGroups( accept );
133 return m_EquiDistantBlocksSorter->GetAcceptTwoSlicesGroups();
138 unsigned int sortIndex( 1 );
139 for (
auto sorterIter = m_Sorter.cbegin(); sorterIter != m_Sorter.cend(); ++sortIndex, ++sorterIter )
141 os <<
"Sorting step " << sortIndex <<
":" << std::endl;
142 ( *sorterIter )->PrintConfiguration( os,
" " );
145 os <<
"Sorting step " << sortIndex <<
":" << std::endl;
146 m_EquiDistantBlocksSorter->PrintConfiguration( os,
" " );
152 return setlocale( LC_NUMERIC,
nullptr );
157 s_LocaleMutex->Lock();
159 std::string currentCLocale = setlocale( LC_NUMERIC,
nullptr );
160 m_ReplacedCLocales.push( currentCLocale );
161 setlocale( LC_NUMERIC,
"C" );
163 std::locale currentCinLocale( std::cin.getloc() );
164 m_ReplacedCinLocales.push( currentCinLocale );
165 std::locale l(
"C" );
168 s_LocaleMutex->Unlock();
173 s_LocaleMutex->Lock();
175 if ( !m_ReplacedCLocales.empty() )
177 setlocale( LC_NUMERIC, m_ReplacedCLocales.top().c_str() );
178 m_ReplacedCLocales.pop();
182 MITK_WARN <<
"Mismatched PopLocale on DICOMITKSeriesGDCMReader.";
185 if ( !m_ReplacedCinLocales.empty() )
187 std::cin.imbue( m_ReplacedCinLocales.top() );
188 m_ReplacedCinLocales.pop();
192 MITK_WARN <<
"Mismatched PopLocale on DICOMITKSeriesGDCMReader.";
195 s_LocaleMutex->Unlock();
204 #if defined( MBILOG_ENABLE_DEBUG ) || defined( ENABLE_TIMING )
205 #define timeStart( part ) timer.Start( part );
206 #define timeStop( part ) timer.Stop( part );
208 #define timeStart( part )
209 #define timeStop( part )
214 itk::TimeProbesCollectorBase timer;
217 this->ClearOutputs();
221 const StringList inputFilenames = this->GetInputFiles();
223 if ( inputFilenames.empty() || !this->CanHandleFile( inputFilenames.front() )
224 || !this->CanHandleFile( inputFilenames.back() )
225 || !this->CanHandleFile( inputFilenames[inputFilenames.size() / 2] )
229 MITK_DEBUG <<
"Reader unable to process files..";
236 if ( m_TagCache.IsNull() || ( m_TagCache->GetMTime()<this->GetMTime() && !m_ExternalCache ))
241 filescanner->SetInputFiles( inputFilenames );
242 filescanner->AddTagPaths( this->GetTagsOfInterest() );
248 m_TagCache = filescanner->GetScanCache();
257 m_SortingResultInProgress.clear();
258 m_SortingResultInProgress.push_back(m_TagCache->GetFrameInfoList());
263 unsigned int sorterIndex = 0;
264 for (
auto sorterIter = m_Sorter.cbegin(); sorterIter != m_Sorter.cend(); ++sorterIndex, ++sorterIter )
266 std::stringstream ss;
267 ss <<
"Sorting step " << sorterIndex;
269 m_SortingResultInProgress =
270 this->InternalExecuteSortingStep( sorterIndex, *sorterIter, m_SortingResultInProgress );
276 m_SortingResultInProgress = this->InternalExecuteSortingStep(
277 sorterIndex++, m_EquiDistantBlocksSorter.GetPointer(), m_SortingResultInProgress );
278 timeStop(
"EquiDistantBlocksSorter" );
283 m_SortingResultInProgress = this->Condense3DBlocks( m_SortingResultInProgress );
289 unsigned int o = this->GetNumberOfOutputs();
290 this->SetNumberOfOutputs(
291 o + m_SortingResultInProgress.size() );
292 for (
auto blockIter = m_SortingResultInProgress.cbegin(); blockIter != m_SortingResultInProgress.cend();
296 assert( !gdcmFrameInfoList.empty() );
301 m_NormalDirectionConsistencySorter->SetInput( datasetList );
302 m_NormalDirectionConsistencySorter->Sort();
309 assert( !frameList.empty() );
315 block.SetAdditionalTagsOfInterest( GetAdditionalTagsOfInterest() );
316 block.SetTagLookupTableToPropertyFunctor( GetTagLookupTableToPropertyFunctor() );
317 block.SetImageFrameList( frameList );
318 block.SetTiltInformation( tiltInfo );
320 block.SetReaderImplementationLevel( this->GetReaderImplementationLevel( block.GetSOPClassUID() ) );
322 this->SetOutput( o, block );
326 #if defined( MBILOG_ENABLE_DEBUG ) || defined( ENABLE_TIMING )
327 std::cout <<
"---------------------------------------------------------------" << std::endl;
328 timer.Report( std::cout );
329 std::cout <<
"---------------------------------------------------------------" << std::endl;
337 std::stringstream ss;
338 ss <<
"Sorting step " << sortingStepIndex <<
" '";
339 #if defined( MBILOG_ENABLE_DEBUG )
340 sorter->PrintConfiguration( ss );
343 nextStepSorting.clear();
345 MITK_DEBUG <<
"================================================================================";
346 MITK_DEBUG <<
"DICOMITKSeriesGDCMReader: " << ss.str() <<
": " << input.size() <<
" groups input";
347 unsigned int groupIndex = 0;
349 for (
auto blockIter = input.cbegin(); blockIter != input.cend(); ++groupIndex, ++blockIter )
354 #if defined( MBILOG_ENABLE_DEBUG )
355 MITK_DEBUG <<
"--------------------------------------------------------------------------------";
356 MITK_DEBUG <<
"DICOMITKSeriesGDCMReader: " << ss.str() <<
", dataset group " << groupIndex <<
" ("
357 << datasetList.size() <<
" datasets): ";
358 for (
auto oi = datasetList.cbegin(); oi != datasetList.cend(); ++oi )
360 MITK_DEBUG <<
" INPUT : " << ( *oi )->GetFilenameIfAvailable();
364 sorter->SetInput( datasetList );
366 unsigned int numberOfResultingBlocks = sorter->GetNumberOfOutputs();
368 for (
unsigned int b = 0; b < numberOfResultingBlocks; ++b )
372 for (
auto oi = blockResult.cbegin(); oi != blockResult.cend(); ++oi )
374 MITK_DEBUG <<
" OUTPUT(" << b <<
") :" << ( *oi )->GetFilenameIfAvailable();
378 nextStepSorting.push_back( sortedGdcmInfoFrameList );
382 return nextStepSorting;
388 if ( sopClassUID.empty() )
393 gdcm::UIDs uidKnowledge;
394 uidKnowledge.SetFromUID( sopClassUID.c_str() );
396 gdcm::UIDs::TSType gdcmType = uidKnowledge;
400 case gdcm::UIDs::CTImageStorage:
401 case gdcm::UIDs::MRImageStorage:
402 case gdcm::UIDs::PositronEmissionTomographyImageStorage:
403 case gdcm::UIDs::ComputedRadiographyImageStorage:
404 case gdcm::UIDs::DigitalXRayImageStorageForPresentation:
405 case gdcm::UIDs::DigitalXRayImageStorageForProcessing:
408 case gdcm::UIDs::NuclearMedicineImageStorage:
411 case gdcm::UIDs::SecondaryCaptureImageStorage:
425 unsigned int numberOfOutputs = this->GetNumberOfOutputs();
426 for (
unsigned int o = 0; o < numberOfOutputs; ++o )
428 success &= this->LoadMitkImageForOutput( o );
443 filenames.reserve( frames.size() );
444 for (
auto frameIter = frames.cbegin(); frameIter != frames.cend(); ++frameIter )
446 filenames.push_back( ( *frameIter )->Filename );
450 bool success(
true );
456 catch (
const std::exception& e )
459 MITK_ERROR <<
"Exception during image loading: " << e.what();
471 return this->LoadMitkImageForImageBlockDescriptor( block );
486 m_Sorter.push_front( sorter );
490 m_Sorter.push_back( sorter );
498 std::list<DICOMDatasetSorter::ConstPointer> result;
500 unsigned int sortIndex( 0 );
501 for (
auto sorterIter = m_Sorter.begin(); sorterIter != m_Sorter.end(); ++sortIndex, ++sorterIter )
505 result.push_back( ( *sorterIter ).GetPointer() );
512 void mitk::DICOMITKSeriesGDCMReader::EnsureMandatorySortersArePresent(
513 unsigned int decimalPlacesForOrientation )
516 splitter->AddDistinguishingTag(
DICOMTag(0x0028, 0x0010) );
517 splitter->AddDistinguishingTag(
DICOMTag(0x0028, 0x0011) );
518 splitter->AddDistinguishingTag(
DICOMTag(0x0028, 0x0030) );
519 splitter->AddDistinguishingTag(
DICOMTag(0x0018, 0x1164) );
521 splitter->AddDistinguishingTag(
DICOMTag(0x0018, 0x0050) );
522 splitter->AddDistinguishingTag(
DICOMTag(0x0028, 0x0008) );
523 this->AddSortingElement( splitter,
true );
525 if ( m_EquiDistantBlocksSorter.IsNull() )
529 m_EquiDistantBlocksSorter->SetAcceptTilt( m_FixTiltByShearing );
531 if ( m_NormalDirectionConsistencySorter.IsNull() )
539 assert( m_EquiDistantBlocksSorter.IsNotNull() );
540 m_EquiDistantBlocksSorter->SetToleratedOriginOffsetToAdaptive( fractionOfInterSliceDistance );
546 assert( m_EquiDistantBlocksSorter.IsNotNull() );
547 m_EquiDistantBlocksSorter->SetToleratedOriginOffset( millimeters );
553 assert( m_EquiDistantBlocksSorter.IsNotNull() );
554 return m_EquiDistantBlocksSorter->GetToleratedOriginOffset();
559 assert( m_EquiDistantBlocksSorter.IsNotNull() );
560 return m_EquiDistantBlocksSorter->IsToleratedOriginOffsetAbsolute();
565 return m_DecimalPlacesForOrientation;
575 m_TagCache = tagCache;
576 m_ExternalCache = tagCache.IsNotNull();
584 for (
auto sorterIter = m_Sorter.cbegin(); sorterIter != m_Sorter.cend(); ++sorterIter )
586 assert( sorterIter->IsNotNull() );
588 const DICOMTagList tags = ( *sorterIter )->GetTagsOfInterest();
589 completeList.insert( completeList.end(), tags.cbegin(), tags.cend() );
593 DICOMTagList tags = m_EquiDistantBlocksSorter->GetTagsOfInterest();
594 completeList.insert( completeList.end(), tags.cbegin(), tags.cend() );
596 tags = m_NormalDirectionConsistencySorter->GetTagsOfInterest();
597 completeList.insert( completeList.end(), tags.cbegin(), tags.cend() );
601 completeList.insert( completeList.end(), tags.cbegin(), tags.cend() );
605 for (
auto iter = tagList.cbegin();
606 iter != tagList.cend();
610 completeList.push_back( iter->first ) ;
section MAP_FRAME_Mapper_Settings Mapper settings For the mapping of corrected you have several settings but high interpolation errors for gray value images Right choice for label images or masks li Details of the frame selection In this tab you can specify the frames of the currently selected image that should be corrected As default all frames of an image will be corrected If you only select specific frames
static DICOMTagList GetTagsOfInterest()
virtual bool CanHandleFile(const std::string &filename) override
Indicate whether this reader can handle given file.
const DICOMImageFrameList & GetImageFrameList() const
List of frames that constitute the mitk::Image (DICOMImageFrames)
virtual void InternalPrintConfiguration(std::ostream &os) const override
Configuration description for human reader, to be implemented by sub-classes.
loader did not yet inspect any images, unknown fitness
itk::SmartPointer< Self > Pointer
virtual bool operator==(const DICOMFileReader &other) const override
The sorting/splitting building-block of DICOMITKSeriesGDCMReader.
Flexible reader based on itk::ImageSeriesReader and GDCM, for single-slice modalities like CT...
static bool CanHandleFile(const std::string &filename)
std::vector< DICOMTag > DICOMTagList
static std::string GetActiveLocale()
Return active C locale.
void SetTagCache(const DICOMTagCache::Pointer &) override
A way to provide external knowledge about files and tag values is appreciated.
void SetToleratedOriginOffsetToAdaptive(double fractionOfInterSliceDistanct=0.3) const
See Forced Configuration.
mitk::EquiDistantBlocksSorter::Pointer m_EquiDistantBlocksSorter
Representation of a DICOM tag.
Image::Pointer Load(const StringContainer &filenames, bool correctTilt, const GantryTiltInformation &tiltInfo)
virtual void AnalyzeInputFiles() override
Runs the sorting / splitting process described in Loading strategy. Method required by DICOMFileReade...
void SetFixTiltByShearing(bool on)
Controls whether to "fix" tilted acquisitions by shearing the output (see Gantry tilt handling)...
ConstSorterList GetFreelyConfiguredSortingElements() const
const GantryTiltInformation GetTiltInformation() const
Describe the gantry tilt of the acquisition.
void SetAcceptTwoSlicesGroups(bool accept) const
Controls whether groups of only two images are accepted when ensuring consecutive slices via EquiDist...
MITKDICOMREADER_EXPORT mitk::DICOMDatasetList ConvertToDICOMDatasetList(const DICOMDatasetAccessingImageFrameList &input)
virtual DICOMTagCache::Pointer GetTagCache() const
loader code and tests are established
virtual SortingBlockList Condense3DBlocks(SortingBlockList &resultOf3DGrouping)
"Hook" for sub-classes, see Sub-classes can condense multiple blocks into a single larger block ...
MITKDICOMREADER_EXPORT mitk::DICOMDatasetAccessingImageFrameList ConvertToDICOMDatasetAccessingImageFrameList(const DICOMDatasetList &input)
void PopLocale() const
Activate last remembered locale from locale stack "C" locale is required for correct parsing of numbe...
virtual bool LoadImages() override
Loads images using itk::ImageSeriesReader, potentially applies shearing to correct gantry tilt...
static SortingBlockList InternalExecuteSortingStep(unsigned int sortingStepIndex, const DICOMDatasetSorter::Pointer &sorter, const SortingBlockList &input)
Sorting step as described in Loading strategy.
loader code is not known to work with this SOP Class
loader code is implemented but not accompanied by tests
void SetMitkImage(Image::Pointer image)
The 3D mitk::Image that is loaded from the DICOM files of a DICOMImageFrameList.
bool IsToleratedOriginOffsetAbsolute() const
const std::list< DICOMDatasetSorter::ConstPointer > ConstSorterList
ReaderImplementationLevel
Describes how well the reader is tested for a certain file type (see mitk::DICOMFileReader).
void PushLocale() const
Remember current locale on stack, activate "C" locale. "C" locale is required for correct parsing of ...
static const std::string filename
std::vector< DICOMImageFrameInfo::Pointer > DICOMImageFrameList
DICOMImageBlockDescriptor::AdditionalTagsMapType AdditionalTagsMapType
virtual bool LoadMitkImageForImageBlockDescriptor(DICOMImageBlockDescriptor &block) const
virtual ~DICOMITKSeriesGDCMReader()
DICOMITKSeriesGDCMReader(unsigned int decimalPlacesForOrientation=5)
Output descriptor for DICOMFileReader.
void SetTagCache(DICOMTagCache *privateCache)
virtual void AddSortingElement(DICOMDatasetSorter *sorter, bool atFront=false)
Add an element to the sorting procedure described in Loading strategy.
virtual bool LoadMitkImageForOutput(unsigned int o)
Loads the mitk::Image by means of an itk::ImageSeriesReader.
std::vector< std::string > StringList
std::vector< DICOMTagPath > DICOMTagPathList
std::vector< DICOMDatasetAccessingImageFrameList > SortingBlockList
MITKDICOMREADER_EXPORT mitk::DICOMImageFrameList ConvertToDICOMImageFrameList(const DICOMDatasetAccessingImageFrameList &input)
void SetToleratedOriginOffset(double millimeters=0.005) const
See Forced Configuration.
static ReaderImplementationLevel GetReaderImplementationLevel(const std::string sopClassUID)
Describe this reader's confidence for given SOP class UID.
std::vector< DICOMDatasetAccessingImageFrameInfo::Pointer > DICOMDatasetAccessingImageFrameList
Cuts a number after configured number of decimal places. An instance of this class can be used to avo...
loader code and tests are establised for specific parts of a SOP Class
double GetToleratedOriginError() const
DICOMITKSeriesGDCMReader & operator=(const DICOMITKSeriesGDCMReader &other)
MITKCORE_EXPORT const ScalarType eps
bool GetAcceptTwoSlicesGroups() const
DICOMFileReader & operator=(const DICOMFileReader &other)
std::vector< DICOMDatasetAccess * > DICOMDatasetList
Interface for DICOM readers that produce mitk::Images.
mitk::NormalDirectionConsistencySorter::Pointer m_NormalDirectionConsistencySorter
bool GetFixTiltByShearing() const
double GetDecimalPlacesForOrientation() const
std::vector< std::string > StringContainer
virtual DICOMTagPathList GetTagsOfInterest() const override
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.