diff --git a/bids/layout/models.py b/bids/layout/models.py
index 766edd14..9b1e0893 100644
--- a/bids/layout/models.py
+++ b/bids/layout/models.py
@@ -377,17 +377,15 @@ class BIDSImageFile(BIDSFile):
         'polymorphic_identity': 'image_file'
     }
 
-    def get_image(self, **kwargs):
+    def get_image(self):
         """Return the associated image file (if it exists) as a NiBabel object
-
-        Any keyword arguments are passed to ``nibabel.load``.
         """
         try:
             import nibabel as nb
-            return nb.load(self.path, **kwargs)
-        except Exception as e:
+            return nb.load(self.path)
+        except Exception:
             raise ValueError("'{}' does not appear to be an image format "
-                             "NiBabel can read.".format(self.path)) from e
+                             "NiBabel can read.".format(self.path))
 
 
 class BIDSJSONFile(BIDSFile):
diff --git a/bids/reports/parsing.py b/bids/reports/parsing.py
index ef16eabb..80219315 100644
--- a/bids/reports/parsing.py
+++ b/bids/reports/parsing.py
@@ -456,6 +456,7 @@ def parse_niftis(layout, niftis, subj, config, **kwargs):
                     n_runs = len(layout.get_runs(subject=subj,
                                                  task=nifti_struct.entities['task'],
                                                  **kwargs))
+                    n_runs = max(n_runs, 1)
                     description_list.append(func_info(nifti_struct.entities['task'],
                                                       n_runs, metadata, img,
                                                       config))
diff --git a/bids/reports/report.py b/bids/reports/report.py
index 78f19c9e..e23f4e16 100644
--- a/bids/reports/report.py
+++ b/bids/reports/report.py
@@ -49,6 +49,74 @@ class BIDSReport(object):
 
         self.config = config
 
+    def generate_from_files(self, files):
+        r"""Generate a methods section from a list of files.
+
+        Parameters
+        ----------
+        files : list of BIDSImageFile objects
+            List of files from which to generate methods description.
+
+        Returns
+        -------
+        counter : :obj:`collections.Counter`
+            A dictionary of unique descriptions across subjects in the file list,
+            along with the number of times each pattern occurred. In cases
+            where all subjects underwent the same protocol, the most common
+            pattern is most likely the most complete. In cases where the
+            file list contains multiple protocols, each pattern will need to be
+            inspected manually.
+
+        Examples
+        --------
+        >>> from os.path import join
+        >>> from bids.layout import BIDSLayout
+        >>> from bids.reports import BIDSReport
+        >>> from bids.tests import get_test_data_path
+        >>> layout = BIDSLayout(join(get_test_data_path(), 'synthetic'))
+        >>> report = BIDSReport(layout)
+        >>> files = layout.get(session='01', extension=['nii.gz', 'nii'])
+        >>> counter = report.generate_from_files(files)
+        Number of patterns detected: 1
+        Remember to double-check everything and to replace <deg> with a degree symbol.
+
+        >>> counter.most_common()[0][0]  # doctest: +ELLIPSIS
+        'For session 01:\n\tMR data were...'
+        """
+        descriptions = []
+
+        subjs = sorted(list(set([f.get_entities().get('subject') for f in files])))
+        sessions = sorted(list(set([f.get_entities().get('session') for f in files])))
+        for sid in subjs:
+            subject_files = [f for f in files if f.get_entities().get('subject') == sid]
+            description_list = []
+            for ses in sessions:
+                niftis = [f for f in subject_files if f.get_entities().get('session') == ses]
+
+                if niftis:
+                    description_list.append('For session {0}:'.format(ses))
+                    description_list += parsing.parse_niftis(self.layout, niftis,
+                                                             sid, self.config,
+                                                             session=ses)
+                    metadata = self.layout.get_metadata(niftis[0].path)
+                else:
+                    raise Exception('No niftis for subject {0}'.format(subject))
+
+            # Assume all data were converted the same way and use the last nifti
+            # file's json for conversion information.
+            if 'metadata' not in vars():
+                raise Exception('No valid jsons found. Cannot generate final '
+                                'paragraph.')
+
+            description = '\n\t'.join(description_list)
+            description = description.replace('\tFor session', '\nFor session')
+            description += '\n\n{0}'.format(parsing.final_paragraph(metadata))
+            descriptions.append(description)
+        counter = Counter(descriptions)
+        print('Number of patterns detected: {0}'.format(len(counter.keys())))
+        print(utils.reminder())
+        return counter
+
     def generate(self, **kwargs):
         r"""Generate the methods section.
 
diff --git a/doc/conf.py b/doc/conf.py
index d5feaf6a..c96e36a6 100755
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -19,7 +19,7 @@ sys.path.insert(0, os.path.abspath('../'))
 # -- Project information -----------------------------------------------------
 
 project = 'PyBIDS'
-copyright = '2020, Developers of PyBIDS'
+copyright = '2019, Developers of PyBIDS'
 author = 'Developers of PyBIDS'
 
 currentdir = os.path.abspath(os.path.dirname(__file__))
@@ -124,4 +124,4 @@ texinfo_documents = [
 ]
 
 # If false, no module index is generated.
-texinfo_domain_indices = False
+texinfo_domain_indices = False
\ No newline at end of file

Add method to build BIDSReport from list of files
It would be nice to be able to build reports from lists of files, for tools that collect their inputs using custom functions, like fMRIPrep. In these cases, BIDSLayout filters are insufficient to collect the exact files required by the tools.

EDIT: I should also note that I've got working code for this and would be happy to open a PR if others think it would be useful.
diff --git a/bids/analysis/tests/test_analysis.py b/bids/analysis/tests/test_analysis.py
index e2971bfb..0b893a0c 100644
--- a/bids/analysis/tests/test_analysis.py
+++ b/bids/analysis/tests/test_analysis.py
@@ -27,8 +27,8 @@ def test_first_level_sparse_design_matrix(analysis):
     assert df.shape == (172, 9)
     assert df['condition'].nunique() == 2
     assert set(df.columns) == {'amplitude', 'onset', 'duration',
-                               'condition', 'subject', 'run',
-                               'task', 'datatype', 'suffix'}
+                                         'condition', 'subject', 'run',
+                                         'task', 'datatype', 'suffix'}
 
 
 def test_post_first_level_sparse_design_matrix(analysis):
@@ -40,15 +40,12 @@ def test_post_first_level_sparse_design_matrix(analysis):
     result = collections[0].to_df(format='long', entities=False)
     assert result.shape == (9, 2)
     entities = {
-        # 'subject': '01',  # PY35
+        'subject': '01',
         'task': 'mixedgamblestask',
         'datatype': 'func',
         'suffix': 'bold'}
     assert not set(entities.keys()) - set(collections[0].entities.keys())
     assert not set(entities.values()) - set(collections[0].entities.values())
-    # PY35
-    assert 'subject' in collections[0].entities
-    assert collections[0].entities['subject'] in ('01', '02')
 
     # Participant level and also check integer-based indexing
     collections = analysis['participant'].get_collections()
diff --git a/bids/reports/tests/test_report.py b/bids/reports/tests/test_report.py
index 5921a77b..798eafad 100644
--- a/bids/reports/tests/test_report.py
+++ b/bids/reports/tests/test_report.py
@@ -34,6 +34,16 @@ def test_report_gen(testlayout):
     assert isinstance(descriptions, Counter)
 
 
+def test_report_gen_from_files(testlayout):
+    """Report generation from file list should return a counter of unique
+    descriptions in the dataset.
+    """
+    report = BIDSReport(testlayout)
+    files = testlayout.get(extension=['nii.gz', 'nii'])
+    descriptions = report.generate_from_files(files)
+    assert isinstance(descriptions, Counter)
+
+
 def test_report_subject(testlayout):
     """Generating a report for one subject should only return one subject's
     description (i.e., one pattern with a count of one).

pip install -e .[dev]
parse_log_pytest
pytest
pytest pytest-cov pytest
apt-get update apt-get install -y gcc
3.7
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster==0.7.13
attrs @ file:///croot/attrs_1668696182826/work
Babel==2.14.0
bids-validator==1.14.0
certifi @ file:///croot/certifi_1671487769961/work/certifi
charset-normalizer==3.4.1
coverage==7.2.7
docopt==0.6.2
docutils==0.17.1
flit_core @ file:///opt/conda/conda-bld/flit-core_1644941570762/work/source/flit_core
greenlet==3.1.1
idna==3.10
imagesize==1.4.1
importlib-metadata @ file:///tmp/build/80754af9/importlib-metadata_1648562407465/work
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
Jinja2==3.0.3
m2r==0.3.1
MarkupSafe==2.1.5
mistune==0.8.4
mock==5.2.0
nibabel==4.0.2
num2words==0.5.14
numpy==1.21.6
numpydoc==1.2.1
packaging @ file:///croot/packaging_1671697413597/work
pandas==1.3.5
patsy==1.0.1
pluggy @ file:///tmp/build/80754af9/pluggy_1648042572264/work
py @ file:///opt/conda/conda-bld/py_1644396412707/work
-e git+https://github.com/bids-standard/pybids.git@5fab1dee770babffa7aef668b24cb59a90ba37ef#egg=pybids
Pygments==2.17.2
pytest==7.1.2
pytest-cov==4.1.0
python-dateutil==2.9.0.post0
pytz==2025.2
requests==2.31.0
scipy==1.7.3
six==1.17.0
snowballstemmer==2.2.0
Sphinx==2.4.5
sphinx-rtd-theme==1.3.0
sphinxcontrib-applehelp==1.0.2
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.0
sphinxcontrib-jquery==4.1
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
SQLAlchemy==2.0.40
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
typing_extensions==4.7.1
urllib3==2.0.7
zipp @ file:///croot/zipp_1672387121353/work

name: pybids
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
  - attrs=22.1.0=py37h06a4308_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - flit-core=3.6.0=pyhd3eb1b0_0
  - importlib-metadata=4.11.3=py37h06a4308_0
  - importlib_metadata=4.11.3=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_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
  - packaging=22.0=py37h06a4308_0
  - pip=22.3.1=py37h06a4308_0
  - pluggy=1.0.0=py37h06a4308_1
  - py=1.11.0=pyhd3eb1b0_0
  - pytest=7.1.2=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
  - tomli=2.0.1=py37h06a4308_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.11.0=py37h06a4308_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - alabaster==0.7.13
      - babel==2.14.0
      - bids-validator==1.14.0
      - charset-normalizer==3.4.1
      - coverage==7.2.7
      - docopt==0.6.2
      - docutils==0.17.1
      - greenlet==3.1.1
      - idna==3.10
      - imagesize==1.4.1
      - jinja2==3.0.3
      - m2r==0.3.1
      - markupsafe==2.1.5
      - mistune==0.8.4
      - mock==5.2.0
      - nibabel==4.0.2
      - num2words==0.5.14
      - numpy==1.21.6
      - numpydoc==1.2.1
      - pandas==1.3.5
      - patsy==1.0.1
      - pybids==0.10.2+69.g5fab1dee
      - pygments==2.17.2
      - pytest-cov==4.1.0
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - requests==2.31.0
      - scipy==1.7.3
      - six==1.17.0
      - snowballstemmer==2.2.0
      - sphinx==2.4.5
      - sphinx-rtd-theme==1.3.0
      - sphinxcontrib-applehelp==1.0.2
      - sphinxcontrib-devhelp==1.0.2
      - sphinxcontrib-htmlhelp==2.0.0
      - sphinxcontrib-jquery==4.1
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==1.0.3
      - sphinxcontrib-serializinghtml==1.1.5
      - sqlalchemy==2.0.40
      - typing-extensions==4.7.1
      - urllib3==2.0.7
prefix: /opt/conda/envs/pybids

bids/reports/tests/test_report.py::test_report_gen_from_files
bids/analysis/tests/test_analysis.py::test_first_level_sparse_design_matrix bids/analysis/tests/test_analysis.py::test_post_first_level_sparse_design_matrix bids/analysis/tests/test_analysis.py::test_step_get_collections bids/analysis/tests/test_analysis.py::test_contrast_info bids/analysis/tests/test_analysis.py::test_contrast_info_with_specified_variables bids/analysis/tests/test_analysis.py::test_contrast_info_F_contrast bids/analysis/tests/test_analysis.py::test_dummy_contrasts bids/analysis/tests/test_analysis.py::test_get_model_spec bids/reports/tests/test_report.py::test_report_init bids/reports/tests/test_report.py::test_report_gen bids/reports/tests/test_report.py::test_report_subject bids/reports/tests/test_report.py::test_report_session bids/reports/tests/test_report.py::test_report_file_config bids/reports/tests/test_report.py::test_report_dict_config
bids/reports/parsing.py doc/conf.py bids/layout/models.py bids/reports/report.py
bids/reports/parsing.py doc/conf.py bids/layout/models.py bids/reports/report.py