1
+ #include " gdcmScanner.h"
2
+ #include " gdcmTesting.h"
3
+ #include " gdcmIPPSorter.h"
4
+ #include " gdcmDirectionCosines.h"
5
+ #include < cmath>
6
+
7
+ /*
8
+ * The following example is a basic sorted which should work in generic cases.
9
+ * It sort files based on:
10
+ * Study Instance UID
11
+ * Series Instance UID
12
+ * Frame of Reference UID
13
+ * Image Orientation (Patient)
14
+ * Image Position (Patient) (Sorting based on IPP + IOP)
15
+ */
16
+
17
+ namespace gdcm
18
+ {
19
+ const Tag t1 (0x0020 , 0x000d ); // Study Instance UID
20
+ const Tag t2 (0x0020 , 0x000e ); // Series Instance UID
21
+ const Tag t3 (0x0020 , 0x0052 ); // Frame of Reference UID
22
+ const Tag t4 (0x0020 , 0x0037 ); // Image Orientation (Patient)
23
+
24
+ class DiscriminateVolume
25
+ {
26
+ private:
27
+ std::vector<Directory::FilenamesType> SortedFiles;
28
+ std::vector<Directory::FilenamesType> UnsortedFiles;
29
+
30
+ Directory::FilenamesType GetAllFilenamesFromTagToValue (
31
+ Scanner const &s, Directory::FilenamesType const &filesubset, Tag const &t, const char *valueref)
32
+ {
33
+ Directory::FilenamesType theReturn;
34
+ if (valueref)
35
+ {
36
+ size_t len = strlen (valueref);
37
+ Directory::FilenamesType::const_iterator file = filesubset.begin ();
38
+ for (; file != filesubset.end (); ++file)
39
+ {
40
+ const char *filename = file->c_str ();
41
+ const char *value = s.GetValue (filename, t);
42
+ if (value && strncmp (value, valueref, len) == 0 )
43
+ {
44
+ theReturn.push_back (filename);
45
+ }
46
+ }
47
+ }
48
+ return theReturn;
49
+ }
50
+
51
+ void ProcessAIOP (Scanner const &, Directory::FilenamesType const &subset, const char *iopval)
52
+ {
53
+ std::cout << " IOP: " << iopval << std::endl;
54
+ IPPSorter ipp;
55
+ ipp.SetComputeZSpacing (true );
56
+ ipp.SetZSpacingTolerance (1e-3 ); // ??
57
+ bool b = ipp.Sort (subset);
58
+ if (!b)
59
+ {
60
+ // If you reach here this means you need one more parameter to discriminiat this
61
+ // series. Eg. T1 / T2 intertwinted. Multiple Echo (0018,0081)
62
+ std::cerr << " Failed to sort: " << subset.begin ()->c_str () << std::endl;
63
+ for (
64
+ Directory::FilenamesType::const_iterator file = subset.begin ();
65
+ file != subset.end (); ++file)
66
+ {
67
+ std::cerr << *file << std::endl;
68
+ }
69
+ UnsortedFiles.push_back (subset);
70
+ return ;
71
+ }
72
+ ipp.Print (std::cout);
73
+ SortedFiles.push_back (ipp.GetFilenames ());
74
+ }
75
+
76
+ void ProcessAFrameOfRef (Scanner const &s, Directory::FilenamesType const &subset, const char *frameuid)
77
+ {
78
+ // In this subset of files (belonging to same series), let's find those
79
+ // belonging to the same Frame ref UID:
80
+ Directory::FilenamesType files = GetAllFilenamesFromTagToValue (
81
+ s, subset, t3, frameuid);
82
+
83
+ std::set<std::string> iopset;
84
+
85
+ for (
86
+ Directory::FilenamesType::const_iterator file = files.begin ();
87
+ file != files.end (); ++file)
88
+ {
89
+ // std::cout << *file << std::endl;
90
+ const char *value = s.GetValue (file->c_str (), gdcm::t4);
91
+ assert (value);
92
+ iopset.insert (value);
93
+ }
94
+ size_t n = iopset.size ();
95
+ if (n == 0 )
96
+ {
97
+ assert (files.empty ());
98
+ return ;
99
+ }
100
+
101
+ std::cout << " Frame of Ref: " << frameuid << std::endl;
102
+ if (n == 1 )
103
+ {
104
+ ProcessAIOP (s, files, iopset.begin ()->c_str ());
105
+ }
106
+ else
107
+ {
108
+ const char *f = files.begin ()->c_str ();
109
+ std::cerr << " More than one IOP: " << f << std::endl;
110
+ // Make sure that there is actually 'n' different IOP
111
+ gdcm::DirectionCosines ref;
112
+ gdcm::DirectionCosines dc;
113
+ for (
114
+ std::set<std::string>::const_iterator it = iopset.begin ();
115
+ it != iopset.end (); ++it)
116
+ {
117
+ ref.SetFromString (it->c_str ());
118
+ for (
119
+ Directory::FilenamesType::const_iterator file = files.begin ();
120
+ file != files.end (); ++file)
121
+ {
122
+ std::string value = s.GetValue (file->c_str (), gdcm::t4);
123
+ if (value != it->c_str ())
124
+ {
125
+ dc.SetFromString (value.c_str ());
126
+ const double crossdot = ref.CrossDot (dc);
127
+ const double eps = std::fabs (1 . - crossdot);
128
+ if (eps < 1e-6 )
129
+ {
130
+ std::cerr << " Problem with IOP discrimination: " << file->c_str ()
131
+ << " " << it->c_str () << std::endl;
132
+ return ;
133
+ }
134
+ }
135
+ }
136
+ }
137
+ // If we reach here this means there is actually 'n' different IOP
138
+ for (
139
+ std::set<std::string>::const_iterator it = iopset.begin ();
140
+ it != iopset.end (); ++it)
141
+ {
142
+ const char *iopvalue = it->c_str ();
143
+ Directory::FilenamesType iopfiles = GetAllFilenamesFromTagToValue (
144
+ s, files, t4, iopvalue);
145
+ ProcessAIOP (s, iopfiles, iopvalue);
146
+ }
147
+ }
148
+ }
149
+
150
+ void ProcessASeries (Scanner const &s, const char *seriesuid)
151
+ {
152
+ std::cout << " Series: " << seriesuid << std::endl;
153
+ // let's find all files belonging to this series:
154
+ Directory::FilenamesType seriesfiles = GetAllFilenamesFromTagToValue (
155
+ s, s.GetFilenames (), t2, seriesuid);
156
+
157
+ gdcm::Scanner::ValuesType vt3 = s.GetValues (t3);
158
+ for (
159
+ gdcm::Scanner::ValuesType::const_iterator it = vt3.begin (); it != vt3.end (); ++it)
160
+ {
161
+ ProcessAFrameOfRef (s, seriesfiles, it->c_str ());
162
+ }
163
+ }
164
+
165
+ void ProcessAStudy (Scanner const &s, const char *studyuid)
166
+ {
167
+ std::cout << " Study: " << studyuid << std::endl;
168
+ gdcm::Scanner::ValuesType vt2 = s.GetValues (t2);
169
+ for (
170
+ gdcm::Scanner::ValuesType::const_iterator it = vt2.begin (); it != vt2.end (); ++it)
171
+ {
172
+ ProcessASeries (s, it->c_str ());
173
+ }
174
+ }
175
+
176
+ public:
177
+ void Print (std::ostream &os)
178
+ {
179
+ os << " Sorted Files: " << std::endl;
180
+ for (
181
+ std::vector<Directory::FilenamesType>::const_iterator it = SortedFiles.begin ();
182
+ it != SortedFiles.end (); ++it)
183
+ {
184
+ os << " Group: " << std::endl;
185
+ for (
186
+ Directory::FilenamesType::const_iterator file = it->begin ();
187
+ file != it->end (); ++file)
188
+ {
189
+ os << *file << std::endl;
190
+ }
191
+ }
192
+ os << " Unsorted Files: " << std::endl;
193
+ for (
194
+ std::vector<Directory::FilenamesType>::const_iterator it = UnsortedFiles.begin ();
195
+ it != UnsortedFiles.end (); ++it)
196
+ {
197
+ os << " Group: " << std::endl;
198
+ for (
199
+ Directory::FilenamesType::const_iterator file = it->begin ();
200
+ file != it->end (); ++file)
201
+ {
202
+ os << *file << std::endl;
203
+ }
204
+ }
205
+ }
206
+
207
+ std::vector<Directory::FilenamesType> const &GetSortedFiles () const { return SortedFiles; }
208
+ std::vector<Directory::FilenamesType> const &GetUnsortedFiles () const { return UnsortedFiles; }
209
+
210
+ void ProcessIntoVolume (Scanner const &s)
211
+ {
212
+ gdcm::Scanner::ValuesType vt1 = s.GetValues (gdcm::t1);
213
+ for (
214
+ gdcm::Scanner::ValuesType::const_iterator it = vt1.begin (); it != vt1.end (); ++it)
215
+ {
216
+ ProcessAStudy (s, it->c_str ());
217
+ }
218
+ }
219
+ };
220
+
221
+ } // namespace gdcm
222
+
223
+ // int main(int argc, char *argv[])
224
+ // {
225
+ // std::string dir1;
226
+ // if (argc < 2)
227
+ // {
228
+ // const char *extradataroot = nullptr;
229
+ // #ifdef GDCM_BUILD_TESTING
230
+ // extradataroot = gdcm::Testing::GetDataExtraRoot();
231
+ // #endif
232
+ // if (!extradataroot)
233
+ // {
234
+ // return 1;
235
+ // }
236
+ // dir1 = extradataroot;
237
+ // dir1 += "/gdcmSampleData/ForSeriesTesting/VariousIncidences/ST1";
238
+ // }
239
+ // else
240
+ // {
241
+ // dir1 = argv[1];
242
+ // }
243
+
244
+ // gdcm::Directory d;
245
+ // d.Load(dir1, true); // recursive !
246
+
247
+ // gdcm::Scanner s;
248
+ // s.AddTag(gdcm::t1);
249
+ // s.AddTag(gdcm::t2);
250
+ // s.AddTag(gdcm::t3);
251
+ // s.AddTag(gdcm::t4);
252
+ // bool b = s.Scan(d.GetFilenames());
253
+ // if (!b)
254
+ // {
255
+ // std::cerr << "Scanner failed" << std::endl;
256
+ // return 1;
257
+ // }
258
+
259
+ // gdcm::DiscriminateVolume dv;
260
+ // dv.ProcessIntoVolume(s);
261
+ // dv.Print(std::cout);
262
+
263
+ // return 0;
264
+ // }
0 commit comments