26 return m_GroupedFiles;
33 return m_UnsortedFiles;
40 return m_TiltInfo.IsRegularGantryTilt();
47 m_GroupedFiles.push_back( dataset );
54 m_UnsortedFiles.push_back( dataset );
61 m_UnsortedFiles.insert( m_UnsortedFiles.end(), datasets.begin(), datasets.end() );
68 m_FirstFilenameOfBlock = filename;
75 return m_FirstFilenameOfBlock;
82 m_LastFilenameOfBlock = filename;
89 return m_LastFilenameOfBlock;
97 m_TiltInfo = tiltInfo;
111 assert( !m_GroupedFiles.empty() );
112 m_UnsortedFiles.insert( m_UnsortedFiles.begin(), m_GroupedFiles.back() );
113 m_GroupedFiles.pop_back();
148 if (
const auto* otherSelf = dynamic_cast<const EquiDistantBlocksSorter*>(&other))
165 std::stringstream ts;
175 os << indent <<
"Sort into blocks of equidistant, well-aligned (tolerance " 176 << ts.str() <<
") slices " 232 tags.push_back(
DICOMTag(0x0020, 0x0032) );
233 tags.push_back(
DICOMTag(0x0020, 0x0037) );
234 tags.push_back(
DICOMTag(0x0018, 0x1120) );
245 typedef std::list<DICOMDatasetList> OutputListType;
246 OutputListType outputs;
250 while (!remainingInput.empty())
254 #ifdef MBILOG_ENABLE_DEBUG 257 MITK_DEBUG <<
"Result: sorted 3D group with " << inBlock.size() <<
" files";
258 for (DICOMDatasetList::const_iterator diter = inBlock.cbegin(); diter != inBlock.cend(); ++diter)
259 MITK_DEBUG <<
" IN " << (*diter)->GetFilenameIfAvailable();
260 for (DICOMDatasetList::const_iterator diter = laterBlock.cbegin(); diter != laterBlock.cend(); ++diter)
261 MITK_DEBUG <<
" OUT " << (*diter)->GetFilenameIfAvailable();
262 #endif // MBILOG_ENABLE_DEBUG 269 unsigned int numberOfOutputs = outputs.size();
272 unsigned int outputIndex(0);
273 for (
auto oIter = outputs.cbegin();
274 oIter != outputs.cend();
275 ++outputIndex, ++oIter)
290 MITK_WARN <<
"Call SetToleratedOriginOffsetToAdaptive() only with positive numbers between 0.0 and 1.0, read documentation!";
295 MITK_WARN <<
"EquiDistantBlocksSorter is now accepting large errors, take care of measurements, they could appear at unprecise locations!";
307 MITK_WARN <<
"Negative tolerance set to SetToleratedOriginOffset()!";
330 return s ? std::string(s) : std::string();
337 bool groupImagesWithGantryTilt)
346 Vector3D fromFirstToSecondOrigin; fromFirstToSecondOrigin.Fill(0.0);
347 bool fromFirstToSecondOriginInitialized(
false);
349 thisOrigin.Fill(0.0f);
351 lastOrigin.Fill(0.0f);
353 lastDifferentOrigin.Fill(0.0f);
355 bool lastOriginInitialized(
false);
357 MITK_DEBUG <<
"--------------------------------------------------------------------------------";
358 MITK_DEBUG <<
"Analyzing " << datasets.size() <<
" files for z-spacing assumption of ITK's ImageSeriesReader (group tilted: " << groupImagesWithGantryTilt <<
")";
359 unsigned int fileIndex(0);
360 double toleratedOriginError(0.005);
361 for (
auto dsIter = datasets.cbegin();
362 dsIter != datasets.cend();
363 ++dsIter, ++fileIndex)
365 bool fileFitsIntoPattern(
false);
366 std::string thisOriginString;
368 thisOriginString = (*dsIter)->GetTagValueAsString(tagImagePositionPatient).value;
370 if (thisOriginString.empty())
374 MITK_DEBUG <<
" ==> Sort away " << *dsIter <<
" for later analysis (no position information)";
382 remainingFiles.insert( remainingFiles.end(), dsIter+1, datasets.end() );
385 fileFitsIntoPattern =
false;
392 fileFitsIntoPattern =
false;
397 bool ignoredConversionError(-42);
400 MITK_DEBUG <<
" " << fileIndex <<
" " << (*dsIter)->GetFilenameIfAvailable()
402 <<
"(" << thisOrigin[0] <<
"," << thisOrigin[1] <<
"," << thisOrigin[2] <<
")";
404 if ( lastOriginInitialized && (thisOrigin == lastOrigin) )
406 MITK_DEBUG <<
" ==> Sort away " << *dsIter <<
" for separate time step";
408 fileFitsIntoPattern =
false;
412 if (!fromFirstToSecondOriginInitialized && lastOriginInitialized)
414 fromFirstToSecondOrigin = thisOrigin - lastDifferentOrigin;
415 fromFirstToSecondOriginInitialized =
true;
420 MITK_DEBUG <<
"Distance of two slices: " << fromFirstToSecondOrigin.GetNorm() <<
"mm";
421 toleratedOriginError =
422 fromFirstToSecondOrigin.GetNorm() * 0.3;
429 MITK_DEBUG <<
"Accepting errors in actual versus expected origin up to " << toleratedOriginError <<
"mm";
442 std::string orientationValue = (*dsIter)->GetTagValueAsString( tagImageOrientation ).value;
460 assert(!datasets.empty());
466 fileFitsIntoPattern =
true;
471 fileFitsIntoPattern =
false;
477 fileFitsIntoPattern =
true;
480 else if (fromFirstToSecondOriginInitialized)
482 Point3D assumedOrigin = lastDifferentOrigin + fromFirstToSecondOrigin;
484 Vector3D originError = assumedOrigin - thisOrigin;
485 double norm = originError.GetNorm();
487 if (norm > toleratedOriginError)
489 MITK_DEBUG <<
" File does not fit into the inter-slice distance pattern (diff = " 490 << norm <<
", allowed " 491 << toleratedOriginError <<
").";
492 MITK_DEBUG <<
" Expected position (" << assumedOrigin[0] <<
"," 493 << assumedOrigin[1] <<
"," 494 << assumedOrigin[2] <<
"), got position (" 495 << thisOrigin[0] <<
"," 496 << thisOrigin[1] <<
"," 497 << thisOrigin[2] <<
")";
498 MITK_DEBUG <<
" ==> Sort away " << *dsIter <<
" for later analysis";
506 fileFitsIntoPattern =
false;
511 fileFitsIntoPattern =
true;
517 fileFitsIntoPattern =
true;
522 if ( !lastOriginInitialized || ( fileFitsIntoPattern && (thisOrigin != lastOrigin) ) )
524 lastDifferentOrigin = thisOrigin;
527 lastOrigin = thisOrigin;
528 lastOriginInitialized =
true;
555 unsigned int numberOfSlicesApart = datasets.size() - 1;
EquiDistantBlocksSorter()
SliceGroupingAnalysisResult AnalyzeFileForITKImageSeriesReaderSpacingAssumption(const DICOMDatasetList &files, bool groupsOfSimilarImages)
Ensure an equal z-spacing for a group of files.
bool ContainsGantryTilt()
Wheter or not the grouped result contain a gantry tilt.
EquiDistantBlocksSorter & operator=(const EquiDistantBlocksSorter &other)
bool m_ToleratedOriginOffsetIsAbsolute
void SetLastFilenameOfBlock(const std::string &filename)
void SetToleratedOriginOffsetToAdaptive(double fractionOfInterSliceDistanct=0.3)
See class description and SetToleratedOriginOffset().
DICOMDatasetList GetUnsortedDatasets()
Remaining files, which could not be grouped.
ResultsList m_SliceGroupingResults
std::string GetLastFilenameOfBlock() const
bool GetAcceptTilt() const
The sorting/splitting building-block of DICOMITKSeriesGDCMReader.
void Sort() override
Delegates work to AnalyzeFileForITKImageSeriesReaderSpacingAssumption(). AnalyzeFileForITKImageSeries...
void SetAcceptTilt(bool accept)
Whether or not to accept images from a tilted acquisition in a single output group.
Split inputs into blocks of equidistant slices (for use in DICOMITKSeriesGDCMReader).
std::vector< DICOMTag > DICOMTagList
void DICOMStringToOrientationVectors(const std::string &s, Vector3D &right, Vector3D &up, bool &successful)
Convert DICOM string describing a point two Vector3D.
Representation of a DICOM tag.
void AddFilesToUnsortedBlock(const DICOMDatasetList &datasets)
DICOMTagList GetTagsOfInterest() override
Return the tags of interest (to facilitate scanning)
bool IsToleratedOriginOffsetAbsolute() const
void SetNumberOfOutputs(unsigned int numberOfOutputs)
void SetAcceptTwoSlicesGroups(bool accept)
std::string ConstCharStarToString(const char *s)
Safely convert const char* to std::string.
const DICOMDatasetList & GetInput() const
Input for sorting.
Interface to datasets that is presented to sorting classes such as DICOMDatasetSorter.
Return type of AnalyzeFileForITKImageSeriesReaderSpacingAssumption().
const GantryTiltInformation & GetTiltInfo() const
Detailed description of gantry tilt.
DICOMDatasetList GetBlockDatasets()
Grouping result, all same origin-to-origin distance w/o gaps.
virtual DICOMDatasetFinding GetTagValueAsString(const DICOMTag &tag) const =0
Return a DICOMDatasetFinding instance of the tag. The return containes (if valid) the raw value of th...
void AddFileToSortedBlock(DICOMDatasetAccess *dataset)
Meant for internal use by AnalyzeFileForITKImageSeriesReaderSpacingAssumption only.
~EquiDistantBlocksSorter() override
std::string GetFirstFilenameOfBlock() const
bool m_AcceptTwoSlicesGroups
double m_ToleratedOriginOffset
MITKCORE_EXPORT const ScalarType eps
double GetToleratedOriginOffset() const
SliceGroupingAnalysisResult()
void SetFirstFilenameOfBlock(const std::string &filename)
Point3D DICOMStringToPoint3D(const std::string &s, bool &successful)
Convert DICOM string describing a point to Point3D.
void SetOutput(unsigned int index, const DICOMDatasetList &output)
bool GetAcceptTwoSlicesGroups() const
DICOMDatasetSorter & operator=(const DICOMDatasetSorter &other)
void UndoPrematureGrouping()
Only meaningful for use by AnalyzeFileForITKImageSeriesReaderSpacingAssumption.
std::vector< DICOMDatasetAccess * > DICOMDatasetList
bool operator==(const DICOMDatasetSorter &other) const override
void SetToleratedOriginOffset(double millimeters=0.005)
See class description and SetToleratedOriginOffsetToAdaptive().
void PrintConfiguration(std::ostream &os, const std::string &indent="") const override
Print configuration details into stream.
void FlagGantryTilt(const GantryTiltInformation &tiltInfo)
Meant for internal use by AnalyzeFileForITKImageSeriesReaderSpacingAssumption only.
void AddFileToUnsortedBlock(DICOMDatasetAccess *dataset)
Meant for internal use by AnalyzeFileForITKImageSeriesReaderSpacingAssumption only.