Skip to content

Read dicom tags #406

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 20, 2021
Merged

Conversation

floryst
Copy link
Member

@floryst floryst commented Mar 26, 2021

This adds an API for reading DICOM tags from DICOM object files. Additionally, appropriate character set conversion is performed, decoding encoded strings into UTF-8.

Relevant issue: #394

Todo:

  • add async version
  • add browser version
  • add charset decoder
  • Add docs
  • Make API and docs consistent

@floryst floryst marked this pull request as draft March 26, 2021 22:35
@floryst
Copy link
Member Author

floryst commented Mar 26, 2021

FYI @agirault

@agirault
Copy link
Collaborator

Can you add usage documentation @floryst ? or an example?

@floryst floryst marked this pull request as ready for review March 31, 2021 21:49
@floryst floryst changed the title WIP: Read dicom tags Read dicom tags Mar 31, 2021
@floryst
Copy link
Member Author

floryst commented Mar 31, 2021

I'm not sure why I can't request reviewers, so here: @thewtex @agirault.

This is still in a rough shape, so apart from a code review there are a few questions/remarks remaining:

  • The API is readDICOMTags(fileList, tags=[]). I think the API would make more sense if we simply read the tags from a single file instead, i.e. readDICOMTags(file, tags=[]). I pretty much copied this from readImageDICOMFileSeries, and in doing so kept the multiple file parameter fileList. Initially the rationale was that, performance wise, its probably better to spawn one webworker to get the tags for a set of files rather than many webworkers, but this could likely be remedied by letting the API pass in an existing webworker anyways.
  • Would it make sense to support returning all tags, rather than specifying which ones the user wants? If so, I think setting tags=null|undefined can mean "return all tags".
  • I haven't tested private tags. What would the expected behavior be for private tags, since we don't necessarily know the tag's VR? (This is partially a GDCM question.)
  • Code style: is there an automatic c++ style enforcer for itk-js? My c++ code currently has a mix of the itk-js c++ coding style and the clang c++ codingstyle and I wanted to ask before making manual changes to match the itk-js c++ coding style.
  • libiconv: if the docker container installed the requisite compilation headers for iconv (which might be provided by libc6 rather than a dedicated package), then I wouldn't need to add iconv as an external project. As it stands, the ExternalProject is the only way to use iconv, which is why I include it.


const readDICOMTags = async (
fileList,
tags = null
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These parameters may change, pending API discussions.

  • fileList: probably going to become a single file rather than a list of files
  • tags: if we want a null/undefined tags arg to mean "give me all tags", then this will stay. Right now there is no logic for getting all tags.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for the single file. Specification of the tags-per-file is simpler this way, too. +1 for the current null returns all tags API.

Copy link
Member

@thewtex thewtex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@floryst awesome!! 🚀 👨‍🎤

Additionally, appropriate character set conversion is performed, decoding encoded strings into UTF-8.

This is fantastic! Can we add a test to ensure its functionality?

I'm not sure why I can't request reviewers, so here: @thewtex @agirault.

@floryst after accepting the invitation to the repository (just sent), you should be able to request reviewers.

I think the API would make more sense if we simply read the tags from a single file instead

+1

Would it make sense to support returning all tags, rather than specifying which ones the user wants? If so, I think setting tags=null|undefined can mean "return all tags".

+1

I haven't tested private tags. What would the expected behavior be for private tags, since we don't necessarily know the tag's VR? (This is partially a GDCM question.)

In the future, if this is possible and needed, we could add a third argument, privateTags=false.

Code style: is there an automatic c++ style enforcer for itk-js? My c++ code currently has a mix of the itk-js c++ coding style and the clang c++ codingstyle and I wanted to ask before making manual changes to match the itk-js c++ coding style.

Thanks for asking! The code is looking very clean, btw. We should use the ITK clang-format style. To apply it to the current code, download the clang-format-8 executable, and run it on the source code files with the ITK/.clang-format configuration file.

We gave a pre-commit hooks setup for ITK that runs clang-format -- we could add this to itk.js sometime.

libiconv: if the docker container installed the requisite compilation headers for iconv (which might be provided by libc6 rather than a dedicated package), then I wouldn't need to add iconv as an external project. As it stands, the ExternalProject is the only way to use iconv, which is why I include it.

This is awesome. While we could add the package to the docker image, I think the ExternalProject is better because we can change the base image Linux distribution and Linux distribution version, and not have to worry about losing the required headers or them moving around. We can also independently update the libiconv version.

@@ -3,6 +3,14 @@ find_path(RapidJSON_INCLUDE_DIR
)
include_directories(${RapidJSON_INCLUDE_DIR})

# include iconv for reading dicom tags
include(ExternalProject)
set(Iconv iconv)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lovely!

return { tags: tagResults, webWorker: worker }
}
const numberOfWorkers = navigator.hardwareConcurrency ? navigator.hardwareConcurrency : 4
const workerPool = new WorkerPool(numberOfWorkers, workerFunction)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want this to defined outside function scope so to re-use across multiple runs.


const readDICOMTags = async (
fileList,
tags = null
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for the single file. Specification of the tags-per-file is simpler this way, too. +1 for the current null returns all tags API.

@floryst
Copy link
Member Author

floryst commented Apr 19, 2021

Good timing, I was just starting to rewrite this PR to read in a single file instead of a list. I'll push that out shortly, after some build resolutions.

@floryst floryst requested a review from thewtex April 19, 2021 21:37
@floryst
Copy link
Member Author

floryst commented Apr 19, 2021

  • I've switched to using a single-file API with a reusable webworker for the browser API.
  • passing null for tags (or really anything that fails the Array.isArray test) will return all tags.
  • Tag maps are returned as Map objects rather than plain objects.

Copy link
Member

@thewtex thewtex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@floryst beautiful!

@thewtex thewtex merged commit f18435a into InsightSoftwareConsortium:master Apr 20, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants