Repository: bids-standard/pybids
Pull request #854 (2022-05-06 17:45:37)

ENH: Make intercept-only first level models throw a NotImplementedError
Following discussion on 2022-05-06, make intercept only first level models throw a not implemented error


Patch:
diff --git a/bids/modeling/statsmodels.py b/bids/modeling/statsmodels.py
index e9092d1a..279d5b48 100644
--- a/bids/modeling/statsmodels.py
+++ b/bids/modeling/statsmodels.py
@@ -288,6 +288,17 @@ class BIDSStatsModelsNode:
                 group_by.append(self.level)
         self.group_by = group_by
 
+        # Check for intercept only run level model and throw an error
+        try:
+            if (self.level == 'run') and (self.model['x'] == [1]):
+                raise NotImplementedError("Run level intercept only models are not currently supported."
+                                          "If this is a feature you need, please leave a comment at"
+                                          "https://github.com/bids-standard/pybids/issues/852.")
+        except KeyError:
+            # We talked about X being required, I don't know if we want to throw an error over that requirement here
+            # though.
+            pass
+
     def __repr__(self):
         return f"<{self.__class__.__name__}[{self.level}] {self.name}>"
 


Test patch:
diff --git a/bids/modeling/tests/test_statsmodels.py b/bids/modeling/tests/test_statsmodels.py
index 5035bf27..97ec6263 100644
--- a/bids/modeling/tests/test_statsmodels.py
+++ b/bids/modeling/tests/test_statsmodels.py
@@ -171,3 +171,11 @@ def test_expand_wildcards():
     assert expand_wildcards(
         ["non_steady_state*"], ["non_steady_state00", "non_steady_state01"]
     ) == ["non_steady_state00", "non_steady_state01"]
+
+
+def test_interceptonly_runlevel_error():
+    layout_path = join(get_test_data_path(), "ds005")
+    layout = BIDSLayout(layout_path)
+    json_file = join(layout_path, "models", "ds-005_type-interceptonlyrunlevel_model.json")
+    with pytest.raises(NotImplementedError):
+        graph = BIDSStatsModelsGraph(layout, json_file)
diff --git a/bids/tests/data/ds005/models/ds-005_type-interceptonlyrunlevel_model.json b/bids/tests/data/ds005/models/ds-005_type-interceptonlyrunlevel_model.json
new file mode 100644
index 00000000..46e4e36f
--- /dev/null
+++ b/bids/tests/data/ds005/models/ds-005_type-interceptonlyrunlevel_model.json
@@ -0,0 +1,60 @@
+{
+  "Name": "ds005_mixedgamblestask",
+  "Description": "An intercept only run level model to test that an error is correctly thrown.",
+  "BIDSModelVersion": "1.0.0",
+  "Input": {
+    "task": [
+      "mixedgamblestask"
+    ]
+  },
+  "Nodes": [
+    {
+      "Level": "Run",
+      "Name": "Run",
+      "GroupBy": [
+        "run",
+        "subject"
+      ],
+      "Transformations": {
+        "Transformer": "pybids-transforms-v1",
+        "Instructions": [
+          {
+            "Name": "Factor",
+            "Input": "trial_type"
+          }
+        ]
+      },
+      "Model": {
+        "Type": "glm",
+        "X": [
+          1
+        ],
+        "HRF": {
+          "Variables": [
+            "trial_type.parametric gain"
+          ],
+          "Model": "DoubleGamma",
+          "Parameters": {
+            "PeakDelay": 3,
+            "PeakDispersion": 6,
+            "UndershootDelay": 10,
+            "UndershootDispersion": 12,
+            "PeakUndershootRatio": 0.2
+          }
+        }
+      },
+      "Contrasts": [
+        {
+          "Name": "run_parametric gain",
+          "ConditionList": [
+            "trial_type.parametric gain"
+          ],
+          "Weights": [
+            1.0
+          ],
+          "Test": "t"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file