codecov[bot]: # [Codecov](https://codecov.io/gh/HBClab/NiBetaSeries/pull/289?src=pr&el=h1) Report
> Merging [#289](https://codecov.io/gh/HBClab/NiBetaSeries/pull/289?src=pr&el=desc) into [master](https://codecov.io/gh/HBClab/NiBetaSeries/commit/e8e367021a63fad37db43f95045c6d7ea6894d5b&el=desc) will **decrease** coverage by `0.01%`.
> The diff coverage is `100.00%`.


```diff
@@            Coverage Diff             @@
##           master     #289      +/-   ##
==========================================
- Coverage   89.34%   89.33%   -0.02%     
==========================================
  Files          10       10              
  Lines         723      722       -1     
  Branches      109      109              
==========================================
- Hits          646      645       -1     
  Misses         45       45              
  Partials       32       32              
```

diff --git a/src/nibetaseries/interfaces/nistats.py b/src/nibetaseries/interfaces/nistats.py
index 88e8c6d..44818fd 100644
--- a/src/nibetaseries/interfaces/nistats.py
+++ b/src/nibetaseries/interfaces/nistats.py
@@ -7,6 +7,7 @@ from nipype.interfaces.base import (
     OutputMultiPath, File, LibraryBaseInterface,
     SimpleInterface, traits
     )
+import nibabel as nib
 
 
 class NistatsBaseInterface(LibraryBaseInterface):
@@ -14,12 +15,14 @@ class NistatsBaseInterface(LibraryBaseInterface):
 
 
 class LSSBetaSeriesInputSpec(BaseInterfaceInputSpec):
-    bold_file = File(exists=True, mandatory=True,
-                     desc="The bold run")
+    bold_file = traits.Either(File(exists=True, mandatory=True,
+                                   desc="The bold run"),
+                              nib.spatialimages.SpatialImage)
     bold_metadata = traits.Dict(desc='Dictionary containing useful information about'
                                 ' the bold_file')
-    mask_file = File(exists=True, mandatory=True,
-                     desc="Binarized nifti file indicating the brain")
+    mask_file = traits.Either(File(exists=True, mandatory=True,
+                              desc="Binarized nifti file indicating the brain"),
+                              nib.spatialimages.SpatialImage)
     events_file = File(exists=True, mandatory=True,
                        desc="File that contains all events from the bold run")
     confounds_file = traits.Either(None, File(exists=True),
@@ -46,7 +49,6 @@ class LSSBetaSeries(NistatsBaseInterface, SimpleInterface):
 
     def _run_interface(self, runtime):
         from nistats import first_level_model
-        import nibabel as nib
         import os
 
         # get t_r from bold_metadata
@@ -123,12 +125,14 @@ class LSSBetaSeries(NistatsBaseInterface, SimpleInterface):
 
 
 class LSABetaSeriesInputSpec(BaseInterfaceInputSpec):
-    bold_file = File(exists=True, mandatory=True,
-                     desc="The bold run")
+    bold_file = traits.Either(File(exists=True, mandatory=True,
+                                   desc="The bold run"),
+                              nib.spatialimages.SpatialImage)
     bold_metadata = traits.Dict(desc='Dictionary containing useful information about'
                                 ' the bold_file')
-    mask_file = File(exists=True, mandatory=True,
-                     desc="Binarized nifti file indicating the brain")
+    mask_file = traits.Either(File(exists=True, mandatory=True,
+                              desc="Binarized nifti file indicating the brain"),
+                              nib.spatialimages.SpatialImage)
     events_file = File(exists=True, mandatory=True,
                        desc="File that contains all events from the bold run")
     confounds_file = traits.Either(None, File(exists=True),
@@ -153,7 +157,6 @@ class LSABetaSeries(NistatsBaseInterface, SimpleInterface):
 
     def _run_interface(self, runtime):
         from nistats import first_level_model
-        import nibabel as nib
         import os
 
         # get t_r from bold_metadata

allow users to pass nibabel objects to nistats interfaces
**Is your feature request related to a problem? Please describe.**
I'm running a [butt-ton of simulations using the lss/lsa interfaces](https://github.com/jdkent/betaSeriesSimulations/blob/31230b13a79d245eb36dae42b941095300ac293f/beta_sim/workflow.py#L165-L180) and one choke point is reading/writing the simulated nifti file to disk before calculating the betaseries.

**Describe the solution you'd like**
It would be nice to to pass the nibabel image in python directly into the interface so that intermediate writes are not required.

**Describe alternatives you've considered**
N/A

**Additional context**
N/A
diff --git a/src/nibetaseries/interfaces/tests/test_nistats.py b/src/nibetaseries/interfaces/tests/test_nistats.py
index 9c9ac8a..094272d 100644
--- a/src/nibetaseries/interfaces/tests/test_nistats.py
+++ b/src/nibetaseries/interfaces/tests/test_nistats.py
@@ -4,21 +4,33 @@ import json
 
 import pytest
 
+
 from ..nistats import (LSSBetaSeries, LSABetaSeries,
                        _lss_events_iterator, _lsa_events_converter,
                        _select_confounds)
 
 
+@pytest.mark.parametrize("use_nibabel", [(True), (False)])
 def test_lss_beta_series(sub_metadata, preproc_file, sub_events,
-                         confounds_file, brainmask_file):
+                         confounds_file, brainmask_file, use_nibabel):
+    """Test lss interface with nibabel nifti images
+    """
+    if use_nibabel:
+        import nibabel as nib
+        bold_file = nib.load(str(preproc_file))
+        mask_file = nib.load(str(brainmask_file))
+    else:
+        bold_file = str(preproc_file)
+        mask_file = str(brainmask_file)
+
     selected_confounds = ['white_matter', 'csf']
     hrf_model = 'spm'
     with open(str(sub_metadata), 'r') as md:
         bold_metadata = json.load(md)
 
-    beta_series = LSSBetaSeries(bold_file=str(preproc_file),
+    beta_series = LSSBetaSeries(bold_file=bold_file,
                                 bold_metadata=bold_metadata,
-                                mask_file=str(brainmask_file),
+                                mask_file=mask_file,
                                 events_file=str(sub_events),
                                 confounds_file=str(confounds_file),
                                 selected_confounds=selected_confounds,
@@ -32,17 +44,26 @@ def test_lss_beta_series(sub_metadata, preproc_file, sub_events,
         os.remove(beta_map)
 
 
+@pytest.mark.parametrize("use_nibabel", [(True), (False)])
 def test_fs_beta_series(sub_metadata, preproc_file, sub_events,
-                        confounds_file, brainmask_file):
+                        confounds_file, brainmask_file, use_nibabel):
+    if use_nibabel:
+        import nibabel as nib
+        bold_file = nib.load(str(preproc_file))
+        mask_file = nib.load(str(brainmask_file))
+    else:
+        bold_file = str(preproc_file)
+        mask_file = str(brainmask_file)
+
     selected_confounds = ['white_matter', 'csf']
     hrf_model = 'fir'
     fir_delays = [0, 1, 2, 3, 4]
     with open(str(sub_metadata), 'r') as md:
         bold_metadata = json.load(md)
 
-    beta_series = LSSBetaSeries(bold_file=str(preproc_file),
+    beta_series = LSSBetaSeries(bold_file=bold_file,
                                 bold_metadata=bold_metadata,
-                                mask_file=str(brainmask_file),
+                                mask_file=mask_file,
                                 events_file=str(sub_events),
                                 confounds_file=str(confounds_file),
                                 selected_confounds=selected_confounds,
@@ -57,16 +78,25 @@ def test_fs_beta_series(sub_metadata, preproc_file, sub_events,
         os.remove(beta_map)
 
 
+@pytest.mark.parametrize("use_nibabel", [(True), (False)])
 def test_lsa_beta_series(sub_metadata, preproc_file, sub_events,
-                         confounds_file, brainmask_file):
+                         confounds_file, brainmask_file, use_nibabel):
+    if use_nibabel:
+        import nibabel as nib
+        bold_file = nib.load(str(preproc_file))
+        mask_file = nib.load(str(brainmask_file))
+    else:
+        bold_file = str(preproc_file)
+        mask_file = str(brainmask_file)
+
     selected_confounds = ['white_matter', 'csf']
     hrf_model = 'spm'
     with open(str(sub_metadata), 'r') as md:
         bold_metadata = json.load(md)
 
-    beta_series = LSABetaSeries(bold_file=str(preproc_file),
+    beta_series = LSABetaSeries(bold_file=bold_file,
                                 bold_metadata=bold_metadata,
-                                mask_file=str(brainmask_file),
+                                mask_file=mask_file,
                                 events_file=str(sub_events),
                                 confounds_file=str(confounds_file),
                                 selected_confounds=selected_confounds,

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest pytest-cov pytest-xdist
apt-get update apt-get install -y gcc
3.7
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
bids-validator==1.14.0
build==0.10.0
certifi @ file:///croot/certifi_1671487769961/work/certifi
charset-normalizer==3.4.1
check-manifest==0.50
ci-info==0.3.0
citeproc-py==0.6.0
click==8.1.8
codecov==2.1.13
coverage==7.2.7
cycler==0.11.0
docopt==0.6.2
duecredit==0.6.5
etelemetry==0.3.1
exceptiongroup==1.2.2
execnet==2.0.2
filelock==3.12.2
flake8==5.0.4
greenlet==3.1.1
idna==3.10
imageio==2.31.2
importlib-metadata==4.2.0
iniconfig==2.0.0
isodate==0.6.1
Jinja2==3.1.6
kiwisolver==1.4.5
lxml==5.3.1
MarkupSafe==2.1.5
matplotlib==2.2.5
mccabe==0.7.0
mne==0.18.2
networkx==2.6.3
neurdflib==5.0.1
nibabel==2.4.1
-e git+https://github.com/HBClab/NiBetaSeries.git@e8e367021a63fad37db43f95045c6d7ea6894d5b#egg=nibetaseries
nilearn==0.4.2
nipype==1.4.2
nistats==0.0.1b1
niworkflows==1.0.4
num2words==0.5.14
numpy==1.21.6
packaging==24.0
pandas==0.24.2
patsy==1.0.1
Pillow==9.5.0
pluggy==1.2.0
prov==2.0.1
pybids==0.9.5
pycodestyle==2.9.1
pydot==2.0.0
pydotplus==2.0.2
pyflakes==2.5.0
pyparsing==3.1.4
pyproject_hooks==1.2.0
pytest==7.4.4
pytest-cov==4.1.0
pytest-xdist==3.5.0
python-dateutil==2.9.0.post0
pytz==2025.2
PyWavelets==1.3.0
PyYAML==6.0.1
rdflib==6.3.2
requests==2.31.0
scikit-image==0.19.3
scikit-learn==0.19.2
scipy==1.7.3
seaborn==0.11.2
simplejson==3.20.1
six==1.17.0
SQLAlchemy==2.0.40
svgutils==0.3.4
templateflow==0.4.2
tifffile==2021.11.2
tomli==2.0.1
tqdm==4.67.1
traits==6.4.3
transforms3d==0.4.2
typing_extensions==4.7.1
urllib3==2.0.7
zipp==3.15.0

name: NiBetaSeries
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=22.3.1=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - bids-validator==1.14.0
      - build==0.10.0
      - charset-normalizer==3.4.1
      - check-manifest==0.50
      - ci-info==0.3.0
      - citeproc-py==0.6.0
      - click==8.1.8
      - codecov==2.1.13
      - coverage==7.2.7
      - cycler==0.11.0
      - docopt==0.6.2
      - duecredit==0.6.5
      - etelemetry==0.3.1
      - exceptiongroup==1.2.2
      - execnet==2.0.2
      - filelock==3.12.2
      - flake8==5.0.4
      - greenlet==3.1.1
      - idna==3.10
      - imageio==2.31.2
      - importlib-metadata==4.2.0
      - iniconfig==2.0.0
      - isodate==0.6.1
      - jinja2==3.1.6
      - kiwisolver==1.4.5
      - lxml==5.3.1
      - markupsafe==2.1.5
      - matplotlib==2.2.5
      - mccabe==0.7.0
      - mne==0.18.2
      - networkx==2.6.3
      - neurdflib==5.0.1
      - nibabel==2.4.1
      - nibetaseries==0.4.3.post1+ge8e3670
      - nilearn==0.4.2
      - nipype==1.4.2
      - nistats==0.0.1b1
      - niworkflows==1.0.4
      - num2words==0.5.14
      - numpy==1.21.6
      - packaging==24.0
      - pandas==0.24.2
      - patsy==1.0.1
      - pillow==9.5.0
      - pluggy==1.2.0
      - prov==2.0.1
      - pybids==0.9.5
      - pycodestyle==2.9.1
      - pydot==2.0.0
      - pydotplus==2.0.2
      - pyflakes==2.5.0
      - pyparsing==3.1.4
      - pyproject-hooks==1.2.0
      - pytest==7.4.4
      - pytest-cov==4.1.0
      - pytest-xdist==3.5.0
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - pywavelets==1.3.0
      - pyyaml==6.0.1
      - rdflib==6.3.2
      - requests==2.31.0
      - scikit-image==0.19.3
      - scikit-learn==0.19.2
      - scipy==1.7.3
      - seaborn==0.11.2
      - simplejson==3.20.1
      - six==1.17.0
      - sqlalchemy==2.0.40
      - svgutils==0.3.4
      - templateflow==0.4.2
      - tifffile==2021.11.2
      - tomli==2.0.1
      - tqdm==4.67.1
      - traits==6.4.3
      - transforms3d==0.4.2
      - typing-extensions==4.7.1
      - urllib3==2.0.7
      - zipp==3.15.0
prefix: /opt/conda/envs/NiBetaSeries

src/nibetaseries/interfaces/tests/test_nistats.py::test_lss_beta_series[True] src/nibetaseries/interfaces/tests/test_nistats.py::test_fs_beta_series[True] src/nibetaseries/interfaces/tests/test_nistats.py::test_lsa_beta_series[True]
src/nibetaseries/interfaces/tests/test_nistats.py::test_lss_beta_series[False] src/nibetaseries/interfaces/tests/test_nistats.py::test_fs_beta_series[False] src/nibetaseries/interfaces/tests/test_nistats.py::test_lsa_beta_series[False] src/nibetaseries/interfaces/tests/test_nistats.py::test_lss_events_iterator src/nibetaseries/interfaces/tests/test_nistats.py::test_lsa_events_converter src/nibetaseries/interfaces/tests/test_nistats.py::test_select_confounds_error src/nibetaseries/interfaces/tests/test_nistats.py::test_select_confounds[selected_confounds0-nan_confounds0-expanded_confounds0] src/nibetaseries/interfaces/tests/test_nistats.py::test_select_confounds[selected_confounds1-None-expanded_confounds1] src/nibetaseries/interfaces/tests/test_nistats.py::test_select_confounds[selected_confounds2-nan_confounds2-expanded_confounds2]
src/nibetaseries/interfaces/nistats.py
src/nibetaseries/interfaces/nistats.py