28 return m_GroupedFiles;
35 return m_UnsortedFiles;
42 return m_TiltInfo.IsRegularGantryTilt();
49 m_GroupedFiles.push_back( dataset );
56 m_UnsortedFiles.push_back( dataset );
63 m_UnsortedFiles.insert( m_UnsortedFiles.end(), datasets.begin(), datasets.end() );
77 return m_FirstFilenameOfBlock;
91 return m_LastFilenameOfBlock;
99 m_TiltInfo = tiltInfo;
113 assert( !m_GroupedFiles.empty() );
114 m_UnsortedFiles.insert( m_UnsortedFiles.begin(), m_GroupedFiles.back() );
115 m_GroupedFiles.pop_back();
125 ,m_ToleratedOriginOffset(0.3)
126 ,m_ToleratedOriginOffsetIsAbsolute(false)
127 ,m_AcceptTwoSlicesGroups(true)
134 ,m_AcceptTilt(other.m_AcceptTilt)
135 ,m_ToleratedOriginOffset(other.m_ToleratedOriginOffset)
136 ,m_ToleratedOriginOffsetIsAbsolute(other.m_ToleratedOriginOffsetIsAbsolute)
137 ,m_AcceptTwoSlicesGroups(other.m_AcceptTwoSlicesGroups)
152 return this->m_AcceptTilt == otherSelf->m_AcceptTilt
153 && this->m_ToleratedOriginOffsetIsAbsolute == otherSelf->m_ToleratedOriginOffsetIsAbsolute
154 && this->m_AcceptTwoSlicesGroups == otherSelf->m_AcceptTwoSlicesGroups
155 && (fabs(this->m_ToleratedOriginOffset - otherSelf->m_ToleratedOriginOffset) <
eps);
167 std::stringstream ts;
168 if (!m_ToleratedOriginOffsetIsAbsolute)
174 ts << m_ToleratedOriginOffset <<
"mm";
177 os << indent <<
"Sort into blocks of equidistant, well-aligned (tolerance "
178 << ts.str() <<
") slices "
179 << (m_AcceptTilt ?
"(accepting a gantry tilt)" :
"")
188 m_AcceptTilt = accept;
203 m_AcceptTwoSlicesGroups = accept;
210 return m_AcceptTwoSlicesGroups;
234 tags.push_back(
DICOMTag(0x0020, 0x0032) );
235 tags.push_back(
DICOMTag(0x0020, 0x0037) );
236 tags.push_back(
DICOMTag(0x0018, 0x1120) );
247 typedef std::list<DICOMDatasetList> OutputListType;
248 OutputListType outputs;
250 m_SliceGroupingResults.clear();
252 while (!remainingInput.empty())
254 SliceGroupingAnalysisResult regularBlock = this->AnalyzeFileForITKImageSeriesReaderSpacingAssumption( remainingInput, m_AcceptTilt );
256 #ifdef MBILOG_ENABLE_DEBUG
259 MITK_DEBUG <<
"Result: sorted 3D group with " << inBlock.size() <<
" files";
260 for (DICOMDatasetList::const_iterator diter = inBlock.cbegin(); diter != inBlock.cend(); ++diter)
261 MITK_DEBUG <<
" IN " << (*diter)->GetFilenameIfAvailable();
262 for (DICOMDatasetList::const_iterator diter = laterBlock.cbegin(); diter != laterBlock.cend(); ++diter)
263 MITK_DEBUG <<
" OUT " << (*diter)->GetFilenameIfAvailable();
264 #endif // MBILOG_ENABLE_DEBUG
267 m_SliceGroupingResults.push_back( regularBlock );
271 unsigned int numberOfOutputs = outputs.size();
272 this->SetNumberOfOutputs(numberOfOutputs);
274 unsigned int outputIndex(0);
275 for (
auto oIter = outputs.cbegin();
276 oIter != outputs.cend();
277 ++outputIndex, ++oIter)
279 this->SetOutput(outputIndex, *oIter);
287 m_ToleratedOriginOffset = fractionOfInterSliceDistance;
288 m_ToleratedOriginOffsetIsAbsolute =
false;
290 if (m_ToleratedOriginOffset < 0.0)
292 MITK_WARN <<
"Call SetToleratedOriginOffsetToAdaptive() only with positive numbers between 0.0 and 1.0, read documentation!";
295 if (m_ToleratedOriginOffset > 0.5)
297 MITK_WARN <<
"EquiDistantBlocksSorter is now accepting large errors, take care of measurements, they could appear at unprecise locations!";
305 m_ToleratedOriginOffset = millimeters;
306 m_ToleratedOriginOffsetIsAbsolute =
true;
307 if (m_ToleratedOriginOffset < 0.0)
309 MITK_WARN <<
"Negative tolerance set to SetToleratedOriginOffset()!";
317 return m_ToleratedOriginOffset;
324 return m_ToleratedOriginOffsetIsAbsolute;
332 return s ? std::string(s) : std::string();
339 bool groupImagesWithGantryTilt)
349 Vector3D fromFirstToSecondOrigin; fromFirstToSecondOrigin.Fill(0.0);
350 bool fromFirstToSecondOriginInitialized(
false);
352 thisOrigin.Fill(0.0f);
354 lastOrigin.Fill(0.0f);
356 lastDifferentOrigin.Fill(0.0f);
358 bool lastOriginInitialized(
false);
360 MITK_DEBUG <<
"--------------------------------------------------------------------------------";
361 MITK_DEBUG <<
"Analyzing " << datasets.size() <<
" files for z-spacing assumption of ITK's ImageSeriesReader (group tilted: " << groupImagesWithGantryTilt <<
")";
362 unsigned int fileIndex(0);
363 double toleratedOriginError(0.005);
364 for (
auto dsIter = datasets.cbegin();
365 dsIter != datasets.cend();
366 ++dsIter, ++fileIndex)
368 bool fileFitsIntoPattern(
false);
369 std::string thisOriginString;
371 thisOriginString = (*dsIter)->GetTagValueAsString(tagImagePositionPatient).value;
373 if (thisOriginString.empty())
377 MITK_DEBUG <<
" ==> Sort away " << *dsIter <<
" for later analysis (no position information)";
385 remainingFiles.insert( remainingFiles.end(), dsIter+1, datasets.end() );
388 fileFitsIntoPattern =
false;
395 fileFitsIntoPattern =
false;
400 bool ignoredConversionError(-42);
403 MITK_DEBUG <<
" " << fileIndex <<
" " << (*dsIter)->GetFilenameIfAvailable()
405 <<
"(" << thisOrigin[0] <<
"," << thisOrigin[1] <<
"," << thisOrigin[2] <<
")";
407 if ( lastOriginInitialized && (thisOrigin == lastOrigin) )
409 MITK_DEBUG <<
" ==> Sort away " << *dsIter <<
" for separate time step";
411 fileFitsIntoPattern =
false;
415 if (!fromFirstToSecondOriginInitialized && lastOriginInitialized)
417 fromFirstToSecondOrigin = thisOrigin - lastDifferentOrigin;
418 fromFirstToSecondOriginInitialized =
true;
421 if (!m_ToleratedOriginOffsetIsAbsolute)
423 MITK_DEBUG <<
"Distance of two slices: " << fromFirstToSecondOrigin.GetNorm() <<
"mm";
424 toleratedOriginError =
425 fromFirstToSecondOrigin.GetNorm() * 0.3;
430 toleratedOriginError = m_ToleratedOriginOffset;
432 MITK_DEBUG <<
"Accepting errors in actual versus expected origin up to " << toleratedOriginError <<
"mm";
445 std::string orientationValue = (*dsIter)->GetTagValueAsString( tagImageOrientation ).value;
463 assert(!datasets.empty());
469 fileFitsIntoPattern =
true;
474 fileFitsIntoPattern =
false;
480 fileFitsIntoPattern =
true;
483 else if (fromFirstToSecondOriginInitialized)
485 Point3D assumedOrigin = lastDifferentOrigin + fromFirstToSecondOrigin;
487 Vector3D originError = assumedOrigin - thisOrigin;
488 double norm = originError.GetNorm();
490 if (norm > toleratedOriginError)
492 MITK_DEBUG <<
" File does not fit into the inter-slice distance pattern (diff = "
493 << norm <<
", allowed "
494 << toleratedOriginError <<
").";
495 MITK_DEBUG <<
" Expected position (" << assumedOrigin[0] <<
","
496 << assumedOrigin[1] <<
","
497 << assumedOrigin[2] <<
"), got position ("
498 << thisOrigin[0] <<
","
499 << thisOrigin[1] <<
","
500 << thisOrigin[2] <<
")";
501 MITK_DEBUG <<
" ==> Sort away " << *dsIter <<
" for later analysis";
509 fileFitsIntoPattern =
false;
514 fileFitsIntoPattern =
true;
520 fileFitsIntoPattern =
true;
525 if ( !lastOriginInitialized || ( fileFitsIntoPattern && (thisOrigin != lastOrigin) ) )
527 lastDifferentOrigin = thisOrigin;
530 lastOrigin = thisOrigin;
531 lastOriginInitialized =
true;
558 unsigned int numberOfSlicesApart = datasets.size() - 1;
EquiDistantBlocksSorter()
std::string GetLastFilenameOfBlock() const
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.
The sorting/splitting building-block of DICOMITKSeriesGDCMReader.
virtual 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.
bool GetAcceptTwoSlicesGroups() const
Split inputs into blocks of equidistant slices (for use in DICOMITKSeriesGDCMReader).
std::vector< DICOMTag > DICOMTagList
std::string GetFirstFilenameOfBlock() const
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)
virtual DICOMTagList GetTagsOfInterest() override
void SetAcceptTwoSlicesGroups(bool accept)
std::string ConstCharStarToString(const char *s)
Safely convert const char* to std::string.
Interface to datasets that is presented to sorting classes such as DICOMDatasetSorter.
Return type of AnalyzeFileForITKImageSeriesReaderSpacingAssumption().
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.
static const std::string filename
const GantryTiltInformation & GetTiltInfo() const
Detailed description of gantry tilt.
virtual ~EquiDistantBlocksSorter()
bool m_AcceptTwoSlicesGroups
double GetToleratedOriginOffset() const
double m_ToleratedOriginOffset
MITKCORE_EXPORT const ScalarType eps
SliceGroupingAnalysisResult()
void SetFirstFilenameOfBlock(const std::string &filename)
Point3D DICOMStringToPoint3D(const std::string &s, bool &successful)
Convert DICOM string describing a point to Point3D.
bool IsToleratedOriginOffsetAbsolute() const
DICOMDatasetSorter & operator=(const DICOMDatasetSorter &other)
void UndoPrematureGrouping()
Only meaningful for use by AnalyzeFileForITKImageSeriesReaderSpacingAssumption.
std::vector< DICOMDatasetAccess * > DICOMDatasetList
virtual bool operator==(const DICOMDatasetSorter &other) const override
void SetToleratedOriginOffset(double millimeters=0.005)
See class description and SetToleratedOriginOffsetToAdaptive().
bool GetAcceptTilt() const
virtual 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.