Repository: HBClab/NiBetaSeries

Issue:
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

Discussion:
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              
```


Patch:
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


Test patch:
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,