-
Notifications
You must be signed in to change notification settings - Fork 83
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
IDC DICOM use itkwasm-dicom, idc python package #757
base: main
Are you sure you want to change the base?
Conversation
Check out this pull request on See visual diffs & provide feedback on Jupyter Notebooks. Powered by ReviewNB |
Rendered preview: https://app.reviewnb.com/InsightSoftwareConsortium/itkwidgets/pull/757/ |
To make this easier to review, if I understand correctly from https://app.reviewnb.com/InsightSoftwareConsortium/itkwidgets/pull/757/, this is SEG:
and this is CT:
I think there are multiple issues that are/may be involved.
My recommendation has been to resample SEG to the image geometry with nearest neighbor interpolator before working with the arrays. It is not pretty, but should be lossless. I am not sure there is a better way. @pieper do you have any comments? |
@thewtex related to this PR, in
I recommend you instead of For example, the cell below: %%capture
# CT series downloaded from IDC, NLST collection (https://doi.org/10.7937/TCIA.HMQ8-J677)
!s5cmd --no-sign-request --endpoint-url https://storage.googleapis.com cp "s3://public-datasets-idc/865da32b-cea7-4e6d-b4fe-9731bf08b3d2/*" CT_DICOM_series
# segmentation of this series downloaded from IDC, from nnU-Net-BPR-Annotations (https://doi.org/10.5281/zenodo.7539035)
!s5cmd --no-sign-request --endpoint-url https://storage.googleapis.com cp "s3://public-datasets-idc/3a0c03fe-3d17-48dc-9b8d-f64f5302e0a4/*" SEG_DICOM_series will become the following: # CT series downloaded from IDC, NLST collection (https://doi.org/10.7937/TCIA.HMQ8-J677)
!idc download 1.2.840.113654.2.55.247854884634057477137769379611681725965
# segmentation of this series downloaded from IDC, from nnU-Net-BPR-Annotations (https://doi.org/10.5281/zenodo.7539035)
!idc download 1.2.276.0.7230010.3.1.3.481034752.249602.1661572065.734219 In the above,
We definitely can add the functionality to download by In any case, I strongly recommend |
@thewtex My first impression is that the coordinate system chosen for SEG is different. I suppose it depends on how the SEG was generated. Also agree with @fedorov regarding precision loss as well as skipping of slices (accounts for dim difference). Would there be a way to interpret the SEG from any third party software (even if closed source), get it converted and then compare the outputs? |
Lots of good things to discuss here - a main point being that the SEG and CT are essentially two independent entities with their own spacings, dimensions, orientations, etc that are only shown together when they share a frame of reference UID (or there's a spatial registration to map between frames of reference. So we shouldn't, for example, consider the CT geometry when creating the SEG object, but rather create the most faithful representation of the input data. |
I agree with Steve, this is a perfect summary! Also, since I wrote the above, I realized that original segmentations were created in NIfTI format using nnU-Net, which were then converted into DICOM SEG using dcmqi. Change in image orientation most likely happened during NIfTI conversion. A separate question is why itkWidgets don't seem to be able to correctly render segmentation label that has a different orientation compared to the image? Is this a bug? |
Yes, this does seem to be the source of the problem. What would you like to do? A few ideas:
Yes, we are trying to use the metadata of the CT and SEG as encoded individually in each. But that input metadata appears to have issues.
This is already the case. In fact, we even use an interpolator with better than nearest-neighbor interpolation for labels, available in a small, universal ITK-Wasm python package :-). If we apply the CT metadata to the SEG, this is what we get: Note that it is also incorrect -- the heart and esophagus are inverted. This is what the current metadata is specifying: The empty box is the domain of the SEG -- vtk.js has a limitation of only rendering one volume.
Most excellent!! 🎇 Done. 🍾 |
Simplify by using itkwasm-dicom instead of pydicom-seg. Also use the s5cmd Python package.
c38adef
to
b951799
Compare
I hadn't realized that, but yes, one of the liver segs here has incorrect geometry. We should get the data fixed and not use this for a demonstration or tutorial (unless we want to warn about bad metadata). |
@thewtex I don't see what are the issues with the data - the image is oriented differently, but I am not aware of any issues with the metadata. It works fine in Slicer, which is using dcmqi, screenshot below. You can see this series visualized in OHIF, which is using completely independent DICOM readers: https://viewer.imaging.datacommons.cancer.gov/v3/viewer/?StudyInstanceUIDs=1.2.840.113654.2.55.133032926508606330165457723341736723804&SeriesInstanceUIDs=1.2.840.113654.2.55.247854884634057477137769379611681725965,1.2.276.0.7230010.3.1.3.481034752.249602.1661572065.734219.
Where is this taking place? I did not see any resampling in the notebook code, unless I missed it.
@pieper which sample are you referring to? I do not see any liver segmentations in the sample used in the notebook: https://viewer.imaging.datacommons.cancer.gov/v3/viewer/?StudyInstanceUIDs=1.2.840.113654.2.55.133032926508606330165457723341736723804&SeriesInstanceUIDs=1.2.840.113654.2.55.247854884634057477137769379611681725965,1.2.276.0.7230010.3.1.3.481034752.249602.1661572065.734219. |
Thanks for the link to the actual data @fedorov. The data I was looking at came from a different study, but I don't have the uid handy. So there is a dataset with a bad liver segmentation geometry but it's not the one from this issue. Sorry for the extra confusion. @thewtex - since Andrey and I confirmed the geometry is read correctly in OHIF and Slicer for StudyInstanceUID 1.2.840.113654.2.55.133032926508606330165457723341736723804 can you show and itk widgets example for it? The seg and the referenced series uids are:
|
Here is the metadata I get for the CT when loaded in 3D Slicer: I was not able to load the This seems to be different from what we get in this notebook,
I suspect there is a difference with how the CT is loaded and interpreted.
Yes, that is what is in this PR.
This is part of the rendering process. |
Well, we also have LPS / RAS to account for. |
This may be enlightening. |
Can you tell me what OS you are on? I just uninstalled/installed, and everything works for me on Mac with 5.6.2. I checked cdash, and I do see an error for stable mac build for today, which seems to be an intermittent failure to clone the repo: https://slicer.cdash.org/builds/3504732/configure. I also tested on 5.7.0, and did not see any problems.
This part is tricky with my knowledge of Slicer.... The issue is that segmentations are not loaded into Slicer scalar volumes, but into "Slicer Segmentations". The only way I know of to see volume-level metadata (spacing, orientation, etc) is to export "Segmentation" into a volume, but that operation takes an image volume as a reference, so the result will not tell us what you want to know... Maybe @pieper or @lassoan can help here? How can we know the metadata for loaded segmentation similar to what Volumes module shows as in #757 (comment)? |
My suspicion is that resampling is not done correctly in itkwidgets. |
Doesn't that export process take reference volume as reference, and resamples to that reference? It would always match the geometry of the reference then, but it does not reflect geometry "as loaded". |
No, I don't think it is in the reading process. As I tried to explain earlier, I am pretty certain this is happening in the process of generating the original representation of the segmentation by nnU-Net that is then converted into SEG. This is the approximate provenance of the SEG we are looking at: [DICOM CT] --> nnU-Net --> [NIfTI] --> dcmqi --> [DICOM SEG] --> dcmqi --> [NRRD] --> Slicer There is no way around it - we should just accept that orientations may differ, and make sure resampling is implemented correctly for the systems that don't render in patient space. |
Actually, the pipeline is: [DICOM CT] --> [NIfTI] --> nnU-Net --> [NIfTI] --> dcmqi --> [DICOM SEG] --> dcmqi --> [NRRD] --> Slicer And it's possible that the first conversion from dicom to nii introduced a reorganization of the data. By the "something in the reading process is converting the SEG to Axial IS." what I mean is that the CT and the SEG have different ImageOrientationPatient vectors in the instances, but they end up having the same IJK to RAS directions in Slicer, so they are being reorganized as part of that process. I believe it's because the data gets reshuffled in order to make the IJKToRAS transform right handed. |
Very helpful, thanks, Steve! When we read the CT in this notebook, it looks consistent with Slicer. But the SEG is not consistent. As IJK->RAS is consistent between the CT and SEG, we should see a consistent IJK->LPS.
The bounding box of the volumes, which is independent of any resampling, is showing that there are issues independent of resampling.
Linux 🐧
I wonder if we can capture the NRRD here? We could compare the header to a NRRD generated by |
You can do that step running
Compared to what I see in Slicer when I load the resulting NRRD as a volume. |
@pieper from the above, comparing volume metadata between what you exported from Segmentations and what I loaded directly from SEG NRRD, clearly there is a resampling to reference that is happening (509 slices vs 510). Just wanted to bring your attention to this. |
itkwidget's conversion of images to NGFF is dropping the direction array. I see the correct seg direction matrix in itkwidget's JS layer and correctly rendered images when I short circuit |
Scary stuff! I didn't realize that in order to render the image it first has to be converted into ngff-zarr. Glad you traced it down. Hope it is solvable? |
Following our Get Your Brain Together HCK03 and further work by @bogovicj, we now have an OME-Zarr RFC on Coordinate systems and transformations that includes a |
This is great @thewtex 👍 Do we have an example of a lossless nrrd <--> ome-zarr conversion process? I would love to see (and/or help with) a file plugin for Slicer. |
I will work on these. |
No description provided.