-
-
Notifications
You must be signed in to change notification settings - Fork 127
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
Mirror issue #166
Comments
So i have been searching for couple of hours and i have a problem to really find any DICOM dataset that starts from top-to-bottom. I only found one dataset, which was behaving really odly with file ordering, so it might have not been even top-to-bottom and it was sorted artificially. For simpleITK image sequence importer this should work. IsHeadFeetDataset method is here
TryGetPositionInPatient method is here
For simpleITK file importer it should be something like this. The issue is, i cannot really read slice position metadata from nrrd. This is a showcase for SimpleITK importer, something like this should be probably added to every importer if it is having same mirror problems. |
Oh, wow that's actually a pretty big issue. I hadn't noticed it all this time. Thanks for reporting! And yes, I think that would be a good solution! |
@mlavik1 After further testing, the ExtractSlice method does work, it extracts the slice but i cant really get it to extract any metadata from the specific slice. The metadata array is always empty. The ImageFileReader contains overall metadata, but that is not really helpful. Do you know the way how to extract the specific slice metadata from formats like nrrd or nifti? Is it even possible?
My temporary suggestion: If it contains the position metadata and the flip is required, lets flip it. If there is no metadata, it will not do anything with possibility that it might be incorrectly mirrored. I think majority of the datasets are from feet-to-head, so lets default to that. When somebody loads the head-to-feet dataset with no location metadata, it will mirror, we can add option to flip it in realtime to manually correct it. This would be temporary solution. We should probably still find better way to do it, if it is possible. Well I could probably make PR if the metadata extraction from files like nrrd an nifti worked. So it is still an open issue. |
Hi @SitronX Yes, I agree with your suggestion. I'm not sure what we could do if the position tag is missing.. My first thought was to use the location tag, but apparently that is " relative to an unspecified implementation specific reference point". I guess if they scanned a patient top-to-bottom without adding a position element then that is probably a mistake, that would cause issues in other software as well? If we find a head-to-bottom dataset we could probably verify that by removing the position tag and trying to import it elsewhere. I have a bunch of DICOM datasets I can test with as well, and also some NRRD/NIFTI. I'll see if I can have a look at it tomorrow or in the weekend. After that I'll be away for a week :) |
@mlavik1 |
Hi @SitronX ! I'll also start creating a PR based on the changes you posted above (saw you pushed them to your repo as well). |
Hello @mlavik1 The sequenceSeries reverse as i showed above in SimpleITKImageSequenceImporter.cs is wrong. It needs to be read normally and then the whole pixelData array at the end must be reversed similarly as it is done in SimpleITKFileImporter.cs. Otherwise the data will be little bit corrupted due to wrong pixel ordering between the slices. |
Ok, thanks for the info! :) |
Hi again! And regarding NRRD: It seems to have a "space" field: https://teem.sourceforge.net/nrrd/format.html. Could that be what we're looking for? Do you have some NRRD files that have a different orientation / coordinate system, or are all your NRRD datasets similar as well? I pushed my suggested changes here: https://github.com/mlavik1/UnityVolumeRendering/tree/coordinate-systems |
Hello @mlavik1
Yes i think that is right. With Z, head should always have higher vale than feet. I havent found anything saying otherwise.
Aha, you are right. Supposedly, DICOM should always be stored in LPS. If you view DICOM in Slicer3D, Slicer3D specifically
In my code above, not every slice is checked for position. Only first and last slice of dataset is checked and Z is compared, to determine the type of acquisition. While the LPS should always be the case, i dont think it actually tells the acquisition order. I think it is just a coordinate system, and both head-to-feet or feet-to-head dataset can use same coordinate system, while acquisition order would be different. It would still mean, that head has higher Z value than feet, thus it is increasing towards the head. But without checking Z value, either head-to-feet or feet-to-head would still cause mirror issue (depending if it is flipped defaulty). Here are described possible types of scans, I have also found this interesting post from user, where he was dealing with same problem, this was sent to him. Which describes to him how it should be dealt with. The lady mentiones there, that these tags are the only reliable way how to represent dataset correctly (in right acquisition order). It is really interesting read, i recommend it. It is also possible to get acquisition order from the already mentioned tag, but this tag is not required and might be missing sometimes. Reading Z value from slice position in patient is reliable, because the position tag should always be there.
Yes you are right, the orientation is slightly different and i had to correct it. Switching axis like you said (x=-x, y=z, z=-y) would probably be better, if it works :D So i have checked your solution, and you have it backwards, cause my nrrd mirrors :D You have and it should be
The data reverse should happen, if it is feet-to-head dataset. (Edit: Just noticed you have it switched only in file reader, sequence reader is alright) But i havent checked the rest of the code, i only tested the one nrrd i have :D |
Hi @SitronX Thanks for the extra info! That mailing list reply you linked was really informative :)
Ah, yes, acquisition order might be in any direction. So if we simply used the SimpleItk DICOM reader to read the dataset slice by slice and then manually tried to construct a dataset (like that person asking in the mailing list), we would need to order the slices ourselves. However, since we're using the
Ooops! You're right haha. I'l lfix that right away :D
Thanks, I'll try out those datasets! |
haha sorry for the confusion :D You are right. So supposedly the GetGDCMSeriesFileNames() handles the ordering. It is not exactly specified how, but it says it orders it with several strategies. So that means, that the ordering should be done automatically for us with SimpleITK and ImageSeriesReader. Since SimpleITK handles this ordering in ImageSeriesReader, is it possible that something similar happens with FileImporter, where it loads it automatically in same way (feet first), no matter what type of scan it is? So that would mean the only required thing is to defaultly flip it and it should always be correct no matter the scan type, cause SimpleITK should always order it as feet first. But hey, atleast here is a path how to fix the standard dicom loader, if SimpleITK is not used :D Again, sorry for the confusion. I just wish the itk/simpleITK documentation was more detailed on this topic. |
Hi again @SitronX ! Oh, right! That might be the function that does it then :)
Yes, I think that's the case! So it might seem like SimpleITK reads the coordinate space, but only converts to LPS on demand, so we should probably do that :)
Yes, that's right! It already reads the position tag and uses that to order the slices (see
Yes, it's hard to find out exactly what's going on. So the solution to this issue would then be to:
Is that right? Regarding the second one, reversing the pixel array is definitely the simplest fix. We might want to swap it in place though, instead of how it's done now, to avoid extra memory allocations (these arrays can be big! haha) |
Yep, that sound great.
Ahh, that is actually great solution. Changing the x scale to -x of the rendered object. This is so much better than reversing the array and so simple. I am gonna ditch reversing the array in my project and use this instead :D |
Before you celebrate: Doing that will apparently break the slicing plane tool 😅 I'll make a new branch with the changes we talked about, so we can eventually create a PR :) |
Ok, I think the PR should be ready for review now: #170 It has a lot of changes, so if there's something there you disagree with or think should be different please let me know 😁 I think the SimpleITK importer is the most important to fix, and then I can do a separate PR for fixing the OpenDICOM importer. |
Fixed for the Open DICOM importer as well! |
Hello @mlavik1,
I have encountered very particular issue. When dataset comes from CT machine, i guess it can be scanned two ways. The patient is either scanned from head to feet, or from feet to head.
The major issue is, when the patient is scanned from feet to head, the library doesnt know that and after careful observation, all organs are mirror flipped (organs that should be in left part of the body are in right part).
I also havent noticed that before, but surgeons noticed :)
The simple temporary fix for these specific datasets is to reverse the data texture array, before the texture is generated. Like this (same for gradient texture)
It will then correctly show the dataset, maybe rotated around little bit, but organs are not mirror flipped anymore and it matches.
The issue is, this is needed only for CT scans that are from feet to head, CT scans from head to feet are probably rendering correctly (I dont have head to feet datasets).
The library should ideally detect how are the data stored and then subsequently flip the array if needed. I guess comparing two slice positions and recognizing which type of scan it is should work.
Here is how the dataset looks in Slicer3D for comparison
FeetToHead.mp4
This is how it looks in this version of the library, organs are basically mirror flipped
This is after reversing the texture array, organs are now in correct place similar to Slicer3D
The pictures are only for position comparisons, i probably have slightly different density interval on both pictures.
The text was updated successfully, but these errors were encountered: