netneurolab / neuromaps

A toolbox for comparing brain maps
https://netneurolab.github.io/neuromaps
Other
238 stars 53 forks source link

TypeError: argument should be a str or an os.PathLike object where __fspath__ returns a str, not 'Nifti1Image' [BUG] #166

Closed LuRoe7 closed 2 weeks ago

LuRoe7 commented 3 months ago

Issue summary

When I try to run the Parcellater class, I get the error: TypeError: argument should be a str or an os.PathLike object where fspath returns a str, not 'Nifti1Image'. I expect the error to be related to nibabel and python3.12/pathlib.py, as indicated in the detailed error message below.

I am using a virtual environment, hence I could easily downgrade any packages if required.

Detailed issue description

This is the full error message:


TypeError Traceback (most recent call last) Cell In[11], line 7 2 parcellation = Parcellater(parcellation=atlas, 3 space='MNI152', 4 resampling_target='data', 5 hemi=None) 6 # parcellate statistical brain maps of choice ----> 7 statmap_struct_parc = parcellation.fit_transform(data=statmap_struct, 8 space='MNI152', 9 ignore_background_data=False, 10 background_value=None, 11 hemi=None) 12 # parcellate statistical brain maps of choice 13 statmap_func_parc = parcellation.fit_transform(data=statmap_func, 14 space='MNI152', 15 ignore_background_data=False, 16 background_value=None, 17 hemi=None)

File ~/ve_general/lib/python3.12/site-packages/neuromaps/parcellate.py:222, in Parcellater.fit_transform(self, data, space, ignore_background_data, background_value, hemi) 219 def fit_transform(self, data, space, ignore_background_data=False, 220 background_value=None, hemi=None): 221 """Prepare and perform parcellation of data.""" --> 222 return self.fit().transform(data, space, ignore_background_data, 223 background_value, hemi)

File ~/ve_general/lib/python3.12/site-packages/neuromaps/parcellate.py:155, in Parcellater.transform(self, data, space, ignore_background_data, background_value, hemi) 153 else: 154 resampling_method = 'linear' --> 155 data, parc = resample_images(data, self.parcellation, 156 space, self.space, hemi=hemi, 157 resampling=self._resampling, 158 method=resampling_method) 160 if ((self.resampling_target == 'data' 161 and space.lower() == 'mni152') 162 or (self.resampling_target == 'parcellation' 163 and self._volumetric)): 164 data = nib.concat_images([nib.squeeze_image(data)])

File ~/ve_general/lib/python3.12/site-packages/neuromaps/resampling.py:252, in resample_images(src, trg, src_space, trg_space, method, hemi, resampling, alt_spec) 249 trg, src = mni_transform(trg, src, trg_space, src_space, 250 method=method, hemi=hemi) 251 elif src_space == 'MNI152' and trg_space == 'MNI152': --> 252 src, trg = load_nifti(src), load_nifti(trg) 253 srcres = np.prod(nib.affines.voxel_sizes(src.affine)) 254 trgres = np.prod(nib.affines.voxel_sizes(trg.affine))

File ~/ve_general/lib/python3.12/site-packages/neuromaps/images.py:136, in load_nifti(img) 134 except (TypeError) as err: 135 if not ("os.PathLike" in str(err) and "not Nifti1Image" in str(err)): --> 136 raise err 137 return img

File ~/ve_general/lib/python3.12/site-packages/neuromaps/images.py:133, in load_nifti(img) 116 """ 117 Load nifti file img. 118 (...) 130 Loaded NIFTI image 131 """ 132 try: --> 133 img = nib.load(img) 134 except (TypeError) as err: 135 if not ("os.PathLike" in str(err) and "not Nifti1Image" in str(err)):

File ~/ve_general/lib/python3.12/site-packages/nibabel/loadsave.py:96, in load(filename, kwargs) 81 def load(filename: FileSpec, kwargs) -> FileBasedImage: 82 r"""Load file given filename, guessing at file type 83 84 Parameters (...) 94 Image of guessed type 95 """ ---> 96 filename = _stringify_path(filename) 98 # Check file exists and is not empty 99 try:

File ~/ve_general/lib/python3.12/site-packages/nibabel/filename_parser.py:41, in _stringify_path(filepath_or_buffer) 25 def _stringify_path(filepath_or_buffer: FileSpec) -> str: 26 """Attempt to convert a path-like object to a string. 27 28 Parameters (...) 39 https://github.com/pandas-dev/pandas/blob/325dd68/pandas/io/common.py#L131-L160 40 """ ---> 41 return pathlib.Path(filepath_or_buffer).expanduser().as_posix()

File /usr/lib/python3.12/pathlib.py:1164, in Path.init(self, args, kwargs) 1161 msg = ("support for supplying keyword arguments to pathlib.PurePath " 1162 "is deprecated and scheduled for removal in Python {remove}") 1163 warnings._deprecated("pathlib.PurePath(kwargs)", msg, remove=(3, 14)) -> 1164 super().init(args)

File /usr/lib/python3.12/pathlib.py:373, in PurePath.init(self, *args) 371 path = arg 372 if not isinstance(path, str): --> 373 raise TypeError( 374 "argument should be a str or an os.PathLike " 375 "object where fspath returns a str, " 376 f"not {type(path).name!r}") 377 paths.append(path) 378 self._raw_paths = paths

TypeError: argument should be a str or an os.PathLike object where fspath returns a str, not 'Nifti1Image'

Steps to reproduce issue

# import modules
import re
import glob
import os
import nibabel as nb
import numpy as np
import pandas as pd
from neuromaps.parcellate import Parcellater
from neuromaps import images, nulls, resampling,transforms
from neuromaps.stats import compare_images
from neuromaps.datasets import fetch_annotation, available_annotations
from neuromaps.resampling import resample_images
from netneurotools import datasets as nntdata
from neuromaps.images import dlabel_to_gifti
import gseapy as gp
from gseapy import dotplot
import matplotlib.pyplot as plt

# specify input directory
input_dir = "/home/lukas/Desktop/Science/Projects/Genetic-Receptors_Neuro_Clinic/data/esprit/"
# load statistical brainmap
statmap_struct = os.path.join(input_dir,"statmaps","esprit_statmap_namnis_t1.nii.gz")
# specify directory in which all required atlases and templates are stored
atlas_dir = "/home/lukas/Desktop/Science/MRI/Atlases/"
# load atlas
atlas = os.path.join(atlas_dir,"Brainnetome","BN_Atlas_246_MNI152NLin2009cAsym_2mm_3D.nii.gz")

# set up parcellation object with atlas of choice
parcellation = Parcellater(parcellation=atlas,
                           space='MNI152',
                           resampling_target='data',
                           hemi=None)
# parcellate statistical brain maps of choice
statmap_struct_parc = parcellation.fit_transform(data=statmap_struct,
                                                 space='MNI152',
                                                 ignore_background_data=False,
                                                 background_value=None,
                                                 hemi=None)

Software version

neuromaps 0.5.0 nibabel 5.2.1 python 3.12

Code of Conduct

LuRoe7 commented 3 months ago

I just downgraded nibabel to version 4.0.0 and the error is solved!

VinceBaz commented 3 months ago

Hey @LuRoe7,

This bug is due to an update of the pathlib module in Python 3.12! Some of the error messages that pathlib.Path raises have changed, so we need to update our load functions to fix this issue. We opened a PR a couple of months ago to fix the deprecated functions in Python 3.12. but we haven't had time to complete it yet. We'll try to fix these issues as soon as possible :smile:

It seems like downgrading to nibabel version 4.0.0 works, which is great, but an alternative (if you run into similar issues or would like to use new functionalities from newer versions of nibabel) would be to downgrade to Python 3.10!

We apologize for these issues, and we'll let you know when it's fixed.

liuzhenqi77 commented 2 weeks ago

Fixed by #173