3030
3131const std::string STUDY_INSTANCE_UID = " 0020|000D" ;
3232const std::string SERIES_INSTANCE_UID = " 0020|000e" ;
33+ const std::string FRAME_OF_REFERENCE_UID = " 0020|0052" ;
34+ const std::string IMAGE_ORIENTATION_PATIENT = " 0020|0037" ;
3335
34- using File = std::string;
3536
3637rapidjson::Value mapToJsonObj (const TagMap &tags, rapidjson::Document::AllocatorType &allocator)
3738{
@@ -73,29 +74,41 @@ rapidjson::Value jsonFromTags(const TagMap &tags, const TagNames &tagNames, rapi
7374 return mapToJsonObj (filteredTags, allocator);
7475}
7576
76- using DicomFile = std::pair<const File, const TagMap>;
77+ using FileName = std::string;
78+
79+ struct DicomFile
80+ {
81+ FileName fileName;
82+ TagMap tags;
83+
84+ bool operator ==(const DicomFile &other) const
85+ {
86+ return fileName == other.fileName ;
87+ }
88+ };
89+
7790struct dicomFileHash
7891{
79- std::size_t operator ()(const DicomFile &dFile ) const
92+ std::size_t operator ()(const DicomFile &dicomFile ) const
8093 {
81- return std::hash<File >{}(dFile. first );
94+ return std::hash<FileName >{}(dicomFile. fileName );
8295 }
8396};
8497using DicomFiles = std::unordered_set<DicomFile, dicomFileHash>;
8598
86- DicomFiles readTags (const std::vector<File > &files)
99+ DicomFiles loadFiles (const std::vector<FileName > &files)
87100{
88101 DicomFiles dicomFiles;
89102 itk::DICOMTagReader tagReader;
90- for (const File &fileName : files)
103+ for (const FileName &fileName : files)
91104 {
92105 if (!tagReader.CanReadFile (fileName))
93106 {
94107 throw std::runtime_error (" Could not read the input DICOM file: " + fileName);
95108 }
96109 tagReader.SetFileName (fileName);
97110 const TagMap dicomTags = tagReader.ReadAllTags ();
98- dicomFiles.insert (std::make_pair ( fileName, dicomTags) );
111+ dicomFiles.insert ({ fileName, dicomTags} );
99112 }
100113 return dicomFiles;
101114}
@@ -108,35 +121,33 @@ bool compareTags(const TagMap &tags1, const TagMap &tags2, const TagKeys &tagKey
108121{
109122 for (const auto &tagKey : tagKeys)
110123 {
111- const auto it1 = tags1.find (tagKey);
112- const auto it2 = tags2.find (tagKey);
113- if (it1 == tags1.end () || it2 == tags2.end ())
124+ const auto tagA = tags1.find (tagKey);
125+ const auto tagB = tags2.find (tagKey);
126+ if (tagA == tags1.end () || tagB == tags2.end ())
114127 {
115128 return false ;
116129 }
117- if (it1 ->second != it2 ->second )
130+ if (tagA ->second != tagB ->second )
118131 {
119132 return false ;
120133 }
121134 }
122135 return true ;
123136}
124137
125- bool isSameVolume (const TagMap &tags1 , const TagMap &tags2 )
138+ bool isSameVolume (const TagMap &tagsA , const TagMap &tagsB )
126139{
127- // TODO check cosines
128- return compareTags (tags1, tags2, {SERIES_INSTANCE_UID});
140+ return compareTags (tagsA, tagsB, {SERIES_INSTANCE_UID, FRAME_OF_REFERENCE_UID, IMAGE_ORIENTATION_PATIENT});
129141}
130142
131143Volumes groupByVolume (const DicomFiles &dicomFiles)
132144{
133145 Volumes volumes;
134146 for (const DicomFile &dicomFile : dicomFiles)
135147 {
136- const auto tags = dicomFile.second ;
148+ const auto tags = dicomFile.tags ;
137149 auto matchingVolume = std::find_if (volumes.begin (), volumes.end (), [&tags](const Volume &volume)
138- {
139- return isSameVolume (volume.begin ()->second , tags); });
150+ { return isSameVolume (volume.begin ()->tags , tags); });
140151
141152 if (matchingVolume != volumes.end ())
142153 {
@@ -156,10 +167,10 @@ ImageSets groupByImageSet(const Volumes &volumes)
156167 ImageSets imageSets;
157168 for (const Volume &volume : volumes)
158169 {
159- const auto volumeTags = volume.begin ()->second ;
170+ const auto volumeTags = volume.begin ()->tags ;
160171 auto matchingImageSet = std::find_if (imageSets.begin (), imageSets.end (), [&volumeTags](const Volumes &volumes)
161172 {
162- const TagMap imageSetTags = volumes.begin ()->begin ()->second ;
173+ const TagMap imageSetTags = volumes.begin ()->begin ()->tags ;
163174 return compareTags (imageSetTags, volumeTags, {STUDY_INSTANCE_UID}); });
164175 if (matchingImageSet != imageSets.end ())
165176 {
@@ -179,18 +190,18 @@ Volumes sortSpatially(Volumes &volumes)
179190 Volumes sortedVolumes;
180191 for (Volume &volume : volumes)
181192 {
182- std::vector<std::string> unsortedSerieFileNames ;
193+ std::vector<std::string> unsortedSeriesFileNames ;
183194 for (const DicomFile &dicomFile : volume)
184195 {
185- unsortedSerieFileNames .push_back (dicomFile.first );
196+ unsortedSeriesFileNames .push_back (dicomFile.fileName );
186197 }
187- std::vector<std::string> sortedFileNames = sortSpatially (unsortedSerieFileNames );
198+ std::vector<std::string> sortedFileNames = sortSpatially (unsortedSeriesFileNames );
188199
189200 Volume sorted;
190201 for (const auto &fileName : sortedFileNames)
191202 {
192203 const auto matchingDicomFile = std::find_if (volume.begin (), volume.end (), [&fileName](const DicomFile &dicomFile)
193- { return dicomFile.first == fileName; });
204+ { return dicomFile.fileName == fileName; });
194205 if (matchingDicomFile != volume.end ())
195206 {
196207 sorted.push_back (*matchingDicomFile);
@@ -214,8 +225,8 @@ rapidjson::Document toJson(const ImageSets &imageSets)
214225 rapidjson::Value instances (rapidjson::kObjectType );
215226 for (const auto &dicomFile : volume)
216227 {
217- File file = dicomFile.first ;
218- dicomTags = dicomFile.second ;
228+ FileName file = dicomFile.fileName ;
229+ dicomTags = dicomFile.tags ;
219230 // filter out patient, study, series tags
220231 TagMap instanceTags = remove (dicomTags, PATIENT_TAG_NAMES);
221232 instanceTags = remove (instanceTags, STUDY_TAG_NAMES);
@@ -290,7 +301,7 @@ int main(int argc, char *argv[])
290301
291302 ITK_WASM_PARSE (pipeline);
292303
293- const DicomFiles dicomFiles = readTags (files);
304+ const DicomFiles dicomFiles = loadFiles (files);
294305 Volumes volumes = groupByVolume (dicomFiles);
295306 volumes = sortSpatially (volumes);
296307 const ImageSets imageSets = groupByImageSet (volumes);
0 commit comments