21 #include <itkGDCMSeriesFileNames.h> 23 #include <gdcmAttribute.h> 24 #include <gdcmDirectory.h> 25 #include <gdcmPixmapReader.h> 26 #include <gdcmRAWCodec.h> 27 #include <gdcmScanner.h> 28 #include <gdcmSorter.h> 29 #include <gdcmStringFilter.h> 43 return "PartlySupported";
49 return "<unknown value of enum ReaderImplementationLevel>";
62 return "Unknown spacing";
64 return "<unknown value of enum PixelSpacingInterpretation>";
70 static bool initialized =
false;
84 dictionary[
"0010|0010"] =
"dicom.patient.PatientsName";
85 dictionary[
"0010|0020"] =
"dicom.patient.PatientID";
86 dictionary[
"0010|0030"] =
"dicom.patient.PatientsBirthDate";
87 dictionary[
"0010|0040"] =
"dicom.patient.PatientsSex";
88 dictionary[
"0010|0032"] =
"dicom.patient.PatientsBirthTime";
89 dictionary[
"0010|1000"] =
"dicom.patient.OtherPatientIDs";
90 dictionary[
"0010|1001"] =
"dicom.patient.OtherPatientNames";
91 dictionary[
"0010|2160"] =
"dicom.patient.EthnicGroup";
92 dictionary[
"0010|4000"] =
"dicom.patient.PatientComments";
93 dictionary[
"0012|0062"] =
"dicom.patient.PatientIdentityRemoved";
94 dictionary[
"0012|0063"] =
"dicom.patient.DeIdentificationMethod";
97 dictionary[
"0020|000d"] =
"dicom.study.StudyInstanceUID";
98 dictionary[
"0008|0020"] =
"dicom.study.StudyDate";
99 dictionary[
"0008|0030"] =
"dicom.study.StudyTime";
100 dictionary[
"0008|0090"] =
"dicom.study.ReferringPhysiciansName";
101 dictionary[
"0020|0010"] =
"dicom.study.StudyID";
102 dictionary[
"0008|0050"] =
"dicom.study.AccessionNumber";
103 dictionary[
"0008|1030"] =
"dicom.study.StudyDescription";
104 dictionary[
"0008|1048"] =
"dicom.study.PhysiciansOfRecord";
105 dictionary[
"0008|1060"] =
"dicom.study.NameOfPhysicianReadingStudy";
108 dictionary[
"0008|0060"] =
"dicom.series.Modality";
109 dictionary[
"0020|000e"] =
"dicom.series.SeriesInstanceUID";
110 dictionary[
"0020|0011"] =
"dicom.series.SeriesNumber";
111 dictionary[
"0020|0060"] =
"dicom.series.Laterality";
112 dictionary[
"0008|0021"] =
"dicom.series.SeriesDate";
113 dictionary[
"0008|0031"] =
"dicom.series.SeriesTime";
114 dictionary[
"0008|1050"] =
"dicom.series.PerformingPhysiciansName";
115 dictionary[
"0018|1030"] =
"dicom.series.ProtocolName";
116 dictionary[
"0008|103e"] =
"dicom.series.SeriesDescription";
117 dictionary[
"0008|1070"] =
"dicom.series.OperatorsName";
118 dictionary[
"0018|0015"] =
"dicom.series.BodyPartExamined";
119 dictionary[
"0018|5100"] =
"dicom.series.PatientPosition";
120 dictionary[
"0028|0108"] =
"dicom.series.SmallestPixelValueInSeries";
121 dictionary[
"0028|0109"] =
"dicom.series.LargestPixelValueInSeries";
124 dictionary[
"0028|1050"] =
"dicom.voilut.WindowCenter";
125 dictionary[
"0028|1051"] =
"dicom.voilut.WindowWidth";
126 dictionary[
"0028|1055"] =
"dicom.voilut.WindowCenterAndWidthExplanation";
129 dictionary[
"0028|0004"] =
"dicom.pixel.PhotometricInterpretation";
130 dictionary[
"0028|0010"] =
"dicom.pixel.Rows";
131 dictionary[
"0028|0011"] =
"dicom.pixel.Columns";
134 dictionary[
"0028|0030"] =
"dicom.PixelSpacing";
135 dictionary[
"0018|1164"] =
"dicom.ImagerPixelSpacing";
138 dictionary[
"0008|0005"] =
"dicom.SpecificCharacterSet";
156 filenames, *node, sort, check_4d, correctTilt, callback, preLoadedImageBlock))
158 if (filenames.empty())
179 if (filenames.empty())
181 MITK_DEBUG <<
"Calling LoadDicomSeries with empty filename string container. Probably invalid application logic.";
186 DcmIoType::Pointer io = DcmIoType::New();
190 if (io->CanReadFile(filenames.front().c_str()))
192 io->SetFileName(filenames.front().c_str());
193 io->ReadImageInformation();
195 if (io->GetPixelType() == itk::ImageIOBase::SCALAR || io->GetPixelType() == itk::ImageIOBase::RGB)
197 LoadDicom(filenames, node, sort, check_4d, correctTilt, callback, preLoadedImageBlock);
206 catch (
const itk::MemoryAllocationError &e )
208 MITK_ERROR <<
"Out of memory. Cannot load DICOM series: " << e.what();
210 catch (
const std::exception &e )
212 MITK_ERROR <<
"Error encountered when loading DICOM series:" << e.what();
216 MITK_ERROR <<
"Unspecified error encountered when loading DICOM series.";
224 DcmIoType::Pointer io = DcmIoType::New();
226 return io->CanReadFile(filename.c_str());
231 DcmIoType::Pointer io = DcmIoType::New();
233 if (io->CanReadFile(filename.c_str()))
237 reader.SetFileName(filename.c_str());
239 gdcm::DataSet &data_set = reader.GetFile().GetDataSet();
240 gdcm::StringFilter sf;
241 sf.SetFile(reader.GetFile());
243 if (data_set.FindDataElement(gdcm::Tag(0x3001, 0x0010)) &&
244 (sf.ToString(gdcm::Tag(0x3001, 0x0010)) ==
"Philips3D "))
256 gdcm::PixmapReader reader;
257 reader.SetFileName(filename.c_str());
259 gdcm::DataSet &data_set = reader.GetFile().GetDataSet();
260 gdcm::StringFilter sf;
261 sf.SetFile(reader.GetFile());
263 gdcm::Attribute<0x0028, 0x0011> dimTagX;
264 gdcm::Attribute<0x3001, 0x1001, gdcm::VR::UL, gdcm::VM::VM1>
266 gdcm::Attribute<0x0028, 0x0010> dimTagY;
267 gdcm::Attribute<0x0028, 0x0008> dimTagT;
268 gdcm::Attribute<0x0018, 0x602c> spaceTagX;
269 gdcm::Attribute<0x0018, 0x602e> spaceTagY;
270 gdcm::Attribute<0x3001, 0x1003, gdcm::VR::FD, gdcm::VM::VM1> spaceTagZ;
271 gdcm::Attribute<0x0018, 0x6024> physicalTagX;
272 gdcm::Attribute<0x0018, 0x6026> physicalTagY;
273 gdcm::Attribute<0x3001, 0x1002, gdcm::VR::US, gdcm::VM::VM1> physicalTagZ;
275 dimTagX.Set(data_set);
276 dimTagY.Set(data_set);
277 dimTagZ.Set(data_set);
278 dimTagT.Set(data_set);
279 spaceTagX.Set(data_set);
280 spaceTagY.Set(data_set);
281 spaceTagZ.Set(data_set);
282 physicalTagX.Set(data_set);
283 physicalTagY.Set(data_set);
284 physicalTagZ.Set(data_set);
286 unsigned int dimX = dimTagX.GetValue(), dimY = dimTagY.GetValue(), dimZ = dimTagZ.GetValue(),
287 dimT = dimTagT.GetValue(), physicalX = physicalTagX.GetValue(), physicalY = physicalTagY.GetValue(),
288 physicalZ = physicalTagZ.GetValue();
290 float spaceX = spaceTagX.GetValue(), spaceY = spaceTagY.GetValue(), spaceZ = spaceTagZ.GetValue();
293 spaceX = spaceX * 10;
296 spaceY = spaceY * 10;
299 spaceZ = spaceZ * 10;
304 const gdcm::Pixmap &pixels = reader.GetPixmap();
305 gdcm::RAWCodec codec;
307 codec.SetPhotometricInterpretation(gdcm::PhotometricInterpretation::MONOCHROME2);
308 codec.SetPixelFormat(pixels.GetPixelFormat());
309 codec.SetPlanarConfiguration(0);
311 gdcm::DataElement out;
312 codec.Decode(data_set.GetDataElement(gdcm::Tag(0x7fe0, 0x0010)), out);
314 const gdcm::ByteValue *bv = out.GetByteValue();
315 const char *new_pixels = bv->GetPointer();
318 typedef itk::Image<unsigned char, 4>
320 ImageType::RegionType myRegion;
321 ImageType::SizeType mySize;
322 ImageType::IndexType myIndex;
323 ImageType::SpacingType mySpacing;
324 ImageType::Pointer imageItk = ImageType::New();
326 mySpacing[0] = spaceX;
327 mySpacing[1] = spaceY;
328 mySpacing[2] = spaceZ;
338 myRegion.SetSize(mySize);
339 myRegion.SetIndex(myIndex);
340 imageItk->SetSpacing(mySpacing);
341 imageItk->SetRegions(myRegion);
342 imageItk->Allocate();
343 imageItk->FillBuffer(0);
345 itk::ImageRegionIterator<ImageType> iterator(imageItk, imageItk->GetLargestPossibleRegion());
346 iterator.GoToBegin();
347 unsigned long pixCount = 0;
348 unsigned long planeSize = dimX * dimY;
349 unsigned long planeCount = 0;
350 unsigned long timeCount = 0;
351 unsigned long numberOfSlices = dimZ;
353 while (!iterator.IsAtEnd())
355 unsigned long adressedPixel =
357 (numberOfSlices - 1 - planeCount) * planeSize
358 + timeCount * numberOfSlices * planeSize;
360 iterator.Set(new_pixels[adressedPixel]);
364 if (pixCount == planeSize)
369 if (planeCount == numberOfSlices)
374 if (timeCount == dimT)
386 bool successful =
false;
388 std::istringstream spacingReader(s);
390 if (std::getline(spacingReader, spacing,
'\\'))
392 spacingY = atof(spacing.c_str());
394 if (std::getline(spacingReader, spacing,
'\\'))
396 spacingX = atof(spacing.c_str());
410 std::istringstream originReader(s);
411 std::string coordinate;
413 while (std::getline(originReader, coordinate,
'\\') && dim < 3)
415 p[dim++] = atof(coordinate.c_str());
421 MITK_ERROR <<
"Reader implementation made wrong assumption on tag (0020,0032). Found " << dim
422 <<
" instead of 3 values.";
440 std::istringstream orientationReader(s);
441 std::string coordinate;
443 while (std::getline(orientationReader, coordinate,
'\\') && dim < 6)
447 right[dim++] = atof(coordinate.c_str());
451 up[dim++ - 3] = atof(coordinate.c_str());
458 MITK_ERROR <<
"Reader implementation made wrong assumption on tag (0020,0037). Found " << dim
459 <<
" instead of 6 values.";
475 const StringContainer &files,
bool groupImagesWithGantryTilt,
const gdcm::Scanner::MappingType &tagValueMappings_)
484 auto &tagValueMappings =
const_cast<gdcm::Scanner::MappingType &
>(tagValueMappings_);
485 const gdcm::Tag tagImagePositionPatient(0x0020, 0x0032);
486 const gdcm::Tag tagImageOrientation(0x0020, 0x0037);
487 const gdcm::Tag tagGantryTilt(0x0018, 0x1120);
490 fromFirstToSecondOrigin.Fill(0.0);
491 bool fromFirstToSecondOriginInitialized(
false);
493 thisOrigin.Fill(0.0f);
495 lastOrigin.Fill(0.0f);
497 lastDifferentOrigin.Fill(0.0f);
499 bool lastOriginInitialized(
false);
501 MITK_DEBUG <<
"--------------------------------------------------------------------------------";
502 MITK_DEBUG <<
"Analyzing files for z-spacing assumption of ITK's ImageSeriesReader (group tilted: " 503 << groupImagesWithGantryTilt <<
")";
504 unsigned int fileIndex(0);
505 for (
auto fileIter = files.begin(); fileIter != files.end(); ++fileIter, ++fileIndex)
507 bool fileFitsIntoPattern(
false);
508 std::string thisOriginString;
510 thisOriginString =
ConstCharStarToString(tagValueMappings[fileIter->c_str()][tagImagePositionPatient]);
512 if (thisOriginString.empty())
518 <<
" for later analysis (no position information)";
526 remainingFiles.insert(remainingFiles.end(), fileIter + 1, files.end());
529 fileFitsIntoPattern =
false;
536 fileFitsIntoPattern =
false;
541 bool ignoredConversionError(-42);
544 MITK_DEBUG <<
" " << fileIndex <<
" " << *fileIter <<
" at " 546 <<
"(" << thisOrigin[0] <<
"," << thisOrigin[1] <<
"," << thisOrigin[2] <<
")";
548 if (lastOriginInitialized && (thisOrigin == lastOrigin))
551 <<
" for separate time step";
553 fileFitsIntoPattern =
false;
557 if (!fromFirstToSecondOriginInitialized &&
558 lastOriginInitialized)
560 fromFirstToSecondOrigin = thisOrigin - lastDifferentOrigin;
561 fromFirstToSecondOriginInitialized =
true;
577 tagValueMappings[fileIter->c_str()][tagImageOrientation], right, up, ignoredConversionError);
581 if (tiltInfo.IsSheared())
596 if (groupImagesWithGantryTilt && tiltInfo.IsRegularGantryTilt())
599 if (tagValueMappings[fileIter->c_str()].find(tagGantryTilt) != tagValueMappings[fileIter->c_str()].end())
603 double angle = atof(tiltStr.c_str());
605 MITK_DEBUG <<
"Comparing recorded tilt angle " << angle <<
" against calculated value " 606 << tiltInfo.GetTiltAngleInDegrees();
612 if (fabs(angle) - tiltInfo.GetTiltAngleInDegrees() > 0.25)
615 fileFitsIntoPattern =
false;
623 fileFitsIntoPattern =
true;
632 fileFitsIntoPattern =
true;
638 fileFitsIntoPattern =
false;
644 fileFitsIntoPattern =
true;
647 else if (fromFirstToSecondOriginInitialized)
649 Point3D assumedOrigin = lastDifferentOrigin + fromFirstToSecondOrigin;
651 Vector3D originError = assumedOrigin - thisOrigin;
652 double norm = originError.GetNorm();
653 double toleratedError(0.005);
655 if (norm > toleratedError)
657 MITK_DEBUG <<
" File does not fit into the inter-slice distance pattern (diff = " << norm <<
", allowed " 658 << toleratedError <<
").";
659 MITK_DEBUG <<
" Expected position (" << assumedOrigin[0] <<
"," << assumedOrigin[1] <<
"," 660 << assumedOrigin[2] <<
"), got position (" << thisOrigin[0] <<
"," << thisOrigin[1] <<
"," 661 << thisOrigin[2] <<
")";
662 MITK_DEBUG <<
" ==> Sort away " << *fileIter <<
" for later analysis";
670 fileFitsIntoPattern =
false;
675 fileFitsIntoPattern =
true;
681 fileFitsIntoPattern =
true;
686 if (!lastOriginInitialized || (fileFitsIntoPattern && (thisOrigin != lastOrigin)))
688 lastDifferentOrigin = thisOrigin;
691 lastOrigin = thisOrigin;
692 lastOriginInitialized =
true;
712 bool groupImagesWithGantryTilt,
715 return GetSeries(files,
true, groupImagesWithGantryTilt, restrictions);
720 bool groupImagesWithGantryTilt,
740 gdcm::Scanner scanner;
741 const gdcm::Tag tagSOPClassUID(0x0008, 0x0016);
742 scanner.AddTag(tagSOPClassUID);
744 const gdcm::Tag tagSeriesInstanceUID(0x0020, 0x000e);
745 scanner.AddTag(tagSeriesInstanceUID);
747 const gdcm::Tag tagImageOrientation(0x0020, 0x0037);
748 scanner.AddTag(tagImageOrientation);
750 const gdcm::Tag tagPixelSpacing(0x0028, 0x0030);
751 scanner.AddTag(tagPixelSpacing);
753 const gdcm::Tag tagImagerPixelSpacing(0x0018, 0x1164);
754 scanner.AddTag(tagImagerPixelSpacing);
756 const gdcm::Tag tagSliceThickness(0x0018, 0x0050);
757 scanner.AddTag(tagSliceThickness);
759 const gdcm::Tag tagNumberOfRows(0x0028, 0x0010);
760 scanner.AddTag(tagNumberOfRows);
762 const gdcm::Tag tagNumberOfColumns(0x0028, 0x0011);
763 scanner.AddTag(tagNumberOfColumns);
765 const gdcm::Tag tagGantryTilt(0x0018, 0x1120);
766 scanner.AddTag(tagGantryTilt);
768 const gdcm::Tag tagModality(0x0008, 0x0060);
769 scanner.AddTag(tagModality);
771 const gdcm::Tag tagNumberOfFrames(0x0028, 0x0008);
772 scanner.AddTag(tagNumberOfFrames);
776 const gdcm::Tag tagImagePositionPatient(0x0020, 0x0032);
777 scanner.AddTag(tagImagePositionPatient);
784 if (!scanner.Scan(files))
786 MITK_ERROR <<
"gdcm::Scanner failed when scanning " << files.size() <<
" input files.";
791 for (
auto fileIter = scanner.Begin(); fileIter != scanner.End(); ++fileIter)
793 if (std::string(fileIter->first).empty())
795 if (std::string(fileIter->first) == std::string(
"DICOMDIR"))
809 std::string moreUniqueSeriesId =
811 result[moreUniqueSeriesId].AddFile(fileIter->first);
816 for (FileNamesGrouping::const_iterator groupIter = result.begin(); groupIter != result.end(); ++groupIter)
820 result[groupIter->first] =
840 for (FileNamesGrouping::const_iterator groupIter = result.begin(); groupIter != result.end(); ++groupIter)
843 StringContainer filesStillToAnalyze = groupIter->second.GetFilenames();
844 std::string groupUID = groupIter->first;
845 unsigned int subgroup(0);
846 MITK_DEBUG <<
"Analyze group " << groupUID <<
" of " << groupIter->second.GetFilenames().size() <<
" files";
848 while (!filesStillToAnalyze.empty())
851 filesStillToAnalyze, groupImagesWithGantryTilt, scanner.GetMappings());
854 std::stringstream newGroupUID;
855 newGroupUID << groupUID <<
'.' << subgroup;
859 std::string firstFileInBlock = thisBlock.
GetFilenames().front();
861 thisBlock.SetImageBlockUID(newGroupUID.str());
862 thisBlock.SetSeriesInstanceUID(
865 thisBlock.SetSOPClassUID(
867 thisBlock.SetNumberOfFrames(
869 thisBlock.SetModality(
871 thisBlock.SetPixelSpacingInformation(
874 thisBlock.SetHasMultipleTimePoints(
false);
876 groupsOf3DBlocks[newGroupUID.str()] = thisBlock;
880 MITK_DEBUG <<
"Result: sorted 3D group with " << groupsOf3DBlocks[newGroupUID.str()].GetFilenames().size()
883 for (StringContainer::const_iterator siter = debugOutputFiles.begin(); siter != debugOutputFiles.end(); ++siter)
889 for (StringContainer::const_iterator siter = filesStillToAnalyze.begin(); siter != filesStillToAnalyze.end();
907 groupsOf3DPlusTBlocks.insert(groupsOf3DBlocks.begin(), groupsOf3DBlocks.end());
913 MITK_DEBUG <<
"================================================================================";
916 unsigned int numberOfFilesInPreviousBlock(0);
917 std::string previousBlockKey;
919 for (FileNamesGrouping::const_iterator block3DIter = groupsOf3DBlocks.begin();
920 block3DIter != groupsOf3DBlocks.end();
923 unsigned int numberOfFilesInThisBlock = block3DIter->second.GetFilenames().size();
924 std::string thisBlockKey = block3DIter->first;
926 if (numberOfFilesInPreviousBlock == 0)
928 numberOfFilesInPreviousBlock = numberOfFilesInThisBlock;
929 groupsOf3DPlusTBlocks[thisBlockKey] = block3DIter->second;
931 previousBlockKey = thisBlockKey;
935 bool identicalOrigins;
941 const char *origin_value = scanner.GetValue(groupsOf3DBlocks[thisBlockKey].GetFilenames().front().c_str(),
942 tagImagePositionPatient),
943 *previous_origin_value = scanner.GetValue(
944 groupsOf3DBlocks[previousBlockKey].GetFilenames().front().c_str(), tagImagePositionPatient),
945 *destination_value = scanner.GetValue(
946 groupsOf3DBlocks[thisBlockKey].GetFilenames().back().c_str(), tagImagePositionPatient),
947 *previous_destination_value = scanner.GetValue(
948 groupsOf3DBlocks[previousBlockKey].GetFilenames().back().c_str(), tagImagePositionPatient);
950 if (!origin_value || !previous_origin_value || !destination_value || !previous_destination_value)
952 identicalOrigins =
false;
964 ((thisOriginString == previousOriginString) && (thisDestinationString == previousDestinationString));
969 identicalOrigins =
false;
972 if (identicalOrigins && (numberOfFilesInPreviousBlock == numberOfFilesInThisBlock))
975 groupsOf3DPlusTBlocks[previousBlockKey].AddFiles(block3DIter->second.GetFilenames());
976 groupsOf3DPlusTBlocks[previousBlockKey].SetHasMultipleTimePoints(
true);
977 MITK_DEBUG <<
" --> group enhanced with another timestep";
982 groupsOf3DPlusTBlocks[thisBlockKey] = block3DIter->second;
983 int numberOfTimeSteps =
984 groupsOf3DPlusTBlocks[previousBlockKey].GetFilenames().size() / numberOfFilesInPreviousBlock;
985 MITK_DEBUG <<
" ==> group closed with " << numberOfTimeSteps <<
" time steps";
986 previousBlockKey = thisBlockKey;
987 MITK_DEBUG <<
" 3D+t group " << thisBlockKey <<
" started";
991 numberOfFilesInPreviousBlock = numberOfFilesInThisBlock;
996 MITK_DEBUG <<
"================================================================================";
998 for (FileNamesGrouping::const_iterator groupIter = groupsOf3DPlusTBlocks.begin();
999 groupIter != groupsOf3DPlusTBlocks.end();
1013 for (StringContainer::const_iterator siter = debugOutputFiles.begin(); siter != debugOutputFiles.end(); ++siter)
1016 MITK_DEBUG <<
"================================================================================";
1018 return groupsOf3DPlusTBlocks;
1022 bool groupImagesWithGantryTilt,
1025 gdcm::Directory directoryLister;
1026 directoryLister.Load(dir.c_str(),
false);
1027 return GetSeries(directoryLister.GetFilenames(), groupImagesWithGantryTilt, restrictions);
1031 const gdcm::Tag &tag)
1036 result =
IDifyTagValue(tagValueMap[tag] ? tagValueMap[tag] : std::string(
""));
1038 catch (
const std::exception & )
1049 const gdcm::Tag tagSeriesInstanceUID(0x0020, 0x000e);
1050 const gdcm::Tag tagImageOrientation(0x0020, 0x0037);
1051 const gdcm::Tag tagPixelSpacing(0x0028, 0x0030);
1052 const gdcm::Tag tagImagerPixelSpacing(0x0018, 0x1164);
1053 const gdcm::Tag tagSliceThickness(0x0018, 0x0050);
1054 const gdcm::Tag tagNumberOfRows(0x0028, 0x0010);
1055 const gdcm::Tag tagNumberOfColumns(0x0028, 0x0011);
1056 const gdcm::Tag tagNumberOfFrames(0x0028, 0x0008);
1058 const char *tagSeriesInstanceUid = tagValueMap[tagSeriesInstanceUID];
1059 if (!tagSeriesInstanceUid)
1061 mitkThrow() <<
"CreateMoreUniqueSeriesIdentifier() could not access series instance UID. Something is seriously " 1062 "wrong with this image, so stopping here.";
1064 std::string constructedID = tagSeriesInstanceUid;
1076 if (tagValueMap.find(tagImageOrientation) != tagValueMap.end())
1078 bool conversionError(
false);
1087 std::ostringstream ss;
1088 ss.setf(std::ios::fixed, std::ios::floatfield);
1090 ss << right[0] <<
"\\" << right[1] <<
"\\" << right[2] <<
"\\" << up[0] <<
"\\" << up[1] <<
"\\" << up[2];
1091 std::string simplifiedOrientationString(ss.str());
1093 constructedID +=
IDifyTagValue(simplifiedOrientationString);
1096 constructedID.resize(constructedID.length() - 1);
1098 return constructedID;
1103 std::string IDifiedValue(value);
1105 throw std::logic_error(
"IDifyTagValue() illegaly called with empty tag value");
1109 for (std::size_t i = 0; i < IDifiedValue.size(); i++)
1111 while (i < IDifiedValue.size() &&
1112 !(IDifiedValue[i] ==
'.' || (IDifiedValue[i] >=
'a' && IDifiedValue[i] <=
'z') ||
1113 (IDifiedValue[i] >=
'0' && IDifiedValue[i] <=
'9') ||
1114 (IDifiedValue[i] >=
'A' && IDifiedValue[i] <=
'Z')))
1116 IDifiedValue.erase(i, 1);
1120 IDifiedValue +=
".";
1121 return IDifiedValue;
1125 const std::string &series_uid,
1126 bool groupImagesWithGantryTilt,
1132 for (FileNamesGrouping::const_iterator idIter = allSeries.begin(); idIter != allSeries.end(); ++idIter)
1134 if (idIter->first.find(series_uid) == 0)
1136 return idIter->second.GetFilenames();
1140 return resultingFileList;
1159 gdcm::Sorter sorter;
1164 if (sorter.Sort(unsortedFilenames))
1166 return sorter.GetFilenames();
1170 MITK_WARN <<
"Sorting error. Leaving series unsorted.";
1171 return unsortedFilenames;
1174 catch (
const std::logic_error & )
1176 MITK_WARN <<
"Sorting error. Leaving series unsorted.";
1177 return unsortedFilenames;
1196 static const gdcm::Tag tagImagePositionPatient(0x0020, 0x0032);
1197 static const gdcm::Tag tagImageOrientation(0x0020, 0x0037);
1200 if (ds1.FindDataElement(tagImagePositionPatient) && ds1.FindDataElement(tagImageOrientation) &&
1201 ds2.FindDataElement(tagImagePositionPatient) && ds2.FindDataElement(tagImageOrientation))
1203 gdcm::Attribute<0x0020, 0x0032> image_pos1;
1204 gdcm::Attribute<0x0020, 0x0037> image_orientation1;
1206 image_pos1.Set(ds1);
1207 image_orientation1.Set(ds1);
1209 gdcm::Attribute<0x0020, 0x0032> image_pos2;
1210 gdcm::Attribute<0x0020, 0x0037> image_orientation2;
1212 image_pos2.Set(ds2);
1213 image_orientation2.Set(ds2);
1222 for (
unsigned int dim = 0; dim < 6; ++dim)
1224 if (fabs(image_orientation2[dim] - image_orientation1[dim]) > 0.0001)
1226 MITK_ERROR <<
"Dicom images have different orientations.";
1227 throw std::logic_error(
1228 "Dicom images have different orientations. Call GetSeries() first to separate images.");
1234 normal[0] = image_orientation1[1] * image_orientation1[5] - image_orientation1[2] * image_orientation1[4];
1235 normal[1] = image_orientation1[2] * image_orientation1[3] - image_orientation1[0] * image_orientation1[5];
1236 normal[2] = image_orientation1[0] * image_orientation1[4] - image_orientation1[1] * image_orientation1[3];
1238 double dist1 = 0.0, dist2 = 0.0;
1241 for (
unsigned char i = 0u; i < 3u; ++i)
1243 dist1 += normal[i] * image_pos1[i];
1244 dist2 += normal[i] * image_pos2[i];
1251 return dist1 < dist2;
1256 static const gdcm::Tag tagAcquisitionNumber(0x0020, 0x0012);
1257 if (ds1.FindDataElement(tagAcquisitionNumber) && ds2.FindDataElement(tagAcquisitionNumber))
1259 gdcm::Attribute<0x0020, 0x0012> acquisition_number1;
1260 gdcm::Attribute<0x0020, 0x0012> acquisition_number2;
1262 acquisition_number1.Set(ds1);
1263 acquisition_number2.Set(ds2);
1265 if (acquisition_number1 != acquisition_number2)
1267 return acquisition_number1 < acquisition_number2;
1272 static const gdcm::Tag tagAcquisitionTime(0x0008, 0x0032);
1273 if (ds1.FindDataElement(tagAcquisitionTime) && ds2.FindDataElement(tagAcquisitionTime))
1275 gdcm::Attribute<0x0008, 0x0032> acquisition_time1;
1276 gdcm::Attribute<0x0008, 0x0032> acquisition_time2;
1278 acquisition_time1.Set(ds1);
1279 acquisition_time2.Set(ds2);
1281 if (acquisition_time1 != acquisition_time2)
1283 return acquisition_time1 < acquisition_time2;
1288 static const gdcm::Tag tagTriggerTime(0x0018, 0x1060);
1289 if (ds1.FindDataElement(tagTriggerTime) && ds2.FindDataElement(tagTriggerTime))
1291 gdcm::Attribute<0x0018, 0x1060> trigger_time1;
1292 gdcm::Attribute<0x0018, 0x1060> trigger_time2;
1294 trigger_time1.Set(ds1);
1295 trigger_time2.Set(ds2);
1297 if (trigger_time1 != trigger_time2)
1299 return trigger_time1 < trigger_time2;
1313 static const gdcm::Tag tagSOPInstanceUID(0x0008, 0x0018);
1314 if (ds1.FindDataElement(tagSOPInstanceUID) && ds2.FindDataElement(tagSOPInstanceUID))
1317 <<
"Dicom images are missing attributes for a meaningful sorting, falling back to SOP instance UID comparison.";
1318 gdcm::Attribute<0x0008, 0x0018> SOPInstanceUID1;
1319 gdcm::Attribute<0x0008, 0x0018> SOPInstanceUID2;
1321 SOPInstanceUID1.Set(ds1);
1322 SOPInstanceUID2.Set(ds2);
1324 return SOPInstanceUID1 < SOPInstanceUID2;
1331 std::string error_message(
"Malformed DICOM images, which do not even contain a SOP Instance UID.");
1333 throw std::logic_error(error_message);
1339 std::stringstream configuration;
1340 configuration <<
"MITK_USE_GDCMIO: ";
1341 configuration <<
"true";
1342 configuration <<
"\n";
1344 configuration <<
"GDCM_VERSION: ";
1345 #ifdef GDCM_MAJOR_VERSION 1346 configuration << GDCM_VERSION;
1350 return configuration.str();
1354 const gdcm::Scanner::MappingType &tagValueMappings_,
1359 std::list<StringContainer> imageBlock;
1360 imageBlock.push_back(filenames);
1365 const gdcm::Scanner::MappingType &tagValueMappings_,
1378 auto &tagValueMappings =
const_cast<gdcm::Scanner::MappingType &
>(tagValueMappings_);
1381 const gdcm::Tag tagSliceLocation(0x0020, 0x1041);
1383 const gdcm::Tag tagInstanceNumber(0x0020, 0x0013);
1385 const gdcm::Tag tagSOPInstanceNumber(0x0008, 0x0018);
1386 unsigned int timeStep(0);
1388 std::string propertyKeySliceLocation =
"dicom.image.0020.1041";
1389 std::string propertyKeyInstanceNumber =
"dicom.image.0020.0013";
1390 std::string propertyKeySOPInstanceNumber =
"dicom.image.0008.0018";
1393 for (
auto i = imageBlock.begin(); i != imageBlock.end(); i++, timeStep++)
1396 unsigned int slice(0);
1397 for (
auto fIter = files.begin(); fIter != files.end(); ++fIter, ++slice)
1400 gdcm::Scanner::TagToValue tagValueMapForFile = tagValueMappings[fIter->c_str()];
1401 if (tagValueMapForFile.find(tagSliceLocation) != tagValueMapForFile.end())
1402 sliceLocationForSlices.
SetTableValue(slice, tagValueMapForFile[tagSliceLocation]);
1403 if (tagValueMapForFile.find(tagInstanceNumber) != tagValueMapForFile.end())
1404 instanceNumberForSlices.
SetTableValue(slice, tagValueMapForFile[tagInstanceNumber]);
1405 if (tagValueMapForFile.find(tagSOPInstanceNumber) != tagValueMapForFile.end())
1406 SOPInstanceNumberForSlices.
SetTableValue(slice, tagValueMapForFile[tagSOPInstanceNumber]);
1414 std::ostringstream postfix;
1415 postfix <<
".t" << timeStep;
1417 propertyKeySliceLocation.append(postfix.str());
1418 propertyKeyInstanceNumber.append(postfix.str());
1419 propertyKeySOPInstanceNumber.append(postfix.str());
1423 image->
SetProperty(propertyKeySOPInstanceNumber.c_str(),
1431 const itk::MetaDataDictionary &dict = io->GetMetaDataDictionary();
1434 auto dictIter = dict.Begin();
1435 while (dictIter != dict.End())
1439 if (itk::ExposeMetaData<std::string>(dict, dictIter->first, value))
1443 auto valuePosition = propertyLookup.find(dictIter->first);
1444 if (valuePosition != propertyLookup.end())
1446 std::string propertyKey = valuePosition->second;
1454 MITK_WARN <<
"Tag " << dictIter->first <<
" not read as string as expected. Ignoring...";
1462 "dicomseriesreader.ReaderImplementationLevelString",
1464 image->
SetProperty(
"dicomseriesreader.ReaderImplementationLevel",
1466 image->
SetProperty(
"dicomseriesreader.PixelSpacingInterpretationString",
1468 image->
SetProperty(
"dicomseriesreader.PixelSpacingInterpretation",
1485 imageBlockDescriptor.GetDesiredMITKImagePixelSpacing(desiredSpacingX, desiredSpacingY);
1487 MITK_DEBUG <<
"Loaded spacing: " << imageSpacingX <<
"/" << imageSpacingY;
1488 MITK_DEBUG <<
"Corrected spacing: " << desiredSpacingX <<
"/" << desiredSpacingY;
1490 imageSpacing[0] = desiredSpacingX;
1491 imageSpacing[1] = desiredSpacingY;
1504 std::locale previousCppLocale(std::cin.getloc());
1510 const gdcm::Tag tagImagePositionPatient(0x0020, 0x0032);
1511 const gdcm::Tag tagImageOrientation(0x0020, 0x0037);
1512 const gdcm::Tag tagSeriesInstanceUID(0x0020, 0x000e);
1513 const gdcm::Tag tagSOPClassUID(0x0008, 0x0016);
1514 const gdcm::Tag tagModality(0x0008, 0x0060);
1515 const gdcm::Tag tagPixelSpacing(0x0028, 0x0030);
1516 const gdcm::Tag tagImagerPixelSpacing(0x0018, 0x1164);
1517 const gdcm::Tag tagNumberOfFrames(0x0028, 0x0008);
1523 bool initialize_node =
false;
1531 initialize_node =
true;
1536 bool canLoadAs4D(
true);
1537 gdcm::Scanner scanner;
1541 auto &tagValueMappings =
const_cast<gdcm::Scanner::MappingType &
>(scanner.GetMappings());
1543 std::list<StringContainer> imageBlocks =
1545 unsigned int volume_count = imageBlocks.size();
1547 imageBlockDescriptor.SetSeriesInstanceUID(
1549 imageBlockDescriptor.SetSOPClassUID(
1551 imageBlockDescriptor.SetModality(
1553 imageBlockDescriptor.SetNumberOfFrames(
1555 imageBlockDescriptor.SetPixelSpacingInformation(
1563 if (!imageBlocks.empty() && imageBlocks.front().size() > 1 && correctTilt)
1568 std::string firstFilename(imageBlocks.front().front());
1570 std::string secondFilename(imageBlocks.front().back());
1572 std::string imagePosition1(
1574 std::string imageOrientation(
1576 std::string imagePosition2(
1579 bool ignoredConversionError(-42);
1594 correctTilt =
false;
1597 imageBlockDescriptor.SetHasGantryTiltCorrected(correctTilt);
1599 if (volume_count == 1 || !canLoadAs4D || !load4D)
1601 DcmIoType::Pointer io;
1603 imageBlocks.front(), correctTilt, tiltInfo, io, command, preLoadedImageBlock);
1605 imageBlockDescriptor.AddFiles(imageBlocks.front());
1606 imageBlockDescriptor.SetHasMultipleTimePoints(
false);
1611 initialize_node =
true;
1613 else if (volume_count > 1)
1615 imageBlockDescriptor.AddFiles(filenames);
1616 imageBlockDescriptor.SetHasMultipleTimePoints(
true);
1618 DcmIoType::Pointer io;
1620 imageBlocks, imageBlockDescriptor, correctTilt, tiltInfo, io, command, preLoadedImageBlock);
1622 initialize_node =
true;
1626 if (initialize_node)
1631 std::string patientName =
"NoName";
1632 if (node.
GetProperty(
"dicom.patient.PatientsName"))
1637 std::cin.imbue(previousCppLocale);
1640 MITK_DEBUG <<
"--------------------------------------------------------------------------------";
1649 << image->GetGeometry()->GetSpacing()[0] <<
"/" << image->GetGeometry()->GetSpacing()[0];
1652 MITK_DEBUG <<
"--------------------------------------------------------------------------------";
1654 catch (
const std::exception &e )
1657 std::cin.imbue(previousCppLocale);
1659 MITK_DEBUG <<
"Caught exception in DicomSeriesReader::LoadDicom";
1667 const gdcm::Tag tagImagePositionPatient(0x0020, 0x0032);
1668 scanner.AddTag(tagImagePositionPatient);
1670 const gdcm::Tag tagSeriesInstanceUID(0x0020, 0x000e);
1671 scanner.AddTag(tagSeriesInstanceUID);
1673 const gdcm::Tag tagImageOrientation(0x0020, 0x0037);
1674 scanner.AddTag(tagImageOrientation);
1676 const gdcm::Tag tagSliceLocation(0x0020, 0x1041);
1677 scanner.AddTag(tagSliceLocation);
1679 const gdcm::Tag tagInstanceNumber(0x0020, 0x0013);
1680 scanner.AddTag(tagInstanceNumber);
1682 const gdcm::Tag tagSOPInstanceNumber(0x0008, 0x0018);
1683 scanner.AddTag(tagSOPInstanceNumber);
1685 const gdcm::Tag tagPixelSpacing(0x0028, 0x0030);
1686 scanner.AddTag(tagPixelSpacing);
1688 const gdcm::Tag tagImagerPixelSpacing(0x0018, 0x1164);
1689 scanner.AddTag(tagImagerPixelSpacing);
1691 const gdcm::Tag tagModality(0x0008, 0x0060);
1692 scanner.AddTag(tagModality);
1694 const gdcm::Tag tagSOPClassUID(0x0008, 0x0016);
1695 scanner.AddTag(tagSOPClassUID);
1697 const gdcm::Tag tagNumberOfFrames(0x0028, 0x0008);
1698 scanner.AddTag(tagNumberOfFrames);
1700 scanner.Scan(filenames);
1705 const gdcm::Scanner::MappingType &tagValueMappings,
1709 std::list<StringContainer> imageBlocks;
1714 std::string firstPosition;
1715 unsigned int numberOfBlocks(0);
1717 static const gdcm::Tag tagImagePositionPatient(0x0020, 0x0032);
1718 const gdcm::Tag tagModality(0x0008, 0x0060);
1721 for (StringContainer::const_iterator fileIter = sorted_filenames.begin(); fileIter != sorted_filenames.end();
1724 gdcm::Scanner::TagToValue tagToValueMap = tagValueMappings.find(fileIter->c_str())->second;
1726 if (tagToValueMap.find(tagImagePositionPatient) == tagToValueMap.end())
1728 const std::string &modality = tagToValueMap.find(tagModality)->second;
1729 if (modality.compare(
"RTIMAGE ") == 0 || modality.compare(
"RTIMAGE") == 0)
1731 MITK_WARN <<
"Modality " << modality <<
" is not fully supported yet.";
1738 assert(presortedFilenames.size() == 1);
1744 std::string position = tagToValueMap.find(tagImagePositionPatient)->second;
1745 MITK_DEBUG <<
" " << *fileIter <<
" at " << position;
1746 if (firstPosition.empty())
1748 firstPosition = position;
1751 if (position == firstPosition)
1761 MITK_DEBUG <<
" ==> Assuming " << numberOfBlocks <<
" time steps";
1763 if (numberOfBlocks == 0)
1767 unsigned int numberOfExpectedSlices(0);
1768 for (
unsigned int block = 0; block < numberOfBlocks; ++block)
1772 for (StringContainer::const_iterator fileIter = sorted_filenames.begin() + block;
1773 fileIter != sorted_filenames.end();
1777 filesOfCurrentBlock.push_back(*fileIter);
1778 for (
unsigned int b = 0; b < numberOfBlocks; ++b)
1780 if (fileIter != sorted_filenames.end())
1785 imageBlocks.push_back(filesOfCurrentBlock);
1789 numberOfExpectedSlices = filesOfCurrentBlock.size();
1793 if (filesOfCurrentBlock.size() != numberOfExpectedSlices)
1796 <<
"DicomSeriesReader expected " << numberOfBlocks <<
" image blocks of " << numberOfExpectedSlices
1797 <<
" images each. Block " << block <<
" got " << filesOfCurrentBlock.size()
1798 <<
" instead. Cannot load this as 3D+t";
1800 canLoadAs4D =
false;
1811 DcmIoType::Pointer &io,
1815 io = DcmIoType::New();
1816 io->SetFileName(filenames.front().c_str());
1817 io->ReadImageInformation();
1819 if (io->GetPixelType() == itk::ImageIOBase::SCALAR)
1823 else if (io->GetPixelType() == itk::ImageIOBase::RGB)
1837 DcmIoType::Pointer &io,
1841 io = DcmIoType::New();
1842 io->SetFileName(imageBlocks.front().front().c_str());
1843 io->ReadImageInformation();
1845 if (io->GetPixelType() == itk::ImageIOBase::SCALAR)
1848 imageBlocks, imageBlockDescriptor, correctTilt, tiltInfo, io, command, preLoadedImageBlock);
1850 else if (io->GetPixelType() == itk::ImageIOBase::RGB)
1853 imageBlocks, imageBlockDescriptor, correctTilt, tiltInfo, io, command, preLoadedImageBlock);
PixelSpacingInterpretation
How the mitk::Image spacing should be interpreted.
mitk::BaseProperty * GetProperty(const char *propertyKey, const mitk::BaseRenderer *renderer=nullptr, bool fallBackOnDataProperties=true) const
Get the property (instance of BaseProperty) with key propertyKey from the PropertyList of the rendere...
distances are mm within a patient
StringContainer GetBlockFilenames()
Grouping result, all same origin-to-origin distance w/o gaps.
std::map< std::string, std::string > TagToPropertyMapType
Maps DICOM tags to MITK properties.
void AddFilesToUnsortedBlock(const StringContainer &filenames)
static itk::SmartPointer< Image > MultiplexLoadDICOMByITK4DScalar(std::list< StringContainer > &imageBlocks, ImageBlockDescriptor imageBlockDescriptor, bool correctTilt, const GantryTiltInformation &tiltInfo, DcmIoType::Pointer &io, CallbackCommand *command, itk::SmartPointer< Image > preLoadedImageBlock)
static bool DICOMStringToSpacing(const std::string &s, ScalarType &spacingX, ScalarType &spacingY)
Safely convert a string into pixel spacing x and y.
void SetSpacing(const mitk::Vector3D &aSpacing, bool enforceSetSpacing=false)
Set the spacing (m_Spacing).
PixelSpacingInterpretation GetPixelSpacingType() const
How the mitk::Image spacing can meaningfully be interpreted.
Return type of GetSeries, describes a logical group of files.
void SetTableValue(IdentifierType id, ValueType value)
static Point3D DICOMStringToPoint3D(const std::string &s, bool &successful)
Convert DICOM string describing a point to Point3D.
static void ScanForSliceInformation(const StringContainer &filenames, gdcm::Scanner &scanner)
Scan for slice image information.
distances are mm at detector surface
itk::Image< unsigned char, 3 > ImageType
static void FixSpacingInformation(Image *image, const ImageBlockDescriptor &imageBlockDescriptor)
void UndoPrematureGrouping()
Only meaningful for use by AnalyzeFileForITKImageSeriesReaderSpacingAssumption.
static std::string GetConfigurationString()
Provide combination of preprocessor defines that was active during compilation.
virtual void SetData(mitk::BaseData *baseData)
Set the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
std::vector< std::string > StringContainer
Lists of filenames.
static bool ReadPhilips3DDicom(const std::string &filename, itk::SmartPointer< Image > output_image)
Read a Philips3D ultrasound DICOM file and put into an mitk::Image.
static DataNode::Pointer LoadDicomSeries(const StringContainer &filenames, bool sort=true, bool load4D=true, bool correctGantryTilt=true, UpdateCallBackMethod callback=nullptr, itk::SmartPointer< Image > preLoadedImageBlock=nullptr)
DataCollection - Class to facilitate loading/accessing structured data.
void ConcatenatePropertyList(PropertyList *pList, bool replace=false)
Set a property object in the list/map by reference.
std::string GetSOPClassUIDAsString() const
SOP Class UID as readable string (Computed Tomography Image Storage, Secondary Capture Image Storage...
static itk::SmartPointer< Image > MultiplexLoadDICOMByITKRGBPixel(const StringContainer &, bool correctTilt, const GantryTiltInformation &tiltInfo, DcmIoType::Pointer &io, CallbackCommand *command, itk::SmartPointer< Image > preLoadedImageBlock)
void(* UpdateCallBackMethod)(float)
Interface for the progress callback.
StringContainer GetFilenames() const
List of files in this group.
StringContainer GetUnsortedFilenames()
Remaining files, which could not be grouped.
static std::string CreateSeriesIdentifierPart(gdcm::Scanner::TagToValue &tagValueMap, const gdcm::Tag &tag)
Helper for CreateMoreUniqueSeriesIdentifier.
static std::string ReaderImplementationLevelToString(const ReaderImplementationLevel &enumValue)
static itk::SmartPointer< Image > MultiplexLoadDICOMByITK4DRGBPixel(std::list< StringContainer > &imageBlocks, ImageBlockDescriptor imageBlockDescriptor, bool correctTilt, const GantryTiltInformation &tiltInfo, DcmIoType::Pointer &io, CallbackCommand *command, itk::SmartPointer< Image > preLoadedImageBlock)
static std::string ConstCharStarToString(const char *s)
Safely convert const char* to std::string.
loader code is implemented but not accompanied by tests
void SetProperty(const std::string &propertyKey, BaseProperty *property, const std::string &contextName="", bool fallBackOnDefaultContext=false) override
Add new or change existent property.
std::string GetSeriesInstanceUID() const
The Series Instance UID.
static std::string PixelSpacingInterpretationToString(const PixelSpacingInterpretation &enumValue)
static std::string IDifyTagValue(const std::string &value)
Helper for CreateMoreUniqueSeriesIdentifier.
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
virtual std::string GetValueAsString() const
static void LoadDicom(const StringContainer &filenames, DataNode &node, bool sort, bool check_4d, bool correctTilt, UpdateCallBackMethod callback, itk::SmartPointer< Image > preLoadedImageBlock)
Performs actual loading of a series and creates an image having the specified pixel type...
Convenience class to temporarily change the current locale.
static std::list< StringContainer > SortIntoBlocksFor3DplusT(const StringContainer &presortedFilenames, const gdcm::Scanner::MappingType &tagValueMappings_, bool sort, bool &canLoadAs4D)
Sort files into time step blocks of a 3D+t image.
ReaderImplementationLevel GetReaderImplementationLevel() const
Confidence of the reader that this block can be read successfully.
static FileNamesGrouping GetSeries(const std::string &dir, bool groupImagesWithGantryTilt, const StringContainer &restrictions=StringContainer())
see other GetSeries().
static void DICOMStringToOrientationVectors(const std::string &s, Vector3D &right, Vector3D &up, bool &successful)
Convert DICOM string describing a point two Vector3D.
void AddFileToSortedBlock(const std::string &filename)
Meant for internal use by AnalyzeFileForITKImageSeriesReaderSpacingAssumption only.
bool HasMultipleTimePoints() const
3D+t or not
Image class for storing images.
virtual void SetName(const char *name)
Extra convenience access method to set the name of an object.
bool ContainsGantryTilt()
Wheter or not the grouped result contain a gantry tilt.
Progress callback for DicomSeriesReader.
std::string GetModality() const
Series Modality (CT, MR, etc.)
mitk::Image::Pointer image
static bool IsPhilips3DDicom(const std::string &filename)
Checks if a specific file is a Philips3D ultrasound DICOM file.
static itk::SmartPointer< Image > MultiplexLoadDICOMByITKScalar(const StringContainer &, bool correctTilt, const GantryTiltInformation &tiltInfo, DcmIoType::Pointer &io, CallbackCommand *command, itk::SmartPointer< Image > preLoadedImageBlock)
static bool IsDicom(const std::string &filename)
Checks if a specific file contains DICOM data.
loader code and tests are established
std::string GetImageBlockUID() const
A unique ID describing this bloc (enhanced Series Instance UID).
mitk::PropertyList * GetPropertyList(const mitk::BaseRenderer *renderer=nullptr) const
Get the PropertyList of the renderer. If renderer is nullptr, the BaseRenderer-independent PropertyLi...
Return type of DicomSeriesReader::AnalyzeFileForITKImageSeriesReaderSpacingAssumption.
void CastToMitkImage(const itk::SmartPointer< ItkOutputImageType > &itkimage, itk::SmartPointer< mitk::Image > &mitkoutputimage)
Cast an itk::Image (with a specific type) to an mitk::Image.
const mitk::Vector3D GetSpacing() const
Get the spacing (size of a pixel).
static void CopyMetaDataToImageProperties(StringContainer filenames, const gdcm::Scanner::MappingType &tagValueMappings_, DcmIoType *io, const ImageBlockDescriptor &blockInfo, Image *image)
Copy information about files and DICOM tags from ITK's MetaDataDictionary and from the list of input ...
static itk::SmartPointer< Image > MultiplexLoadDICOMByITK4D(std::list< StringContainer > &imageBlocks, ImageBlockDescriptor imageBlockDescriptor, bool correctTilt, const GantryTiltInformation &tiltInfo, DcmIoType::Pointer &io, CallbackCommand *command, itk::SmartPointer< Image > preLoadedImageBlock)
void FlagGantryTilt()
Meant for internal use by AnalyzeFileForITKImageSeriesReaderSpacingAssumption only.
MITKCORE_EXPORT const ScalarType eps
static const TagToPropertyMapType & GetDICOMTagsToMITKPropertyMap()
Map between DICOM tags and MITK properties.
void AddFileToUnsortedBlock(const std::string &filename)
Meant for internal use by AnalyzeFileForITKImageSeriesReaderSpacingAssumption only.
std::map< std::string, ImageBlockDescriptor > FileNamesGrouping
bool IsMultiFrameImage() const
Multi-frame image(s) or not.
mitk::BaseGeometry * GetGeometry(int t=0) const
Return the geometry, which is a TimeGeometry, of the data as non-const pointer.
itk::GDCMImageIO DcmIoType
static std::string CreateMoreUniqueSeriesIdentifier(gdcm::Scanner::TagToValue &tagValueMap)
Construct a UID that takes into account sorting criteria from GetSeries().
static itk::SmartPointer< Image > MultiplexLoadDICOMByITK(const StringContainer &, bool correctTilt, const GantryTiltInformation &tiltInfo, DcmIoType::Pointer &io, CallbackCommand *command, itk::SmartPointer< Image > preLoadedImageBlock)
static StringContainer SortSeriesSlices(const StringContainer &unsortedFilenames)
Sort a set of file names in an order that is meaningful for loading them into an mitk::Image.
ReaderImplementationLevel
Describes how well the reader is tested for a certain file type.
static bool GdcmSortFunction(const gdcm::DataSet &ds1, const gdcm::DataSet &ds2)
Defines spatial sorting for sorting by GDCM 2.
Class for nodes of the DataTree.
bool HasGantryTiltCorrected() const
Whether or not the block contains a gantry tilt which will be "corrected" during loading.
static SliceGroupingAnalysisResult AnalyzeFileForITKImageSeriesReaderSpacingAssumption(const StringContainer &files, bool groupsOfSimilarImages, const gdcm::Scanner::MappingType &tagValueMappings_)
Ensure an equal z-spacing for a group of files.