20 :m_Precision(precision)
26 :m_Precision(other.m_Precision)
36 std::ostringstream resultString;
37 resultString.str(std::string());
39 resultString.setf(std::ios::fixed, std::ios::floatfield);
40 resultString.precision(m_Precision);
42 std::stringstream ss(input);
47 std::istringstream converter(item);
48 while (std::getline(ss, item,
'\\'))
52 if (converter >> number && converter.eof())
55 resultString << number;
69 return resultString.str();
148 if (
const auto* otherSelf = dynamic_cast<const DICOMTagBasedSorter*>(&other))
153 bool allTagsPresentAndEqual(
true);
161 allTagsPresentAndEqual &= (std::find( otherSelf->m_DistinguishingTags.cbegin(), otherSelf->m_DistinguishingTags.cend(), *myTag )
162 != otherSelf->m_DistinguishingTags.cend());
166 if (!allTagsPresentAndEqual)
return false;
168 if (this->
m_SortCriterion.IsNotNull() && otherSelf->m_SortCriterion.IsNotNull())
174 return this->
m_SortCriterion.IsNull() && otherSelf->m_SortCriterion.IsNull();
187 os << indent <<
"Tag based sorting " 196 os << indent <<
" Split on ";
202 while (crit.IsNotNull())
204 os << indent <<
" Sort by ";
207 crit = crit->GetSecondaryCriterion();
249 allTags.insert( allTags.end(), sortingRelevantTags.cbegin(), sortingRelevantTags.cend() );
292 mitk::DICOMSortCriterion::ConstPointer
310 unsigned int outputIndex(0);
311 for (
auto groupIter = sortedGroups.cbegin();
312 groupIter != sortedGroups.cend();
313 ++outputIndex, ++groupIter)
315 this->
SetOutput(outputIndex, groupIter->second);
325 std::stringstream groupID;
331 groupID << tagIter->GetGroup() << tagIter->GetElement();
333 std::string processedTagValue;
340 processedTagValue = rawTagValue.
value;
342 groupID << processedTagValue;
345 return groupID.str();
356 for (
auto dsIter = input.cbegin();
357 dsIter != input.cend();
365 listForGroupID[groupID].push_back(dataset);
368 MITK_DEBUG <<
"After tag based splitting: " << listForGroupID.size() <<
" groups";
370 return listForGroupID;
397 unsigned int groupIndex(0);
398 for (
auto gIter = groups.begin();
399 gIter != groups.end();
400 ++groupIndex, ++gIter)
404 #ifdef MBILOG_ENABLE_DEBUG 405 MITK_DEBUG <<
" --------------------------------------------------------------------------------";
406 MITK_DEBUG <<
" DICOMTagBasedSorter before sorting group : " << groupIndex;
407 for (
auto oi = dsList.begin();
411 MITK_DEBUG <<
" INPUT : " << (*oi)->GetFilenameIfAvailable();
413 #endif // #ifdef MBILOG_ENABLE_DEBUG 418 #ifdef MBILOG_ENABLE_DEBUG 419 MITK_DEBUG <<
" --------------------------------------------------------------------------------";
420 MITK_DEBUG <<
" DICOMTagBasedSorter after sorting group : " << groupIndex;
421 for (
auto oi = dsList.cbegin();
425 MITK_DEBUG <<
" OUTPUT : " << (*oi)->GetFilenameIfAvailable();
427 MITK_DEBUG <<
" --------------------------------------------------------------------------------";
429 #endif // MBILOG_ENABLE_DEBUG 437 unsigned int groupIndex(0);
438 for (
auto gIter = groups.begin();
439 gIter != groups.end();
442 std::stringstream groupKey;
443 groupKey << std::setfill(
'0') << std::setw(6) << groupIndex++;
447 unsigned int dsIndex(0);
448 double constantDistance(0.0);
449 bool constantDistanceInitialized(
false);
450 for (
auto dataset = dsList.cbegin();
451 dataset != dsList.cend();
452 ++dsIndex, ++dataset)
459 const double currentDistance =
m_SortCriterion->NumericDistance(previousDS, *dataset);
460 if (constantDistanceInitialized)
462 if (fabs(currentDistance - constantDistance) < fabs(constantDistance * 0.01))
465 MITK_DEBUG <<
"Checking currentDistance==" << currentDistance <<
": small enough";
470 MITK_DEBUG <<
"Split consecutive group at index " << dsIndex <<
" (current distance " << currentDistance <<
", constant distance " << constantDistance <<
")";
472 groupKey.str(std::string());
474 groupKey << std::setfill(
'0') << std::setw(6) << groupIndex++;
492 if ((currentDistance - (
int)currentDistance == 0.0) && fabs(currentDistance) != 1.0)
495 MITK_DEBUG <<
"Split consecutive group at index " << dsIndex <<
" (special case: expected distance 1 exactly)";
496 groupKey.str(std::string());
498 groupKey << std::setfill(
'0') << std::setw(6) << groupIndex++;
502 MITK_DEBUG <<
"Initialize strict distance to currentDistance=" << currentDistance;
504 constantDistance = currentDistance;
505 constantDistanceInitialized =
true;
508 consecutiveGroups[groupKey.str()].push_back(*dataset);
509 previousDS = *dataset;
515 consecutiveGroups = groups;
529 for (
auto gIter = consecutiveGroups.cbegin();
530 gIter != consecutiveGroups.cend();
533 assert(!gIter->second.empty());
534 firstSlices.push_back(gIter->second.front());
540 unsigned int groupKeyValue(0);
541 for (
auto firstSlice = firstSlices.cbegin();
542 firstSlice != firstSlices.cend();
545 for (
auto gIter = consecutiveGroups.cbegin();
546 gIter != consecutiveGroups.cend();
547 ++groupKeyValue, ++gIter)
549 if (gIter->second.front() == *firstSlice)
551 std::stringstream groupKey;
552 groupKey << std::setfill(
'0') << std::setw(6) << groupKeyValue;
553 sortedResultBlocks[groupKey.str()] = gIter->second;
558 groups = sortedResultBlocks;
561 #ifdef MBILOG_ENABLE_DEBUG 562 unsigned int groupIndex( 0 );
563 for (
auto gIter = groups.begin(); gIter != groups.end(); ++groupIndex, ++gIter )
566 MITK_DEBUG <<
" --------------------------------------------------------------------------------";
567 MITK_DEBUG <<
" DICOMTagBasedSorter after sorting group : " << groupIndex;
568 for (
auto oi = dsList.begin(); oi != dsList.end(); ++oi )
570 MITK_DEBUG <<
" OUTPUT : " << ( *oi )->GetFilenameIfAvailable();
572 MITK_DEBUG <<
" --------------------------------------------------------------------------------";
574 #endif // MBILOG_ENABLE_DEBUG void SetStrictSorting(bool strict)
Whether or not groups should be checked for consecutive tag values.
void PrintConfiguration(std::ostream &os, const std::string &indent="") const override
Print configuration details into given stream.
void SetExpectDistanceOne(bool strict)
Flag for a special case in "strict sorting". Please see documentation of SetStrictSorting().
The sorting/splitting building-block of DICOMITKSeriesGDCMReader.
const TagValueProcessor * GetTagValueProcessorForDistinguishingTag(const DICOMTag &) const
void SetSortCriterion(DICOMSortCriterion::ConstPointer criterion)
Define the sorting criterion (which holds seconardy criteria)
std::vector< DICOMTag > DICOMTagList
ParameterizedDatasetSort(DICOMSortCriterion::ConstPointer)
GroupIDToListType & SortGroups(GroupIDToListType &groups)
Implements the sorting step. Relatively simple implementation thanks to std::sort and a parameterizat...
DICOMTagList m_DistinguishingTags
Representation of a DICOM tag.
DICOMSortCriterion::ConstPointer m_SortCriterion
bool operator==(const DICOMDatasetSorter &other) const override
std::map< std::string, DICOMDatasetList > GroupIDToListType
CutDecimalPlaces(unsigned int precision)
void SetNumberOfOutputs(unsigned int numberOfOutputs)
static const bool m_DefaultExpectDistanceOne
Helper struct to feed into std::sort, configured via DICOMSortCriterion.
const DICOMDatasetList & GetInput() const
Input for sorting.
Interface to datasets that is presented to sorting classes such as DICOMDatasetSorter.
GroupIDToListType SplitInputGroups()
Implements the "distiguishing tags". To sort datasets into different groups, a long string will be bu...
void AddDistinguishingTag(const DICOMTag &, TagValueProcessor *tagValueProcessor=nullptr)
Datasets that differ in given tag's value will be sorted into separate outputs.
bool GetExpectDistanceOne() const
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...
TagValueProcessorMap m_TagValueProcessor
std::string operator()(const std::string &) const override
Implements the "processing".
static const bool m_DefaultStrictSorting
DICOMTagList GetDistinguishingTags() const
DICOMSortCriterion::ConstPointer GetSortCriterion() const
DICOMTagBasedSorter & operator=(const DICOMTagBasedSorter &other)
DICOMSortCriterion::ConstPointer m_SortCriterion
void Sort() override
Actually sort as described in the Detailed Description.
bool operator()(const mitk::DICOMDatasetAccess *left, const mitk::DICOMDatasetAccess *right)
bool GetStrictSorting() const
TagValueProcessor * Clone() const override
DICOMTagList GetTagsOfInterest() override
A list of all the tags needed for processing (facilitates scanning).
Cuts a number after configured number of decimal places. An instance of this class can be used to avo...
~DICOMTagBasedSorter() override
virtual std::string GetFilenameIfAvailable() const =0
Return a filename if possible. If DICOM is not read from file but from somewhere else (network...
Sort DICOM datasets based on configurable tags.
void SetOutput(unsigned int index, const DICOMDatasetList &output)
Processes tag values before they are compared. These classes could do some kind of normalization such...
DICOMDatasetSorter & operator=(const DICOMDatasetSorter &other)
std::vector< DICOMDatasetAccess * > DICOMDatasetList
std::string BuildGroupID(DICOMDatasetAccess *dataset)
Helper for SplitInputGroups().
unsigned int GetPrecision() const