22 , m_TagCache( nullptr )
23 , m_PropertiesOutOfDate( true )
25 m_PropertyFunctor = &mitk::DICOMImageBlockDescriptor::GetPropertyForDICOMValues;
33 : m_ImageFrameList( other.m_ImageFrameList )
34 , m_MitkImage( other.m_MitkImage )
35 , m_SliceIsLoaded( other.m_SliceIsLoaded )
36 , m_ReaderImplementationLevel( other.m_ReaderImplementationLevel )
37 , m_TiltInformation( other.m_TiltInformation )
38 , m_PropertyList( other.m_PropertyList->
Clone() )
39 , m_TagCache( other.m_TagCache )
40 , m_PropertiesOutOfDate( other.m_PropertiesOutOfDate )
41 , m_AdditionalTagMap(other.m_AdditionalTagMap)
42 , m_FoundAdditionalTags(other.m_FoundAdditionalTags)
43 , m_PropertyFunctor(other.m_PropertyFunctor)
47 m_MitkImage = m_MitkImage->Clone();
50 m_PropertyFunctor = &mitk::DICOMImageBlockDescriptor::GetPropertyForDICOMValues;
58 m_ImageFrameList = other.m_ImageFrameList;
59 m_MitkImage = other.m_MitkImage;
60 m_SliceIsLoaded = other.m_SliceIsLoaded;
61 m_ReaderImplementationLevel = other.m_ReaderImplementationLevel;
62 m_TiltInformation = other.m_TiltInformation;
64 m_AdditionalTagMap = other.m_AdditionalTagMap;
65 m_FoundAdditionalTags = other.m_FoundAdditionalTags;
66 m_PropertyFunctor = other.m_PropertyFunctor;
68 if ( other.m_PropertyList )
70 m_PropertyList = other.m_PropertyList->Clone();
73 if ( other.m_MitkImage )
75 m_MitkImage = other.m_MitkImage->Clone();
78 m_TagCache = other.m_TagCache;
79 m_PropertiesOutOfDate = other.m_PropertiesOutOfDate;
88 completeList.push_back(
DICOMTag( 0x0018, 0x1164 ) );
89 completeList.push_back(
DICOMTag( 0x0028, 0x0030 ) );
91 completeList.push_back(
DICOMTag( 0x0008, 0x0018 ) );
92 completeList.push_back(
DICOMTag( 0x0008, 0x0016 ) );
94 completeList.push_back(
DICOMTag( 0x0020, 0x0011 ) );
95 completeList.push_back(
DICOMTag( 0x0008, 0x1030 ) );
96 completeList.push_back(
DICOMTag( 0x0008, 0x103e ) );
97 completeList.push_back(
DICOMTag( 0x0008, 0x0060 ) );
98 completeList.push_back(
DICOMTag( 0x0018, 0x0024 ) );
99 completeList.push_back(
DICOMTag( 0x0020, 0x0037 ) );
101 completeList.push_back(
DICOMTag( 0x0020, 0x1041 ) );
102 completeList.push_back(
DICOMTag( 0x0020, 0x0012 ) );
103 completeList.push_back(
DICOMTag( 0x0020, 0x0013 ) );
104 completeList.push_back(
DICOMTag( 0x0020, 0x0032 ) );
106 completeList.push_back(
DICOMTag( 0x0028, 0x1050 ) );
107 completeList.push_back(
DICOMTag( 0x0028, 0x1051 ) );
108 completeList.push_back(
DICOMTag( 0x0008, 0x0008 ) );
109 completeList.push_back(
DICOMTag( 0x0028, 0x0004 ) );
118 m_AdditionalTagMap = tagMap;
124 m_TiltInformation =
info;
129 return m_TiltInformation;
134 m_ImageFrameList = framelist;
135 m_SliceIsLoaded.resize( framelist.size() );
136 m_SliceIsLoaded.assign( framelist.size(), false );
138 m_PropertiesOutOfDate =
true;
143 return m_ImageFrameList;
148 if ( m_MitkImage != image )
150 if ( m_TagCache.IsExpired() )
152 MITK_ERROR <<
"Unable to describe MITK image with properties without a tag-cache object!";
153 m_MitkImage =
nullptr;
157 if ( m_ImageFrameList.empty() )
159 MITK_ERROR <<
"Unable to describe MITK image with properties without a frame list!";
160 m_MitkImage =
nullptr;
170 m_MitkImage = this->DescribeImageWithProperties( this->FixupSpacing( image ) );
188 desiredSpacingX, desiredSpacingY );
190 if ( desiredSpacingX <= 0 || desiredSpacingY <= 0 )
195 MITK_DEBUG <<
"Loaded image with spacing " << imageSpacing[0] <<
", " << imageSpacing[1];
196 MITK_DEBUG <<
"Found correct spacing info " << desiredSpacingX <<
", " << desiredSpacingY;
198 imageSpacing[0] = desiredSpacingX;
199 imageSpacing[1] = desiredSpacingY;
205 void mitk::DICOMImageBlockDescriptor::SetSliceIsLoaded(
unsigned int index,
bool isLoaded )
207 if ( index < m_SliceIsLoaded.size() )
209 m_SliceIsLoaded[index] = isLoaded;
213 std::stringstream ss;
214 ss <<
"Index " << index <<
" out of range (" << m_SliceIsLoaded.size() <<
" indices reserved)";
215 throw std::invalid_argument( ss.str() );
219 bool mitk::DICOMImageBlockDescriptor::IsSliceLoaded(
unsigned int index )
const 221 if ( index < m_SliceIsLoaded.size() )
223 return m_SliceIsLoaded[index];
227 std::stringstream ss;
228 ss <<
"Index " << index <<
" out of range (" << m_SliceIsLoaded.size() <<
" indices reserved)";
229 throw std::invalid_argument( ss.str() );
233 bool mitk::DICOMImageBlockDescriptor::AllSlicesAreLoaded()
const 235 bool allLoaded =
true;
236 for (
auto iter = m_SliceIsLoaded.cbegin(); iter != m_SliceIsLoaded.cend(); ++iter )
256 if ( m_ImageFrameList.empty() || m_TagCache.IsExpired() )
258 MITK_ERROR <<
"Invalid call to GetPixelSpacingInterpretation. Need to have initialized tag-cache!";
262 const std::string pixelSpacing = this->GetPixelSpacing();
263 const std::string imagerPixelSpacing = this->GetImagerPixelSpacing();
265 if ( pixelSpacing.empty() )
267 if ( imagerPixelSpacing.empty() )
278 if ( imagerPixelSpacing.empty() )
282 else if ( pixelSpacing != imagerPixelSpacing )
293 std::string mitk::DICOMImageBlockDescriptor::GetPixelSpacing()
const 295 if ( m_ImageFrameList.empty() || m_TagCache.IsExpired() )
297 MITK_ERROR <<
"Invalid call to GetPixelSpacing. Need to have initialized tag-cache!";
298 return std::string(
"" );
301 static const DICOMTag tagPixelSpacing( 0x0028, 0x0030 );
302 return m_TagCache.Lock()->GetTagValue( m_ImageFrameList.front(), tagPixelSpacing ).value;
305 std::string mitk::DICOMImageBlockDescriptor::GetImagerPixelSpacing()
const 307 if ( m_ImageFrameList.empty() || m_TagCache.IsExpired() )
309 MITK_ERROR <<
"Invalid call to GetImagerPixelSpacing. Need to have initialized tag-cache!";
310 return std::string(
"" );
313 static const DICOMTag tagImagerPixelSpacing( 0x0018, 0x1164 );
314 return m_TagCache.Lock()->GetTagValue( m_ImageFrameList.front(), tagImagerPixelSpacing ).value;
320 const std::string pixelSpacing = this->GetPixelSpacing();
324 const std::string imagerPixelSpacing = this->GetImagerPixelSpacing();
332 if (spacingX < mitk::eps || spacingX > 1000 || spacingY < mitk::eps || spacingY > 1000)
334 spacingX = spacingY = 1.0;
342 m_PropertyList->SetProperty( key, value );
347 this->UpdateImageDescribingProperties();
348 return m_PropertyList->GetProperty( key );
353 this->UpdateImageDescribingProperties();
355 if ( property.IsNotNull() )
357 return property->GetValueAsString();
361 return std::string(
"" );
372 this->UpdateImageDescribingProperties();
374 if ( boolProp.IsNotNull() )
376 return boolProp->GetValue();
391 this->UpdateImageDescribingProperties();
393 if ( intProp.IsNotNull() )
395 return intProp->GetValue();
403 double mitk::DICOMImageBlockDescriptor::stringtodouble(
const std::string& str )
const 406 std::string trimmedstring( str );
409 trimmedstring = trimmedstring.erase( trimmedstring.find_last_not_of(
" \n\r\t" ) + 1 );
416 std::string firstcomponent( trimmedstring );
419 firstcomponent = trimmedstring.erase( trimmedstring.find_first_of(
"\\" ) );
426 std::istringstream converter( firstcomponent );
427 if ( !firstcomponent.empty() && ( converter >> d ) && converter.eof() )
433 throw std::invalid_argument(
"Argument is not a convertable number" );
450 const char* propertyKeySliceLocation =
"dicom.image.0020.1041";
451 const char* propertyKeyInstanceNumber =
"dicom.image.0020.0013";
452 const char* propertyKeySOPInstanceUID =
"dicom.image.0008.0018";
465 "dicomseriesreader.PixelSpacingInterpretationString",
468 "dicomseriesreader.PixelSpacingInterpretation",
472 "dicomseriesreader.ReaderImplementationLevelString",
475 mitkImage->
SetProperty(
"dicomseriesreader.ReaderImplementationLevel",
478 mitkImage->
SetProperty(
"dicomseriesreader.GantyTiltCorrected",
488 const double level = stringtodouble( windowCenter );
489 const double window = stringtodouble( windowWidth );
500 mitkImage->
SetProperty(
"dicom.pixel.PhotometricInterpretation",
501 this->
GetProperty(
"photometricInterpretation" ) );
512 for (
auto tag : m_FoundAdditionalTags)
528 m_ReaderImplementationLevel = level;
533 return m_ReaderImplementationLevel;
538 if ( !m_ImageFrameList.empty() && !m_TagCache.IsExpired() )
540 static const DICOMTag tagSOPClassUID( 0x0008, 0x0016 );
541 return m_TagCache.Lock()->GetTagValue( m_ImageFrameList.front(), tagSOPClassUID ).value;
546 <<
"Invalid call to DICOMImageBlockDescriptor::GetSOPClassUID(). Need to have initialized tag-cache!";
547 return std::string(
"" );
553 if ( !m_ImageFrameList.empty() && !m_TagCache.IsExpired() )
555 gdcm::UIDs uidKnowledge;
558 const char* name = uidKnowledge.GetName();
561 return std::string( name );
565 return std::string(
"" );
570 MITK_ERROR <<
"Invalid call to DICOMImageBlockDescriptor::GetSOPClassUIDAsName(). Need to have " 571 "initialized tag-cache!";
572 return std::string(
"" );
579 this->m_PropertyList->GetIntProperty(
"timesteps", result);
587 int numberOfFramesPerTimestep = this->m_ImageFrameList.size() / numberOfTimesteps;
588 assert(
int(
double((
double)this->m_ImageFrameList.size() / (double)numberOfTimesteps))
589 == numberOfFramesPerTimestep);
591 return numberOfFramesPerTimestep;
598 m_TagCache = privateCache;
601 #define printPropertyRange( label, property_name ) \ 604 const std::string first = this->GetPropertyAsString( #property_name "First" ); \ 605 const std::string last = this->GetPropertyAsString( #property_name "Last" ); \ 606 if ( !first.empty() || !last.empty() ) \ 608 if ( first == last ) \ 610 os << " " label ": '" << first << "'" << std::endl; \ 614 os << " " label ": '" << first << "' - '" << last << "'" << std::endl; \ 620 #define printProperty( label, property_name ) \ 623 const std::string first = this->GetPropertyAsString( #property_name ); \ 624 if ( !first.empty() ) \ 626 os << " " label ": '" << first << "'" << std::endl; \ 631 #define printBool( label, commands ) \ 634 os << " " label ": '" << ( commands ? "yes" : "no" ) << "'" << std::endl; \ 643 os <<
" Number of Frames: '" << m_ImageFrameList.size() <<
"'" << std::endl;
658 os <<
" Pixel spacing interpretation: '" 665 if ( filenameDetails )
667 os <<
" Files in this image block:" << std::endl;
668 for (
auto frameIter = m_ImageFrameList.begin(); frameIter != m_ImageFrameList.end(); ++frameIter )
670 os <<
" " << ( *frameIter )->Filename;
671 if ( ( *frameIter )->FrameNo > 0 )
673 os <<
", " << ( *frameIter )->FrameNo;
680 #define storeTagValueToProperty( tag_name, tag_g, tag_e ) \ 683 const DICOMTag t( tag_g, tag_e ); \ 684 const std::string tagValue = tagCache->GetTagValue( firstFrame, t ).value; \ 685 const_cast<DICOMImageBlockDescriptor*>( this ) \ 686 ->SetProperty( #tag_name, StringProperty::New( tagValue ) ); \ 690 #define storeTagValueRangeToProperty( tag_name, tag_g, tag_e ) \ 693 const DICOMTag t( tag_g, tag_e ); \ 694 const std::string tagValueFirst = tagCache->GetTagValue( firstFrame, t ).value; \ 695 const std::string tagValueLast = tagCache->GetTagValue( lastFrame, t ).value; \ 696 const_cast<DICOMImageBlockDescriptor*>( this ) \ 697 ->SetProperty( #tag_name "First", StringProperty::New( tagValueFirst ) ); \ 698 const_cast<DICOMImageBlockDescriptor*>( this ) \ 699 ->SetProperty( #tag_name "Last", StringProperty::New( tagValueLast ) ); \ 704 void mitk::DICOMImageBlockDescriptor::UpdateImageDescribingProperties()
const 706 if ( !m_PropertiesOutOfDate )
709 if ( !m_ImageFrameList.empty() )
711 if ( m_TagCache.IsExpired() )
713 MITK_ERROR <<
"Invalid call to DICOMImageBlockDescriptor::UpdateImageDescribingProperties(). Need to " 714 "have initialized tag-cache!";
718 auto tagCache = m_TagCache.Lock();
720 if (tagCache.IsNull())
722 MITK_ERROR <<
"Invalid call to DICOMImageBlockDescriptor::UpdateImageDescribingProperties(). Need to " 723 "have initialized tag-cache!";
728 const DICOMImageFrameInfo::Pointer firstFrame = m_ImageFrameList.front();
729 const DICOMImageFrameInfo::Pointer lastFrame = m_ImageFrameList.back();
758 StringLookupTable sliceLocationForSlices;
759 StringLookupTable instanceNumberForSlices;
760 StringLookupTable SOPInstanceUIDForSlices;
761 StringLookupTable filenamesForSlices;
763 const DICOMTag tagSliceLocation( 0x0020, 0x1041 );
764 const DICOMTag tagInstanceNumber( 0x0020, 0x0013 );
765 const DICOMTag tagSOPInstanceNumber( 0x0008, 0x0018 );
767 std::unordered_map<std::string, DICOMCachedValueLookupTable> additionalTagResultList;
769 unsigned int slice(0);
772 for (
auto frameIter = m_ImageFrameList.begin(); frameIter != m_ImageFrameList.end();
773 ++slice, ++frameIter )
775 unsigned int zSlice = slice%framesPerTimeStep;
781 const std::string sliceLocation = tagCache->GetTagValue( *frameIter, tagSliceLocation ).value;
782 sliceLocationForSlices.SetTableValue( slice, sliceLocation );
784 const std::string instanceNumber = tagCache->GetTagValue( *frameIter, tagInstanceNumber ).value;
785 instanceNumberForSlices.SetTableValue( slice, instanceNumber );
787 const std::string sopInstanceUID = tagCache->GetTagValue( *frameIter, tagSOPInstanceNumber ).value;
788 SOPInstanceUIDForSlices.SetTableValue( slice, sopInstanceUID );
790 const std::string filename = ( *frameIter )->Filename;
791 filenamesForSlices.SetTableValue( slice, filename );
793 MITK_DEBUG <<
"Tag info for slice " << slice <<
": SL '" << sliceLocation <<
"' IN '" << instanceNumber
794 <<
"' SOP instance UID '" << sopInstanceUID <<
"'";
796 for (
const auto& tag : m_AdditionalTagMap)
799 for (
const auto& finding : findings)
804 DICOMCachedValueInfo
info{
static_cast<unsigned int>(timePoint), zSlice, finding.value };
805 additionalTagResultList[propKey].SetTableValue(slice,
info);
813 thisInstance->SetProperty(
"sliceLocationForSlices",
816 thisInstance->SetProperty(
"instanceNumberForSlices",
819 thisInstance->SetProperty(
"SOPInstanceUIDForSlices",
827 for (
auto iter = additionalTagResultList.cbegin(); iter != additionalTagResultList.cend(); ++iter )
829 thisInstance->SetProperty( iter->first, m_PropertyFunctor( iter->second ) );
830 thisInstance->m_FoundAdditionalTags.insert(m_FoundAdditionalTags.cend(),iter->first);
833 m_PropertiesOutOfDate =
false;
839 mitk::DICOMImageBlockDescriptor::GetPropertyForDICOMValues(
const DICOMCachedValueLookupTable& cacheLookupTable)
841 const auto& lookupTable = cacheLookupTable.GetLookupTable();
842 typedef std::pair<int, DICOMCachedValueInfo> PairType;
843 if ( std::adjacent_find(
844 lookupTable.cbegin(),
846 [](
const PairType& lhs,
const PairType& rhs ) {
return lhs.second.Value != rhs.second.Value; } )
847 == lookupTable.cend() )
853 StringLookupTable stringTable;
854 for (
auto element : lookupTable)
856 stringTable.SetTableValue(element.first, element.second.Value);
866 if ( functor !=
nullptr )
868 m_PropertyFunctor = functor;
873 const std::string &,
bool )
const 875 this->UpdateImageDescribingProperties();
876 return m_PropertyList->GetConstProperty(propertyKey);
881 this->UpdateImageDescribingProperties();
882 return m_PropertyList->GetPropertyKeys();
887 return std::vector<std::string>();
void GetDesiredMITKImagePixelSpacing(ScalarType &spacingXinMM, ScalarType &spacingYinMM) const
Describe the correct x/y pixel spacing of the mitk::Image (which some readers might need to adjust af...
static DICOMTagList GetTagsOfInterest()
const GantryTiltInformation GetTiltInformation() const
Describe the gantry tilt of the acquisition.
BaseProperty::ConstPointer GetConstProperty(const std::string &propertyKey, const std::string &contextName="", bool fallBackOnDefaultContext=true) const override
Get property by its key.
void Print(std::ostream &os, bool filenameDetails) const
Print information about this image block to given stream.
loader did not yet inspect any images, unknown fitness
void SetSpacing(const mitk::Vector3D &aSpacing, bool enforceSetSpacing=false)
Set the spacing (m_Spacing).
BaseProperty * GetProperty(const std::string &key) const
Key-value store describing aspects of the image to be loaded.
void SetIntProperty(const std::string &key, int value)
Convenience function around SetProperty()
void SetTiltInformation(const GantryTiltInformation &info)
Describe the gantry tilt of the acquisition.
bool DICOMStringToSpacing(const std::string &s, ScalarType &spacingX, ScalarType &spacingY)
std::vector< DICOMTag > DICOMTagList
void SetAdditionalTagsOfInterest(const AdditionalTagsMapType &tagMap)
Set a list of DICOMTagPaths that specifiy all DICOM-Tags that will be copied into the property of the...
Representation of a DICOM tag.
NO spacing information is present, we use (1,1) as default.
DICOMImageBlockDescriptor & operator=(const DICOMImageBlockDescriptor &other)
std::string GetSOPClassUIDAsName() const
SOP Class as human readable name (e.g. "CT Image Storage")
Image::Pointer GetMitkImage() const
the 3D mitk::Image that is loaded from the DICOM files of a DICOMImageFrameList
std::string ReaderImplementationLevelToString(const ReaderImplementationLevel &enumValue)
Convert mitk::ReaderImplementationLevel to a human readable string.
#define printProperty(label, property_name)
ReaderImplementationLevel GetReaderImplementationLevel() const
Reader's capability to appropriately load this set of frames.
int GetIntProperty(const std::string &key, int defaultValue) const
Convenience function around GetProperty()
Key-value list holding instances of BaseProperty.
#define printPropertyRange(label, property_name)
const DICOMImageFrameList & GetImageFrameList() const
List of frames that constitute the mitk::Image (DICOMImageFrames)
std::map< DICOMTagPath, std::string > AdditionalTagsMapType
#define storeTagValueRangeToProperty(tag_name, tag_g, tag_e)
static void info(const char *fmt,...)
void SetProperty(const std::string &propertyKey, BaseProperty *property, const std::string &contextName="", bool fallBackOnDefaultContext=false) override
Add new or change existent property.
std::function< mitk::BaseProperty::Pointer(const DICOMCachedValueLookupTable &) > TagLookupTableToPropertyFunctor
void SetImageFrameList(const DICOMImageFrameList &framelist)
List of frames that constitute the mitk::Image (DICOMImageFrames)
std::string GetSOPClassUID() const
SOP Class UID of this set of frames.
void SetMitkImage(Image::Pointer image)
The 3D mitk::Image that is loaded from the DICOM files of a DICOMImageFrameList.
The LevelWindow class Class to store level/window values.
MITKDICOMREADER_EXPORT std::string DICOMTagPathToPropertyName(const DICOMTagPath &tagPath)
std::vector< std::string > GetPropertyContextNames() const override
Query names of existing contexts.
void SetTagLookupTableToPropertyFunctor(TagLookupTableToPropertyFunctor)
Set a functor that defines how the slice-specific tag-values are stored in a Property.
ReaderImplementationLevel
Describes how well the reader is tested for a certain file type (see mitk::DICOMFileReader).
PixelSpacingInterpretation
How the mitk::Image spacing should be interpreted (see mitk::DICOMFileReader).
Abstract base class for properties.
void SetReaderImplementationLevel(const ReaderImplementationLevel &level)
Reader's capability to appropriately load this set of frames.
std::vector< DICOMImageFrameInfo::Pointer > DICOMImageFrameList
std::string PixelSpacingInterpretationToString(const PixelSpacingInterpretation &value)
Convert mitk::PixelSpacingInterpretation to a human readable string.
Image class for storing images.
Output descriptor for DICOMFileReader.
void SetTagCache(DICOMTagCache *privateCache)
std::vector< std::string > GetPropertyKeys(const std::string &contextName="", bool includeDefaultContext=false) const override
Query keys of existing properties.
mitk::Image::Pointer image
std::string GetPropertyAsString(const std::string &) const
Convenience function around GetProperty()
~DICOMImageBlockDescriptor() override
const mitk::Vector3D GetSpacing() const
Get the spacing (size of a pixel).
void SetProperty(const std::string &key, BaseProperty *value)
Key-value store describing aspects of the image to be loaded.
void SetFlag(const std::string &key, bool value)
Convenience function around SetProperty()
std::list< DICOMDatasetFinding > FindingsListType
int GetNumberOfTimeSteps() const
PixelSpacingInterpretation GetPixelSpacingInterpretation() const
Describe how the mitk::Image's pixel spacing should be interpreted.
#define storeTagValueToProperty(tag_name, tag_g, tag_e)
mitk::BaseGeometry * GetGeometry(int t=0) const
Return the geometry, which is a TimeGeometry, of the data as non-const pointer.
DICOMImageBlockDescriptor()
distances are mm at detector surface
int GetNumberOfFramesPerTimeStep() const
bool GetFlag(const std::string &key, bool defaultValue) const
Convenience function around GetProperty()
#define printBool(label, commands)
distances are mm within a patient