Medical Imaging Interaction Toolkit  2018.4.99-f51274ea
Medical Imaging Interaction Toolkit
mitkDICOMSortByTag.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include "mitkDICOMSortByTag.h"
14 
15 #include "dcmtk/ofstd/ofstd.h"
16 
18 ::DICOMSortByTag(const DICOMTag& tag, DICOMSortCriterion::Pointer secondaryCriterion)
19 :DICOMSortCriterion(secondaryCriterion)
20 ,m_Tag(tag)
21 {
22 }
23 
26 {
27 }
28 
31 :DICOMSortCriterion(other)
32 ,m_Tag(other.m_Tag)
33 {
34 }
35 
39 {
40  if (this != &other)
41  {
43  m_Tag = other.m_Tag;
44  }
45  return *this;
46 }
47 
48 bool
50 ::operator==(const DICOMSortCriterion& other) const
51 {
52  if (const auto* otherSelf = dynamic_cast<const DICOMSortByTag*>(&other))
53  {
54  if (!(this->m_Tag == otherSelf->m_Tag)) return false;
55 
56  if (this->m_SecondaryCriterion.IsNull() && otherSelf->m_SecondaryCriterion.IsNull()) return true;
57 
58  if (this->m_SecondaryCriterion.IsNull() || otherSelf->m_SecondaryCriterion.IsNull()) return false;
59 
60  return *(this->m_SecondaryCriterion) == *(otherSelf->m_SecondaryCriterion);
61  }
62  else
63  {
64  return false;
65  }
66 }
67 
68 void
70 ::Print(std::ostream& os) const
71 {
72  m_Tag.Print(os);
73 }
74 
75 
79 {
80  DICOMTagList list;
81  list.push_back(m_Tag);
82  return list;
83 }
84 
85 bool
88 {
89  return this->NumericCompare(left, right, m_Tag);
90 }
91 
92 bool
94 ::StringCompare(const mitk::DICOMDatasetAccess* left, const mitk::DICOMDatasetAccess* right, const DICOMTag& tag) const
95 {
96  assert(left);
97  assert(right);
98 
99  DICOMDatasetFinding leftFinding = left->GetTagValueAsString(tag);
100  DICOMDatasetFinding rightFinding = right->GetTagValueAsString(tag);
101  //Doesn't care if findings are valid or not. If they are not valid,
102  //value is empty, thats enough.
103  if (leftFinding.value != rightFinding.value)
104  {
105  return leftFinding.value.compare(rightFinding.value) < 0;
106  }
107  else
108  {
109  return this->NextLevelIsLeftBeforeRight(left, right);
110  }
111 }
112 
113 bool
116 {
117  assert(left);
118  assert(right);
119 
120  const DICOMDatasetFinding leftFinding = left->GetTagValueAsString(tag);
121  const DICOMDatasetFinding rightFinding = right->GetTagValueAsString(tag);
122  //Doesn't care if findings are valid or not. If they are not valid,
123  //value is empty, thats enough.
124 
125  double leftDouble( 0 );
126  double rightDouble( 0 );
127 
128  try
129  {
130  leftDouble = OFStandard::atof( leftFinding.value.c_str() );
131  rightDouble = OFStandard::atof(rightFinding.value.c_str());
132  }
133  catch ( const std::exception& /*e*/ )
134  {
135  return this->StringCompare(left,right, tag); // fallback to string compare
136  }
137 
138 
139  if ( leftDouble != rightDouble ) // can we decide?
140  {
141  return leftDouble < rightDouble;
142  }
143  else // ask secondary criterion
144  {
145  return this->NextLevelIsLeftBeforeRight( left, right );
146  }
147 }
148 
149 double
152 {
153  assert(from);
154  assert(to);
155 
156  const DICOMDatasetFinding fromFinding = from->GetTagValueAsString(m_Tag);
157  const DICOMDatasetFinding toFinding = to->GetTagValueAsString(m_Tag);
158  //Doesn't care if findings are valid or not. If they are not valid,
159  //value is empty, thats enough.
160 
161  double fromDouble(0);
162  double toDouble(0);
163 
164  try
165  {
166  fromDouble = OFStandard::atof(fromFinding.value.c_str());
167  toDouble = OFStandard::atof(toFinding.value.c_str());
168  }
169  catch ( const std::exception& /*e*/ )
170  {
171  MITK_WARN << "NO NUMERIC DISTANCE between '" << fromFinding.value << "' and '" << toFinding.value << "'";
172  return 0;
173  }
174 
175  return toDouble - fromDouble;
176  // TODO second-level compare?
177 }
void Print(std::ostream &os) const
add "(group-id,element-id) name" to given stream
std::vector< DICOMTag > DICOMTagList
Definition: mitkDICOMTag.h:59
Representation of a DICOM tag.
Definition: mitkDICOMTag.h:32
void Print(std::ostream &os) const override
brief describe this class in given stream.
DICOMSortCriterion::Pointer m_SecondaryCriterion
DICOMSortCriterion & operator=(const DICOMSortCriterion &other)
Interface to datasets that is presented to sorting classes such as DICOMDatasetSorter.
bool NextLevelIsLeftBeforeRight(const mitk::DICOMDatasetAccess *left, const mitk::DICOMDatasetAccess *right) const
double NumericDistance(const mitk::DICOMDatasetAccess *from, const mitk::DICOMDatasetAccess *to) const override
Calculate a distance between two datasets. This ansers the question of consecutive datasets...
#define MITK_WARN
Definition: mitkLogMacros.h:19
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...
bool StringCompare(const mitk::DICOMDatasetAccess *left, const mitk::DICOMDatasetAccess *right, const DICOMTag &tag) const
DICOMSortByTag & operator=(const DICOMSortByTag &other)
bool operator==(const DICOMSortCriterion &other) const override
Compare two datasets by the value of a single tag (for use in DICOMTagBasedSorter).
A tag based sorting criterion for use in DICOMTagBasedSorter.
DICOMSortByTag(const DICOMTag &tag, DICOMSortCriterion::Pointer secondaryCriterion=nullptr)
bool IsLeftBeforeRight(const mitk::DICOMDatasetAccess *left, const mitk::DICOMDatasetAccess *right) const override
Answer the sorting question.
DICOMTagList GetTagsOfInterest() const override
Tags used for comparison.
bool NumericCompare(const mitk::DICOMDatasetAccess *left, const mitk::DICOMDatasetAccess *right, const DICOMTag &tag) const