MIC-DKFZ / nnUNet

Apache License 2.0
5.6k stars 1.71k forks source link

Inconsistent Axis Order in `median_image_size_in_voxels` After Running `nnUNet_plan_and_preprocess` on Different Datasets #2410

Open KaterinaKrejci231054 opened 1 month ago

KaterinaKrejci231054 commented 1 month ago

Hello,

We noticed that when running nnUNet_plan_and_preprocess on two different datasets separately, the order of axis (median_image_size_in_voxels) is changed in a different way:

Using <class 'nnunetv2.imageio.nibabel_reader_writer.NibabelIO'> reader/writer
3D fullres U-Net configuration:
{'data_identifier': 'nnUNetPlans_3d_fullres', ... , 'median_image_size_in_voxels': array([242., 368., 192.])

It seems that for the first dataset, two last axes are swapped: [242, 192, 368] --> [242, 368, 192] But for the second dataset, the first and third axes are swapped: [64, 320, 300] --> [300, 320, 64]

GregorKoehler commented 3 weeks ago

Hi @KaterinaKrejci231054,

as Nibabel loads images in a different order than SimpleITK, nnUNet reorders the axes according to this line: https://github.com/MIC-DKFZ/nnUNet/blob/9cd9d80ab3d9542138422f33154ee58421a92088/nnunetv2/imageio/nibabel_reader_writer.py#L53-L54

So the reordering in your second dataset seems to be as expected, but not the re-ordering in the first case.

Can you confirm that the two datasets are identical in the affine matrices as well?

KaterinaKrejci231054 commented 3 weeks ago

Hello @GregorKoehler,

thank you for your reply. The datasets have different affine matrices because the data comes from different sites and different contrasts (MP2RAGE and T2w).

We are wondering how the affine matrices are taken into account during the axes reordering (as they might differ even between subjects within the same dataset)?

valosekj commented 1 week ago

Based on this comment, it seems that nnU-Net transposes images based on the spacing (resolution):

so nnU-Net transposes 3D images such that the dimension with the highest resolution (lowest spacing) is in front.

This would explain the axes swapping described in the first comment:

first dataset: [242, 192, 368] (spacing: [0.70652175, 0.69999725, 0.70652175]) --> [242, 368, 192] second dataset: [64, 320, 300] (spacing: [0.79999882, 0.80000001, 0.80000007]) --> [300, 320, 64]

GregorKoehler commented 1 week ago

Thanks for the pointer @valosekj ! Concerning how affines are taking into account, I think https://github.com/MIC-DKFZ/nnUNet/blob/bb1b8090f01a1a7e175b74fa5fbb61935a292f8f/nnunetv2/experiment_planning/experiment_planners/default_experiment_planner.py#L405 and https://github.com/MIC-DKFZ/nnUNet/blob/bb1b8090f01a1a7e175b74fa5fbb61935a292f8f/nnunetv2/experiment_planning/experiment_planners/default_experiment_planner.py#L215-L226

are worth taking a look at.