Question Regarding Validation of DWI data

I am currently stuck uploading another externally validated BIDS dataset due to the following error:

1: [ERR] The number of volumes in this scan does not match the number of volumes in the corresponding .bvec and .bval files. (code: 29 - VOLUME_COUNT_MISMATCH)
		./sub-1/dwi/sub-1_rec-ADC_dwi.nii.gz
		./sub-1/dwi/sub-1_rec-TRACE_dwi.nii.gz
		./sub-10/dwi/sub-10_rec-ADC_dwi.nii.gz
		./sub-10/dwi/sub-10_rec-TRACE_dwi.nii.gz
		./sub-100/dwi/sub-100_rec-ADC_dwi.nii.gz
		./sub-100/dwi/sub-100_rec-TRACE_dwi.nii.gz
		./sub-1000/dwi/sub-1000_rec-ADC_dwi.nii.gz
		./sub-1000/dwi/sub-1000_rec-TRACE_dwi.nii.gz
		./sub-1001/dwi/sub-1001_rec-ADC_dwi.nii.gz
		./sub-1001/dwi/sub-1001_rec-TRACE_dwi.nii.gz
		... and 3420 more files having this issue (Use --verbose to see them all).

We have confirmed that the data and associated .bvec and .bvals are correct.

In our top level directory we have two files which are identical for each participant
dwi.bval (a single value of 0)
dwi.bvec (a single column with three rows, all set to 0)

Any advice getting past this error would be appreciated.

Notably, the -i option will not allow me to ignore this error when uploading.

Best,

Roger

Hi @rogiedodgie,

I am not sure if dwi.bval/bvec is inherited across all the files like .jsons are. Does it work if you subject-ify it for a single subject?

Best,
Steven

Sure thing, here is the fslinfo readout for two files:

fslinfo sub-1_rec-TRACE_dwi.nii.gz 
data_type	INT16
dim1		256
dim2		256
dim3		26
dim4		1
datatype	4
pixdim1		0.937500
pixdim2		0.937500
pixdim3		5.999999
pixdim4		0.000000
cal_max		0.000000
cal_min		0.000000
file_type	NIFTI-1+
fslinfo sub-1_rec-ADC_dwi.nii.gz
data_type INT16
dim1 256
dim2 256
dim3 26
dim4 1
datatype 4
pixdim1 0.937500
pixdim2 0.937500
pixdim3 5.999999
pixdim4 0.000000
cal_max 0.000000
cal_min 0.000000
file_type NIFTI-1+

The dwi.bval and dwi.bvec files are the same for everyone and contained in the top level directory of our project folder. They are here:
https://drive.google.com/drive/folders/1K_hbxhR_KqQChk5E9Cy3isut87jttX1R?usp=sharing

Best,

Roger

Hi @rogiedodgie,

As I edited my original answer to, try putting them in subject folders with the subject prefixes like your ADC/TRACE files, since bvals and bvecs may not follow the BIDS inheritance principle like JSONS and TSVs.

Best,
Steven

I changed the file structure to this:
image
Updated folder for sub_1 here:
https://drive.google.com/drive/folders/1K_hbxhR_KqQChk5E9Cy3isut87jttX1R?usp=drive_link

And still got the following error:

1: [ERR] The number of volumes in this scan does not match the number of volumes in the corresponding .bvec and .bval files. (code: 29 - VOLUME_COUNT_MISMATCH)
	./sub-1/dwi/sub-1_rec-ADC_dwi.nii.gz
	./sub-1/dwi/sub-1_rec-TRACE_dwi.nii.gz
	./sub-10/dwi/sub-10_rec-ADC_dwi.nii.gz
	./sub-10/dwi/sub-10_rec-TRACE_dwi.nii.gz
	./sub-100/dwi/sub-100_rec-ADC_dwi.nii.gz
	./sub-100/dwi/sub-100_rec-TRACE_dwi.nii.gz
	./sub-1000/dwi/sub-1000_rec-ADC_dwi.nii.gz
	./sub-1000/dwi/sub-1000_rec-TRACE_dwi.nii.gz
	./sub-1001/dwi/sub-1001_rec-ADC_dwi.nii.gz
	./sub-1001/dwi/sub-1001_rec-TRACE_dwi.nii.gz
	... and 3420 more files having this issue (Use --verbose to see them all).

Please visit https://neurostars.org/search?q=VOLUME_COUNT_MISMATCH for existing conversations about this issue.

See also : Multiple Lesion Masks for BIDS - #5 by neurolabusc

Thanks for helping me with this!

Roger

I’m able to reproduce this with a 3D dwi file. You could fix this by setting dim0 to 4 instead of 3.

We can open an issue on the validator to permit 3D DWI files, assuming that does not contradict the spec.

@effigies thanks. I think the validator should either to permit 3D DWI files, or allow 3D DWI files not to have bvec/bval files. The specific issue we are having is for non-directional diffusion measures like TRACE and ADC.

1 Like

I added that option to the issue. Linking here: 3D DWI files produce are not marked as invalid, but fail VOLUME_COUNT_MISMATCH · Issue #1858 · bids-standard/bids-validator · GitHub

@effigies do you have any clues how I can set dim[0] using nibabel. I think nibabel sets this depending on the image shape. nibabel provides functions to set many properties for example, the code below will set the intention for each dwi file, but I can not work out how to modify dim[0]:

import os
import nibabel as nib

def set_header(file_path):
    try:
        # Load the NIfTI file
        nifti_img = nib.load(file_path)

        # Set the header description field
        nifti_img.header.set_intent(0)

        # Save the modified NIfTI file
        nib.save(nifti_img, file_path)
        print(f"{file_path}: Header modified'.")
        
    except nib.filebasedimages.ImageFileError:
        print(f"{file_path}: Error loading the NIfTI file.")

def find_and_set_header(directory):
    # Iterate through all files in the directory
    for root, dirs, files in os.walk(directory):
        for file in files:
            # Check if the file ends with "dwi" and has a NIfTI extension
            if file.lower().endswith("dwi.nii.gz") or file.lower().endswith("dwi.nii"):
                file_path = os.path.join(root, file)
                set_header(file_path)

# Specify the directory to search for NIfTI files
search_directory = "/Users/chris/bx"

# Find and set the header description for DWI files in the specified directory
find_and_set_header(search_directory)

We may non-optionally set the dim from dataobj.shape.

The obvious thing to do would be:
img.header['dim'][0] = 4

If that doesn’t work, you can create a new image:

from nibabel.arrayproxy import reshape_dataobj
new_img = nb.Nifti1Image(
    reshape_dataobj(img.dataobj, img.shape + (1,)),
    None,
    img.header,
)

Edit: Confirmed, img.header['dim'][0] = 4 or img.header.set_data_shape(img.shape + (1,)) ultimately get overridden by the array shape during save. So reshaping the dataobject is the way to do it.

@effigies great your trick worked and provides a kludge to pass the existing validator. In case anyone runs into this issue, here was a script that makes any dwi scan report dim[0] as 4.

import os
import nibabel as nib
from nibabel.arrayproxy import reshape_dataobj

def set_header(file_path):
    try:
        # Load the NIfTI file
        nifti_img = nib.load(file_path)
        new_img = nib.Nifti1Image(
            reshape_dataobj(nifti_img.dataobj, nifti_img.shape + (1,)),
            None,
            nifti_img.header,
        )
        # Save the modified NIfTI file
        nib.save(new_img, file_path)
        print(f"{file_path}: Header modified'.")
        
    except nib.filebasedimages.ImageFileError:
        print(f"{file_path}: Error loading the NIfTI file.")

def find_and_set_header(directory):
    # Iterate through all files in the directory
    for root, dirs, files in os.walk(directory):
        for file in files:
            # Check if the file ends with "dwi" and has a NIfTI extension
            if file.lower().endswith("dwi.nii.gz") or file.lower().endswith("dwi.nii"):
                file_path = os.path.join(root, file)
                set_header(file_path)

# Specify the directory to search for NIfTI files
search_directory = "/path/to/images"

# Find and set the header description for DWI files in the specified directory
find_and_set_header(search_directory)
2 Likes