Repository: bids-standard/pybids

Issue:
analysis module: variables field in BIDS Model not filtering 
Presumably the 'variables' field in the BIDS model filters what is available to `get_contrasts` and `get_design_matrix`. Currently, it looks like this may not be happening.

e.g. with the following model:

    {
      "level": "dataset",
      "model": {
        "variables": [
          "brightness"
        ]
      }
    }

`get_contrasts` in this case returns all variables including motion etc from the first level, when it should only have a single column ('brightness')




Discussion:
Thanks, should be an easy fix. Note that the `select` transformation will do exactly the same thing, and that one *should* be working (though it probably doesn't matter in your case).

Resolving patch:
diff --git a/bids/analysis/analysis.py b/bids/analysis/analysis.py
--- a/bids/analysis/analysis.py
+++ b/bids/analysis/analysis.py
@@ -76,13 +76,17 @@ def setup(self, blocks=None, agg_func='mean', identity_contrasts=True,
         # In the beginning, there was nothing
         input_nodes = None
 
+        # Use inputs from model, and update with kwargs
+        selectors = self.model.get('input', {})
+        selectors.update(kwargs)
+
         for i, b in enumerate(self.blocks):
 
             # Skip any blocks whose names or indexes don't match block list
             if blocks is not None and i not in blocks and b.name not in blocks:
                 continue
 
-            b.setup(input_nodes, identity_contrasts, **kwargs)
+            b.setup(input_nodes, identity_contrasts, **selectors)
             input_nodes = b.output_nodes
 
 
@@ -107,7 +111,7 @@ class Block(object):
     '''
 
     def __init__(self, layout, level, index, name=None, transformations=None,
-                 model=None, contrasts=None, input_nodes=None):
+                model=None, contrasts=None, input_nodes=None):
 
         self.layout = layout
         self.level = level
@@ -165,7 +169,7 @@ def setup(self, input_nodes=None, identity_contrasts=True, **kwargs):
                 created for each column in the design matrix.
             kwargs: Optional keyword arguments to pass onto load_variables.
         '''
-
+        self.output_nodes = []
         input_nodes = input_nodes or self.input_nodes or []
 
         # TODO: remove the scan_length argument entirely once we switch tests
@@ -190,6 +194,11 @@ def setup(self, input_nodes=None, identity_contrasts=True, **kwargs):
                 colls.append(node_coll)
 
             coll = merge_collections(colls) if len(colls) > 1 else colls[0]
+
+            model = self.model or {}
+            if model.get('variables'):
+                transform.select(coll, model['variables'])
+                
             coll = apply_transformations(coll, self.transformations)
             node = AnalysisNode(self.level, coll, self.contrasts, input_nodes,
                                 identity_contrasts)
@@ -371,6 +380,7 @@ def get_contrasts(self, names=None, entities=False):
         # Construct a list of all contrasts, including identity contrasts
         contrasts = list(self._block_contrasts)
 
+        ### Add ability to set different types of identity contrasts
         if self.identity_contrasts:
             for col_name in self.collection.variables.keys():
                 contrasts.append({
@@ -378,7 +388,6 @@ def get_contrasts(self, names=None, entities=False):
                     'condition_list': [col_name],
                     'weights': [1],
                 })
-
         # Filter on desired contrast names if passed
         if names is not None:
             contrasts = [c for c in contrasts if c['name'] in names]
diff --git a/bids/analysis/auto_model.py b/bids/analysis/auto_model.py
--- a/bids/analysis/auto_model.py
+++ b/bids/analysis/auto_model.py
@@ -63,7 +63,7 @@ def auto_model(layout, scan_length=None, one_vs_rest=False):
         trial_type_factors = ["trial_type." + tt for tt in trial_types]
 
         run_model = OrderedDict(HRF_variables=trial_type_factors,
-                                variables=trial_type_factors)
+                                variables=['trial_type'])
         run["model"] = run_model
 
         if one_vs_rest:
diff --git a/bids/analysis/transformations/munge.py b/bids/analysis/transformations/munge.py
--- a/bids/analysis/transformations/munge.py
+++ b/bids/analysis/transformations/munge.py
@@ -256,6 +256,7 @@ class select(Transformation):
     _loopable = False
     _input_type = 'variable'
     _return_type = 'none'
+    _allow_categorical = ('variables',)
 
     def _transform(self, variables):
         self.collection.variables = {c.name: c for c in variables}


Test patch: