Skip to content

Commit

Permalink
fix(image-sets-normalization): check more tags when grouping volumes
Browse files Browse the repository at this point in the history
refactor DicomFile to struct
  • Loading branch information
PaulHax committed Apr 1, 2024
1 parent d4ec0c3 commit df876af
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 26 deletions.
63 changes: 37 additions & 26 deletions packages/dicom/gdcm/image-sets-normalization.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@

const std::string STUDY_INSTANCE_UID = "0020|000D";
const std::string SERIES_INSTANCE_UID = "0020|000e";
const std::string FRAME_OF_REFERENCE_UID = "0020|0052";
const std::string IMAGE_ORIENTATION_PATIENT = "0020|0037";

using File = std::string;

rapidjson::Value mapToJsonObj(const TagMap &tags, rapidjson::Document::AllocatorType &allocator)
{
Expand Down Expand Up @@ -73,29 +74,41 @@ rapidjson::Value jsonFromTags(const TagMap &tags, const TagNames &tagNames, rapi
return mapToJsonObj(filteredTags, allocator);
}

using DicomFile = std::pair<const File, const TagMap>;
using FileName = std::string;

struct DicomFile
{
FileName fileName;
TagMap tags;

bool operator==(const DicomFile &other) const
{
return fileName == other.fileName;
}
};

struct dicomFileHash
{
std::size_t operator()(const DicomFile &dFile) const
std::size_t operator()(const DicomFile &dicomFile) const
{
return std::hash<File>{}(dFile.first);
return std::hash<FileName>{}(dicomFile.fileName);
}
};
using DicomFiles = std::unordered_set<DicomFile, dicomFileHash>;

DicomFiles readTags(const std::vector<File> &files)
DicomFiles loadFiles(const std::vector<FileName> &files)
{
DicomFiles dicomFiles;
itk::DICOMTagReader tagReader;
for (const File &fileName : files)
for (const FileName &fileName : files)
{
if (!tagReader.CanReadFile(fileName))
{
throw std::runtime_error("Could not read the input DICOM file: " + fileName);
}
tagReader.SetFileName(fileName);
const TagMap dicomTags = tagReader.ReadAllTags();
dicomFiles.insert(std::make_pair(fileName, dicomTags));
dicomFiles.insert({fileName, dicomTags});
}
return dicomFiles;
}
Expand All @@ -108,35 +121,33 @@ bool compareTags(const TagMap &tags1, const TagMap &tags2, const TagKeys &tagKey
{
for (const auto &tagKey : tagKeys)
{
const auto it1 = tags1.find(tagKey);
const auto it2 = tags2.find(tagKey);
if (it1 == tags1.end() || it2 == tags2.end())
const auto tagA = tags1.find(tagKey);
const auto tagB = tags2.find(tagKey);
if (tagA == tags1.end() || tagB == tags2.end())
{
return false;
}
if (it1->second != it2->second)
if (tagA->second != tagB->second)
{
return false;
}
}
return true;
}

bool isSameVolume(const TagMap &tags1, const TagMap &tags2)
bool isSameVolume(const TagMap &tagsA, const TagMap &tagsB)
{
// TODO check cosines
return compareTags(tags1, tags2, {SERIES_INSTANCE_UID});
return compareTags(tagsA, tagsB, {SERIES_INSTANCE_UID, FRAME_OF_REFERENCE_UID, IMAGE_ORIENTATION_PATIENT});
}

Volumes groupByVolume(const DicomFiles &dicomFiles)
{
Volumes volumes;
for (const DicomFile &dicomFile : dicomFiles)
{
const auto tags = dicomFile.second;
const auto tags = dicomFile.tags;
auto matchingVolume = std::find_if(volumes.begin(), volumes.end(), [&tags](const Volume &volume)
{
return isSameVolume(volume.begin()->second, tags); });
{ return isSameVolume(volume.begin()->tags, tags); });

if (matchingVolume != volumes.end())
{
Expand All @@ -156,10 +167,10 @@ ImageSets groupByImageSet(const Volumes &volumes)
ImageSets imageSets;
for (const Volume &volume : volumes)
{
const auto volumeTags = volume.begin()->second;
const auto volumeTags = volume.begin()->tags;
auto matchingImageSet = std::find_if(imageSets.begin(), imageSets.end(), [&volumeTags](const Volumes &volumes)
{
const TagMap imageSetTags = volumes.begin()->begin()->second;
const TagMap imageSetTags = volumes.begin()->begin()->tags;
return compareTags(imageSetTags, volumeTags, {STUDY_INSTANCE_UID}); });
if (matchingImageSet != imageSets.end())
{
Expand All @@ -179,18 +190,18 @@ Volumes sortSpatially(Volumes &volumes)
Volumes sortedVolumes;
for (Volume &volume : volumes)
{
std::vector<std::string> unsortedSerieFileNames;
std::vector<std::string> unsortedSeriesFileNames;
for (const DicomFile &dicomFile : volume)
{
unsortedSerieFileNames.push_back(dicomFile.first);
unsortedSeriesFileNames.push_back(dicomFile.fileName);
}
std::vector<std::string> sortedFileNames = sortSpatially(unsortedSerieFileNames);
std::vector<std::string> sortedFileNames = sortSpatially(unsortedSeriesFileNames);

Volume sorted;
for (const auto &fileName : sortedFileNames)
{
const auto matchingDicomFile = std::find_if(volume.begin(), volume.end(), [&fileName](const DicomFile &dicomFile)
{ return dicomFile.first == fileName; });
{ return dicomFile.fileName == fileName; });
if (matchingDicomFile != volume.end())
{
sorted.push_back(*matchingDicomFile);
Expand All @@ -214,8 +225,8 @@ rapidjson::Document toJson(const ImageSets &imageSets)
rapidjson::Value instances(rapidjson::kObjectType);
for (const auto &dicomFile : volume)
{
File file = dicomFile.first;
dicomTags = dicomFile.second;
FileName file = dicomFile.fileName;
dicomTags = dicomFile.tags;
// filter out patient, study, series tags
TagMap instanceTags = remove(dicomTags, PATIENT_TAG_NAMES);
instanceTags = remove(instanceTags, STUDY_TAG_NAMES);
Expand Down Expand Up @@ -290,7 +301,7 @@ int main(int argc, char *argv[])

ITK_WASM_PARSE(pipeline);

const DicomFiles dicomFiles = readTags(files);
const DicomFiles dicomFiles = loadFiles(files);
Volumes volumes = groupByVolume(dicomFiles);
volumes = sortSpatially(volumes);
const ImageSets imageSets = groupByImageSet(volumes);
Expand Down
Binary file not shown.

0 comments on commit df876af

Please sign in to comment.