We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Convolve should have sampling rate
For events with duration shorter than 1/50, `Convolve` from a sparse variable will produce all 0s. This can be fixed by inserting `ToDense(sampling_rate=200)` (or whatever), but this should be immediately accessible from `Convolve`.

cc @yarikoptic @AdinaWagner 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `bids/analysis/transformations/compute.py`
Content:
```
1 '''
2 Transformations that primarily involve numerical computation on variables.
3 '''
4 
5 import numpy as np
6 import pandas as pd
7 from bids.utils import listify
8 from .base import Transformation
9 from bids.analysis import hrf
10 from bids.variables import SparseRunVariable,  DenseRunVariable
11 
12 
13 class Convolve(Transformation):
14     """Convolve the input variable with an HRF.
15 
16     Args:
17         var (Variable): The variable to convolve.
18         model (str): The name of the HRF model to apply. Must be one of 'spm',
19             'glover', or 'fir'.
20         derivative (bool): Whether or not to include the temporal derivative.
21         dispersion (bool): Whether or not to include the dispersion derivative.
22         fir_delays (iterable): A list or iterable of delays to use if model is
23             'fir' (ignored otherwise). Spacing between delays must be fixed.
24 
25     Note: Uses the HRF convolution functions implemented in nistats.
26     """
27 
28     _input_type = 'variable'
29     _return_type = 'variable'
30 
31     def _transform(self, var, model='spm', derivative=False, dispersion=False,
32                    fir_delays=None):
33 
34         model = model.lower()
35 
36         if isinstance(var, SparseRunVariable):
37             sr = self.collection.sampling_rate
38             var = var.to_dense(sr)
39 
40         df = var.to_df(entities=False)
41         onsets = df['onset'].values
42         vals = df[['onset', 'duration', 'amplitude']].values.T
43 
44         if model in ['spm', 'glover']:
45             if derivative:
46                 model += ' + derivative'
47             if dispersion:
48                 model += ' + dispersion'
49         elif model != 'fir':
50             raise ValueError("Model must be one of 'spm', 'glover', or 'fir'.")
51 
52         convolved = hrf.compute_regressor(vals, model, onsets,
53                                           fir_delays=fir_delays, min_onset=0)
54 
55         return DenseRunVariable(name=var.name, values=convolved[0], run_info=var.run_info,
56                                 source=var.source, sampling_rate=var.sampling_rate)
57 
58 
59 class Demean(Transformation):
60 
61     def _transform(self, data):
62         return data - data.mean()
63 
64 
65 class Orthogonalize(Transformation):
66 
67     _variables_used = ('variables', 'other')
68     _densify = ('variables', 'other')
69     _align = ('other')
70 
71     def _transform(self, var, other):
72 
73         other = listify(other)
74 
75         # Set up X matrix and slice into it based on target variable indices
76         X = np.array([self._variables[c].values.values.squeeze()
77                       for c in other]).T
78         X = X[var.index, :]
79         assert len(X) == len(var)
80         y = var.values
81         _aX = np.c_[np.ones(len(y)), X]
82         coefs, resids, rank, s = np.linalg.lstsq(_aX, y)
83         result = pd.DataFrame(y - X.dot(coefs[1:]), index=var.index)
84         return result
85 
86 
87 class Product(Transformation):
88 
89     _loopable = False
90     _groupable = False
91     _align = True
92     _output_required = True
93 
94     def _transform(self, data):
95         data = pd.concat(data, axis=1, sort=True)
96         return data.product(1)
97 
98 
99 class Scale(Transformation):
100     ''' Scale a variable.
101 
102     Args:
103         data (Series/DF): The variables to scale.
104         demean (bool): If True, demean each column.
105         rescale (bool): If True, divide variables by their standard deviation.
106         replace_na (str): Whether/when to replace missing values with 0. If
107             None, no replacement is performed. If 'before', missing values are
108             replaced with 0's before scaling. If 'after', missing values are
109             replaced with 0 after scaling.
110 
111     '''
112 
113     def _transform(self, data, demean=True, rescale=True, replace_na=None):
114         if replace_na == 'before':
115             data = data.fillna(0.)
116         if demean:
117             data -= data.mean()
118         if rescale:
119             data /= data.std()
120         if replace_na == 'after':
121             data = data.fillna(0.)
122         return data
123 
124 
125 class Sum(Transformation):
126 
127     _loopable = False
128     _groupable = False
129     _align = True
130     _output_required = True
131 
132     def _transform(self, data, weights=None):
133         data = pd.concat(data, axis=1, sort=True)
134         if weights is None:
135             weights = np.ones(data.shape[1])
136         else:
137             weights = np.array(weights)
138             if len(weights.ravel()) != data.shape[1]:
139                 raise ValueError("If weights are passed to sum(), the number "
140                                  "of elements must equal number of variables"
141                                  "being summed.")
142         return (data * weights).sum(axis=1)
143 
144 
145 
146 class Threshold(Transformation):
147     ''' Threshold and/or binarize a variable.
148 
149     Args:
150         data (Series/DF): The pandas structure to threshold.
151         threshold (float): The value to binarize around (values above will
152             be assigned 1, values below will be assigned 0).
153         binarize (bool): If True, binarizes all non-zero values (i.e., every
154             non-zero value will be set to 1).
155         above (bool): Specifies which values to retain with respect to the
156             cut-off. If True, all value above the threshold will be kept; if
157             False, all values below the threshold will be kept. Defaults to
158             True.
159         signed (bool): Specifies whether to treat the threshold as signed
160         (default) or unsigned. For example, when passing above=True and
161         threshold=3, if signed=True, all and only values above +3 would be
162         retained. If signed=False, all absolute values > 3 would be retained
163         (i.e.,values in  the range -3 < X < 3 would be set to 0).
164 
165     '''
166 
167     _groupable = False
168 
169     def _transform(self, data, threshold=0., binarize=False, above=True,
170                    signed=True):
171         if not signed:
172             threshold = np.abs(threshold)
173             data = data.abs()
174         keep = data >= threshold if above else data <= threshold
175         data[~keep] = 0
176         if binarize:
177             data[keep] = 1
178         return data
179 
180 
181 class And(Transformation):
182     ''' Logical AND on two or more variables.
183 
184     Args:
185         dfs (list of DFs): variables to enter into the conjunction.
186     '''
187 
188     _loopable = False
189     _groupable = False
190     _output_required = True
191 
192     def _transform(self, dfs):
193         df = pd.concat(dfs, axis=1, sort=True)
194         return df.all(axis=1).astype(int)
195 
196 
197 class Not(Transformation):
198     ''' Logical negation of a variable.
199 
200     Args:
201         var (Series): Variable to negate. Must be convertible to bool.
202     '''
203 
204     _loopable = True
205     _groupable = False
206 
207     def _transform(self, var):
208         return ~var.astype(bool)
209 
210 
211 class Or(Transformation):
212     ''' Logical OR (inclusive) on two or more variables.
213 
214     Args:
215         dfs (list of DFs): variables to enter into the disjunction.
216     '''
217 
218     _loopable = False
219     _groupable = False
220     _output_required = True
221 
222     def _transform(self, dfs):
223         df = pd.concat(dfs, axis=1, sort=True)
224         return df.any(axis=1).astype(int)
225
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/bids/analysis/transformations/compute.py b/bids/analysis/transformations/compute.py
--- a/bids/analysis/transformations/compute.py
+++ b/bids/analysis/transformations/compute.py
@@ -1,7 +1,8 @@
 '''
 Transformations that primarily involve numerical computation on variables.
 '''
-
+from __future__ import division
+import math
 import numpy as np
 import pandas as pd
 from bids.utils import listify
@@ -33,12 +34,18 @@
 
         model = model.lower()
 
+        df = var.to_df(entities=False)
+
         if isinstance(var, SparseRunVariable):
-            sr = self.collection.sampling_rate
-            var = var.to_dense(sr)
+            sampling_rate = self.collection.sampling_rate
+            dur = var.get_duration()
+            resample_frames = np.linspace(
+                0, dur, int(math.ceil(dur * sampling_rate)), endpoint=False)
+
+        else:
+            resample_frames = df['onset'].values
+            sampling_rate = var.sampling_rate
 
-        df = var.to_df(entities=False)
-        onsets = df['onset'].values
         vals = df[['onset', 'duration', 'amplitude']].values.T
 
         if model in ['spm', 'glover']:
@@ -49,11 +56,23 @@
         elif model != 'fir':
             raise ValueError("Model must be one of 'spm', 'glover', or 'fir'.")
 
-        convolved = hrf.compute_regressor(vals, model, onsets,
-                                          fir_delays=fir_delays, min_onset=0)
-
-        return DenseRunVariable(name=var.name, values=convolved[0], run_info=var.run_info,
-                                source=var.source, sampling_rate=var.sampling_rate)
+        # Minimum interval between event onsets/duration
+        # Used to compute oversampling factor to prevent information loss
+        unique_onsets = np.unique(np.sort(df.onset))
+        if len(unique_onsets) > 1:
+            min_interval = min(np.ediff1d(unique_onsets).min(),
+                               df.duration.min())
+            oversampling = np.ceil(2*(1 / (min_interval * sampling_rate)))
+        else:
+            oversampling = 2
+        convolved = hrf.compute_regressor(
+            vals, model, resample_frames, fir_delays=fir_delays, min_onset=0,
+            oversampling=oversampling
+            )
+
+        return DenseRunVariable(
+            name=var.name, values=convolved[0], run_info=var.run_info,
+            source=var.source, sampling_rate=sampling_rate)
 
 
 class Demean(Transformation):

{"golden_diff": "diff --git a/bids/analysis/transformations/compute.py b/bids/analysis/transformations/compute.py\n--- a/bids/analysis/transformations/compute.py\n+++ b/bids/analysis/transformations/compute.py\n@@ -1,7 +1,8 @@\n '''\n Transformations that primarily involve numerical computation on variables.\n '''\n-\n+from __future__ import division\n+import math\n import numpy as np\n import pandas as pd\n from bids.utils import listify\n@@ -33,12 +34,18 @@\n \n         model = model.lower()\n \n+        df = var.to_df(entities=False)\n+\n         if isinstance(var, SparseRunVariable):\n-            sr = self.collection.sampling_rate\n-            var = var.to_dense(sr)\n+            sampling_rate = self.collection.sampling_rate\n+            dur = var.get_duration()\n+            resample_frames = np.linspace(\n+                0, dur, int(math.ceil(dur * sampling_rate)), endpoint=False)\n+\n+        else:\n+            resample_frames = df['onset'].values\n+            sampling_rate = var.sampling_rate\n \n-        df = var.to_df(entities=False)\n-        onsets = df['onset'].values\n         vals = df[['onset', 'duration', 'amplitude']].values.T\n \n         if model in ['spm', 'glover']:\n@@ -49,11 +56,23 @@\n         elif model != 'fir':\n             raise ValueError(\"Model must be one of 'spm', 'glover', or 'fir'.\")\n \n-        convolved = hrf.compute_regressor(vals, model, onsets,\n-                                          fir_delays=fir_delays, min_onset=0)\n-\n-        return DenseRunVariable(name=var.name, values=convolved[0], run_info=var.run_info,\n-                                source=var.source, sampling_rate=var.sampling_rate)\n+        # Minimum interval between event onsets/duration\n+        # Used to compute oversampling factor to prevent information loss\n+        unique_onsets = np.unique(np.sort(df.onset))\n+        if len(unique_onsets) > 1:\n+            min_interval = min(np.ediff1d(unique_onsets).min(),\n+                               df.duration.min())\n+            oversampling = np.ceil(2*(1 / (min_interval * sampling_rate)))\n+        else:\n+            oversampling = 2\n+        convolved = hrf.compute_regressor(\n+            vals, model, resample_frames, fir_delays=fir_delays, min_onset=0,\n+            oversampling=oversampling\n+            )\n+\n+        return DenseRunVariable(\n+            name=var.name, values=convolved[0], run_info=var.run_info,\n+            source=var.source, sampling_rate=sampling_rate)\n \n \n class Demean(Transformation):\n", "issue": "Convolve should have sampling rate\nFor events with duration shorter than 1/50, `Convolve` from a sparse variable will produce all 0s. This can be fixed by inserting `ToDense(sampling_rate=200)` (or whatever), but this should be immediately accessible from `Convolve`.\r\n\r\ncc @yarikoptic @AdinaWagner \n", "before_files": [{"content": "'''\nTransformations that primarily involve numerical computation on variables.\n'''\n\nimport numpy as np\nimport pandas as pd\nfrom bids.utils import listify\nfrom .base import Transformation\nfrom bids.analysis import hrf\nfrom bids.variables import SparseRunVariable,  DenseRunVariable\n\n\nclass Convolve(Transformation):\n    \"\"\"Convolve the input variable with an HRF.\n\n    Args:\n        var (Variable): The variable to convolve.\n        model (str): The name of the HRF model to apply. Must be one of 'spm',\n            'glover', or 'fir'.\n        derivative (bool): Whether or not to include the temporal derivative.\n        dispersion (bool): Whether or not to include the dispersion derivative.\n        fir_delays (iterable): A list or iterable of delays to use if model is\n            'fir' (ignored otherwise). Spacing between delays must be fixed.\n\n    Note: Uses the HRF convolution functions implemented in nistats.\n    \"\"\"\n\n    _input_type = 'variable'\n    _return_type = 'variable'\n\n    def _transform(self, var, model='spm', derivative=False, dispersion=False,\n                   fir_delays=None):\n\n        model = model.lower()\n\n        if isinstance(var, SparseRunVariable):\n            sr = self.collection.sampling_rate\n            var = var.to_dense(sr)\n\n        df = var.to_df(entities=False)\n        onsets = df['onset'].values\n        vals = df[['onset', 'duration', 'amplitude']].values.T\n\n        if model in ['spm', 'glover']:\n            if derivative:\n                model += ' + derivative'\n            if dispersion:\n                model += ' + dispersion'\n        elif model != 'fir':\n            raise ValueError(\"Model must be one of 'spm', 'glover', or 'fir'.\")\n\n        convolved = hrf.compute_regressor(vals, model, onsets,\n                                          fir_delays=fir_delays, min_onset=0)\n\n        return DenseRunVariable(name=var.name, values=convolved[0], run_info=var.run_info,\n                                source=var.source, sampling_rate=var.sampling_rate)\n\n\nclass Demean(Transformation):\n\n    def _transform(self, data):\n        return data - data.mean()\n\n\nclass Orthogonalize(Transformation):\n\n    _variables_used = ('variables', 'other')\n    _densify = ('variables', 'other')\n    _align = ('other')\n\n    def _transform(self, var, other):\n\n        other = listify(other)\n\n        # Set up X matrix and slice into it based on target variable indices\n        X = np.array([self._variables[c].values.values.squeeze()\n                      for c in other]).T\n        X = X[var.index, :]\n        assert len(X) == len(var)\n        y = var.values\n        _aX = np.c_[np.ones(len(y)), X]\n        coefs, resids, rank, s = np.linalg.lstsq(_aX, y)\n        result = pd.DataFrame(y - X.dot(coefs[1:]), index=var.index)\n        return result\n\n\nclass Product(Transformation):\n\n    _loopable = False\n    _groupable = False\n    _align = True\n    _output_required = True\n\n    def _transform(self, data):\n        data = pd.concat(data, axis=1, sort=True)\n        return data.product(1)\n\n\nclass Scale(Transformation):\n    ''' Scale a variable.\n\n    Args:\n        data (Series/DF): The variables to scale.\n        demean (bool): If True, demean each column.\n        rescale (bool): If True, divide variables by their standard deviation.\n        replace_na (str): Whether/when to replace missing values with 0. If\n            None, no replacement is performed. If 'before', missing values are\n            replaced with 0's before scaling. If 'after', missing values are\n            replaced with 0 after scaling.\n\n    '''\n\n    def _transform(self, data, demean=True, rescale=True, replace_na=None):\n        if replace_na == 'before':\n            data = data.fillna(0.)\n        if demean:\n            data -= data.mean()\n        if rescale:\n            data /= data.std()\n        if replace_na == 'after':\n            data = data.fillna(0.)\n        return data\n\n\nclass Sum(Transformation):\n\n    _loopable = False\n    _groupable = False\n    _align = True\n    _output_required = True\n\n    def _transform(self, data, weights=None):\n        data = pd.concat(data, axis=1, sort=True)\n        if weights is None:\n            weights = np.ones(data.shape[1])\n        else:\n            weights = np.array(weights)\n            if len(weights.ravel()) != data.shape[1]:\n                raise ValueError(\"If weights are passed to sum(), the number \"\n                                 \"of elements must equal number of variables\"\n                                 \"being summed.\")\n        return (data * weights).sum(axis=1)\n\n\n\nclass Threshold(Transformation):\n    ''' Threshold and/or binarize a variable.\n\n    Args:\n        data (Series/DF): The pandas structure to threshold.\n        threshold (float): The value to binarize around (values above will\n            be assigned 1, values below will be assigned 0).\n        binarize (bool): If True, binarizes all non-zero values (i.e., every\n            non-zero value will be set to 1).\n        above (bool): Specifies which values to retain with respect to the\n            cut-off. If True, all value above the threshold will be kept; if\n            False, all values below the threshold will be kept. Defaults to\n            True.\n        signed (bool): Specifies whether to treat the threshold as signed\n        (default) or unsigned. For example, when passing above=True and\n        threshold=3, if signed=True, all and only values above +3 would be\n        retained. If signed=False, all absolute values > 3 would be retained\n        (i.e.,values in  the range -3 < X < 3 would be set to 0).\n\n    '''\n\n    _groupable = False\n\n    def _transform(self, data, threshold=0., binarize=False, above=True,\n                   signed=True):\n        if not signed:\n            threshold = np.abs(threshold)\n            data = data.abs()\n        keep = data >= threshold if above else data <= threshold\n        data[~keep] = 0\n        if binarize:\n            data[keep] = 1\n        return data\n\n\nclass And(Transformation):\n    ''' Logical AND on two or more variables.\n\n    Args:\n        dfs (list of DFs): variables to enter into the conjunction.\n    '''\n\n    _loopable = False\n    _groupable = False\n    _output_required = True\n\n    def _transform(self, dfs):\n        df = pd.concat(dfs, axis=1, sort=True)\n        return df.all(axis=1).astype(int)\n\n\nclass Not(Transformation):\n    ''' Logical negation of a variable.\n\n    Args:\n        var (Series): Variable to negate. Must be convertible to bool.\n    '''\n\n    _loopable = True\n    _groupable = False\n\n    def _transform(self, var):\n        return ~var.astype(bool)\n\n\nclass Or(Transformation):\n    ''' Logical OR (inclusive) on two or more variables.\n\n    Args:\n        dfs (list of DFs): variables to enter into the disjunction.\n    '''\n\n    _loopable = False\n    _groupable = False\n    _output_required = True\n\n    def _transform(self, dfs):\n        df = pd.concat(dfs, axis=1, sort=True)\n        return df.any(axis=1).astype(int)\n", "path": "bids/analysis/transformations/compute.py"}], "after_files": [{"content": "'''\nTransformations that primarily involve numerical computation on variables.\n'''\nfrom __future__ import division\nimport math\nimport numpy as np\nimport pandas as pd\nfrom bids.utils import listify\nfrom .base import Transformation\nfrom bids.analysis import hrf\nfrom bids.variables import SparseRunVariable,  DenseRunVariable\n\n\nclass Convolve(Transformation):\n    \"\"\"Convolve the input variable with an HRF.\n\n    Args:\n        var (Variable): The variable to convolve.\n        model (str): The name of the HRF model to apply. Must be one of 'spm',\n            'glover', or 'fir'.\n        derivative (bool): Whether or not to include the temporal derivative.\n        dispersion (bool): Whether or not to include the dispersion derivative.\n        fir_delays (iterable): A list or iterable of delays to use if model is\n            'fir' (ignored otherwise). Spacing between delays must be fixed.\n\n    Note: Uses the HRF convolution functions implemented in nistats.\n    \"\"\"\n\n    _input_type = 'variable'\n    _return_type = 'variable'\n\n    def _transform(self, var, model='spm', derivative=False, dispersion=False,\n                   fir_delays=None):\n\n        model = model.lower()\n\n        df = var.to_df(entities=False)\n\n        if isinstance(var, SparseRunVariable):\n            sampling_rate = self.collection.sampling_rate\n            dur = var.get_duration()\n            resample_frames = np.linspace(\n                0, dur, int(math.ceil(dur * sampling_rate)), endpoint=False)\n\n        else:\n            resample_frames = df['onset'].values\n            sampling_rate = var.sampling_rate\n\n        vals = df[['onset', 'duration', 'amplitude']].values.T\n\n        if model in ['spm', 'glover']:\n            if derivative:\n                model += ' + derivative'\n            if dispersion:\n                model += ' + dispersion'\n        elif model != 'fir':\n            raise ValueError(\"Model must be one of 'spm', 'glover', or 'fir'.\")\n\n        # Minimum interval between event onsets/duration\n        # Used to compute oversampling factor to prevent information loss\n        unique_onsets = np.unique(np.sort(df.onset))\n        if len(unique_onsets) > 1:\n            min_interval = min(np.ediff1d(unique_onsets).min(),\n                               df.duration.min())\n            oversampling = np.ceil(2*(1 / (min_interval * sampling_rate)))\n        else:\n            oversampling = 2\n        convolved = hrf.compute_regressor(\n            vals, model, resample_frames, fir_delays=fir_delays, min_onset=0,\n            oversampling=oversampling\n            )\n\n        return DenseRunVariable(\n            name=var.name, values=convolved[0], run_info=var.run_info,\n            source=var.source, sampling_rate=sampling_rate)\n\n\nclass Demean(Transformation):\n\n    def _transform(self, data):\n        return data - data.mean()\n\n\nclass Orthogonalize(Transformation):\n\n    _variables_used = ('variables', 'other')\n    _densify = ('variables', 'other')\n    _align = ('other')\n\n    def _transform(self, var, other):\n\n        other = listify(other)\n\n        # Set up X matrix and slice into it based on target variable indices\n        X = np.array([self._variables[c].values.values.squeeze()\n                      for c in other]).T\n        X = X[var.index, :]\n        assert len(X) == len(var)\n        y = var.values\n        _aX = np.c_[np.ones(len(y)), X]\n        coefs, resids, rank, s = np.linalg.lstsq(_aX, y)\n        result = pd.DataFrame(y - X.dot(coefs[1:]), index=var.index)\n        return result\n\n\nclass Product(Transformation):\n\n    _loopable = False\n    _groupable = False\n    _align = True\n    _output_required = True\n\n    def _transform(self, data):\n        data = pd.concat(data, axis=1, sort=True)\n        return data.product(1)\n\n\nclass Scale(Transformation):\n    ''' Scale a variable.\n\n    Args:\n        data (Series/DF): The variables to scale.\n        demean (bool): If True, demean each column.\n        rescale (bool): If True, divide variables by their standard deviation.\n        replace_na (str): Whether/when to replace missing values with 0. If\n            None, no replacement is performed. If 'before', missing values are\n            replaced with 0's before scaling. If 'after', missing values are\n            replaced with 0 after scaling.\n\n    '''\n\n    def _transform(self, data, demean=True, rescale=True, replace_na=None):\n        if replace_na == 'before':\n            data = data.fillna(0.)\n        if demean:\n            data -= data.mean()\n        if rescale:\n            data /= data.std()\n        if replace_na == 'after':\n            data = data.fillna(0.)\n        return data\n\n\nclass Sum(Transformation):\n\n    _loopable = False\n    _groupable = False\n    _align = True\n    _output_required = True\n\n    def _transform(self, data, weights=None):\n        data = pd.concat(data, axis=1, sort=True)\n        if weights is None:\n            weights = np.ones(data.shape[1])\n        else:\n            weights = np.array(weights)\n            if len(weights.ravel()) != data.shape[1]:\n                raise ValueError(\"If weights are passed to sum(), the number \"\n                                 \"of elements must equal number of variables\"\n                                 \"being summed.\")\n        return (data * weights).sum(axis=1)\n\n\n\nclass Threshold(Transformation):\n    ''' Threshold and/or binarize a variable.\n\n    Args:\n        data (Series/DF): The pandas structure to threshold.\n        threshold (float): The value to binarize around (values above will\n            be assigned 1, values below will be assigned 0).\n        binarize (bool): If True, binarizes all non-zero values (i.e., every\n            non-zero value will be set to 1).\n        above (bool): Specifies which values to retain with respect to the\n            cut-off. If True, all value above the threshold will be kept; if\n            False, all values below the threshold will be kept. Defaults to\n            True.\n        signed (bool): Specifies whether to treat the threshold as signed\n        (default) or unsigned. For example, when passing above=True and\n        threshold=3, if signed=True, all and only values above +3 would be\n        retained. If signed=False, all absolute values > 3 would be retained\n        (i.e.,values in  the range -3 < X < 3 would be set to 0).\n\n    '''\n\n    _groupable = False\n\n    def _transform(self, data, threshold=0., binarize=False, above=True,\n                   signed=True):\n        if not signed:\n            threshold = np.abs(threshold)\n            data = data.abs()\n        keep = data >= threshold if above else data <= threshold\n        data[~keep] = 0\n        if binarize:\n            data[keep] = 1\n        return data\n\n\nclass And(Transformation):\n    ''' Logical AND on two or more variables.\n\n    Args:\n        dfs (list of DFs): variables to enter into the conjunction.\n    '''\n\n    _loopable = False\n    _groupable = False\n    _output_required = True\n\n    def _transform(self, dfs):\n        df = pd.concat(dfs, axis=1, sort=True)\n        return df.all(axis=1).astype(int)\n\n\nclass Not(Transformation):\n    ''' Logical negation of a variable.\n\n    Args:\n        var (Series): Variable to negate. Must be convertible to bool.\n    '''\n\n    _loopable = True\n    _groupable = False\n\n    def _transform(self, var):\n        return ~var.astype(bool)\n\n\nclass Or(Transformation):\n    ''' Logical OR (inclusive) on two or more variables.\n\n    Args:\n        dfs (list of DFs): variables to enter into the disjunction.\n    '''\n\n    _loopable = False\n    _groupable = False\n    _output_required = True\n\n    def _transform(self, dfs):\n        df = pd.concat(dfs, axis=1, sort=True)\n        return df.any(axis=1).astype(int)\n", "path": "bids/analysis/transformations/compute.py"}]}