Skip to content

Commit ddc65bd

Browse files
Merge branch 'main' into small_sample
2 parents 1e068bf + b802f17 commit ddc65bd

20 files changed

+488
-601
lines changed

.readthedocs.yml

+5-1
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@ sphinx:
1010
# Optionally build your docs in additional formats such as PDF
1111
formats: all
1212

13+
build:
14+
os: ubuntu-22.04
15+
tools:
16+
python: "3.8"
17+
1318
# Optionally set the version of Python and requirements required to build your docs
1419
python:
15-
version: 3.7
1620
install:
1721
- requirements: requirements.txt
1822
- requirements: docs/requirements.txt

demos/demo_bootstrap.ipynb

+31-171
Large diffs are not rendered by default.

src/rsatoolbox/inference/result.py

+15-5
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,16 @@ def summary(self, test_type='t-test'):
9898
name_length = max([max(len(m.name) for m in self.models) + 1, 6])
9999
means = self.get_means()
100100
sems = self.get_sem()
101-
p_zero = self.test_zero(test_type=test_type)
102-
p_noise = self.test_noise(test_type=test_type)
101+
if means is None:
102+
means = np.nan * np.ones(self.n_model)
103+
if sems is None:
104+
sems = np.nan * np.ones(self.n_model)
105+
try:
106+
p_zero = self.test_zero(test_type=test_type)
107+
p_noise = self.test_noise(test_type=test_type)
108+
except ValueError:
109+
p_zero = np.nan * np.ones(self.n_model)
110+
p_noise = np.nan * np.ones(self.n_model)
103111
# header of the results table
104112
summary += 'Model' + (' ' * (name_length - 5))
105113
summary += '| Eval \u00B1 SEM |'
@@ -120,7 +128,9 @@ def summary(self, test_type='t-test'):
120128
summary += f'{p_noise[i]:>14.3f} |'
121129
summary += '\n'
122130
summary += '\n'
123-
if test_type == 't-test':
131+
if self.cv_method == 'crossvalidation':
132+
summary += 'No p-values available as crossvalidation provides no variance estimate'
133+
elif test_type == 't-test':
124134
summary += 'p-values are based on uncorrected t-tests'
125135
elif test_type == 'bootstrap':
126136
summary += 'p-values are based on percentiles of the bootstrap samples'
@@ -252,11 +262,11 @@ def get_errorbars(self, eb_type='sem', test_type='t-test'):
252262
ci_percent = float(eb_type[2:]) / 100
253263
ci = self.get_ci(ci_percent, test_type)
254264
means = self.get_means()
255-
errorbar_low = -(ci[0] - means)
265+
errorbar_low = means - ci[0]
256266
errorbar_high = ci[1] - means
257267
limits = np.concatenate((errorbar_low, errorbar_high))
258268
if np.isnan(limits).any() or (abs(limits) == np.inf).any():
259-
raise RuntimeError(
269+
raise ValueError(
260270
'plot_model_comparison: Too few bootstrap samples for ' +
261271
'the requested confidence interval: ' + eb_type + '.')
262272
return (errorbar_low, errorbar_high)

src/rsatoolbox/vis/model_plot.py

+17-11
Original file line numberDiff line numberDiff line change
@@ -264,9 +264,10 @@ def plot_model_comparison(result, sort=False, colors=None,
264264
models = [models[i] for i in idx]
265265
if not ('descend' in sort.lower() or
266266
'ascend' in sort.lower()):
267-
raise Exception('plot_model_comparison: Argument ' +
268-
'sort is incorrectly defined as '
269-
+ sort + '.')
267+
raise ValueError(
268+
'plot_model_comparison: Argument ' +
269+
'sort is incorrectly defined as ' +
270+
sort + '.')
270271

271272
# run tests
272273
if any([test_pair_comparisons,
@@ -290,9 +291,10 @@ def plot_model_comparison(result, sort=False, colors=None,
290291
elif 'nili' in test_pair_comparisons.lower():
291292
h_pair_tests = 0.4
292293
else:
293-
raise Exception('plot_model_comparison: Argument ' +
294-
'test_pair_comparisons is incorrectly defined as '
295-
+ test_pair_comparisons + '.')
294+
raise ValueError(
295+
'plot_model_comparison: Argument ' +
296+
'test_pair_comparisons is incorrectly defined as ' +
297+
test_pair_comparisons + '.')
296298
ax = plt.axes((l, b, w, h*(1-h_pair_tests)))
297299
axbar = plt.axes((l, b + h * (1 - h_pair_tests), w,
298300
h * h_pair_tests * 0.7))
@@ -360,7 +362,7 @@ def plot_model_comparison(result, sort=False, colors=None,
360362
marker=10, markersize=half_sym_size,
361363
linewidth=0)
362364
else:
363-
raise Exception(
365+
raise ValueError(
364366
'plot_model_comparison: Argument test_above_0' +
365367
' is incorrectly defined as ' + test_above_0 + '.')
366368

@@ -397,7 +399,7 @@ def plot_model_comparison(result, sort=False, colors=None,
397399
markerfacecolor=noise_ceil_col,
398400
markeredgecolor='none', linewidth=0)
399401
else:
400-
raise Exception(
402+
raise ValueError(
401403
'plot_model_comparison: Argument ' +
402404
'test_below_noise_ceil is incorrectly defined as ' +
403405
test_below_noise_ceil + '.')
@@ -429,7 +431,7 @@ def plot_model_comparison(result, sort=False, colors=None,
429431
significant = p_pairwise < crit
430432
else:
431433
if 'uncorrected' not in multiple_pair_testing.lower():
432-
raise Exception(
434+
raise ValueError(
433435
'plot_model_comparison: Argument ' +
434436
'multiple_pair_testing is incorrectly defined as ' +
435437
multiple_pair_testing + '.')
@@ -793,7 +795,11 @@ def plot_arrows(axbar, significant):
793795
k += 1
794796
axbar.plot((i, j), (k, k), 'k-', linewidth=2)
795797
occupied[k-1, i*3+2:j*3+1] = 1
796-
h = occupied.sum(axis=1).nonzero()[0].max()+1
798+
h = occupied.sum(axis=1)
799+
if np.any(h > 0):
800+
h = h.nonzero()[0].max()+1
801+
else:
802+
h = 1
797803
axbar.set_ylim((0, max(expected_n_lines, h)))
798804

799805

@@ -905,7 +911,7 @@ def _get_model_comp_descr(test_type, n_models, multiple_pair_testing, alpha,
905911
' model-pair comparisons)')
906912
else:
907913
if 'uncorrected' not in multiple_pair_testing.lower():
908-
raise Exception(
914+
raise ValueError(
909915
'plot_model_comparison: Argument ' +
910916
'multiple_pair_testing is incorrectly defined as ' +
911917
multiple_pair_testing + '.')

tests/test_c.py

+10-6
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@
1717
class TestSimilarity(unittest.TestCase):
1818

1919
def setUp(self):
20-
self.v_i = np.random.rand(21)
21-
self.v_j = np.random.rand(21)
20+
self.rng = np.random.default_rng(0)
21+
self.v_i = self.rng.random((21))
22+
self.v_j = self.rng.random((21))
2223
self.vec_i = np.array([0.11, 0.12, 0.22, 0.30, 0.31])
2324
self.vec_j = np.array([0.13, 0.14, 0.21, 0.29, 0.28])
2425

@@ -61,8 +62,9 @@ def test_noise(self):
6162
class TestCalcOne(unittest.TestCase):
6263

6364
def setUp(self):
64-
self.dat_i = np.random.rand(2, 21)
65-
self.dat_j = np.random.rand(3, 21)
65+
self.rng = np.random.default_rng(0)
66+
self.dat_i = self.rng.random((2, 21))
67+
self.dat_j = self.rng.random((3, 21))
6668
self.dat = np.concatenate((self.dat_i, self.dat_j), 0)
6769
self.data = rsatoolbox.data.Dataset(
6870
self.dat, obs_descriptors={'idx': [1, 1, 2, 2, 2]})
@@ -90,14 +92,16 @@ def test_integer_input_one(self):
9092
from rsatoolbox.data.dataset import Dataset
9193
ds1 = Dataset(np.asarray([[0], [2]]).T) # one pattern, two channels
9294
ds2 = Dataset(np.asarray([[0], [2]]).T) # one pattern, two channels
93-
dissim, _ = calc_one_similarity_c(ds1, ds2, np.array([0]), np.array([1]))
95+
dissim, _ = calc_one_similarity_c(
96+
ds1, ds2, np.array([0]), np.array([1]))
9497
assert_almost_equal(dissim, 2) # standard-squared euclidean
9598

9699

97100
class TestCalc(unittest.TestCase):
98101

99102
def setUp(self):
100-
self.dat = np.random.rand(300, 100)
103+
self.rng = np.random.default_rng(0)
104+
self.dat = self.rng.random((300, 100))
101105
self.data = rsatoolbox.data.Dataset(
102106
self.dat,
103107
obs_descriptors={'obs': np.repeat(np.arange(50), 6),

tests/test_calc_rdm.py

+12-10
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
class TestCalcRDM(unittest.TestCase):
3030

3131
def setUp(self):
32-
measurements = np.random.rand(20, 5)
32+
self.rng = np.random.default_rng(0)
33+
measurements = self.rng.random((20, 5))
3334
measurements_deterministic = np.array(
3435
[
3536
[0.11, 0.12, 0.21, 0.22, 0.30, 0.31],
@@ -85,7 +86,7 @@ def test_parse_input(self):
8586
from rsatoolbox.rdm.calc import _parse_input
8687
data = Mock()
8788
data.descriptors = {'session': 0, 'subj': 0}
88-
data.measurements = np.random.rand(6, 5)
89+
data.measurements = self.rng.random((6, 5))
8990
measurements, desc = _parse_input(data, None)
9091
self.assertIsNone(desc)
9192
self.assertTrue(np.all(data.measurements == measurements))
@@ -97,7 +98,7 @@ def test_calc_euclidean_as_scipy(self, _parse_input):
9798
data.descriptors = {'session': 0, 'subj': 0}
9899
data.obs_descriptors = dict(conds=np.arange(6))
99100
data.channel_descriptors = dict()
100-
data.measurements = np.random.rand(6, 5)
101+
data.measurements = self.rng.random((6, 5))
101102
desc = [0, 1, 2, 3, 4, 5]
102103
_parse_input.return_value = (data.measurements, desc)
103104
rdm_expected = pdist(data.measurements) ** 2 / 5
@@ -112,7 +113,7 @@ def test_calc_correlation(self, _parse_input):
112113
data.descriptors = {'session': 0, 'subj': 0}
113114
data.obs_descriptors = dict(conds=np.arange(6))
114115
data.channel_descriptors = dict()
115-
data.measurements = np.random.rand(6, 5)
116+
data.measurements = self.rng.random((6, 5))
116117
desc = [0, 1, 2, 3, 4, 5]
117118
_parse_input.return_value = (data.measurements, desc)
118119
rdm_expected = 1 - np.corrcoef(data.measurements)
@@ -141,7 +142,7 @@ def test_calc_mahalanobis(self):
141142
method='mahalanobis'
142143
)
143144
assert rdm.n_cond == 6
144-
noise = np.linalg.inv(np.cov(np.random.randn(10, 5).T))
145+
noise = np.linalg.inv(np.cov(self.rng.standard_normal((10, 5)).T))
145146
rdm = rsr.calc_rdm(
146147
self.test_data,
147148
descriptor='conds',
@@ -202,7 +203,7 @@ def test_calc_crossnobis_no_descriptors(self):
202203
assert rdm.n_cond == 5
203204

204205
def test_calc_crossnobis_noise(self):
205-
noise = np.random.randn(10, 5)
206+
noise = self.rng.standard_normal((10, 5))
206207
noise = np.matmul(noise.T, noise)
207208
rdm = rsr.calc_rdm_crossnobis(
208209
self.test_data_balanced, descriptor='conds', noise=noise
@@ -211,7 +212,7 @@ def test_calc_crossnobis_noise(self):
211212

212213
def test_calc_crossnobis_noise_list(self):
213214
# generate two positive definite noise matricies
214-
noise = np.random.randn(2, 10, 5)
215+
noise = self.rng.standard_normal((2, 10, 5))
215216
noise = np.einsum('ijk,ijl->ikl', noise, noise)
216217
rdm = rsr.calc_rdm_crossnobis(
217218
self.test_data_balanced,
@@ -377,7 +378,8 @@ def test_calc_with_descriptors_as_list(self):
377378
class TestCalcRDMMovie(unittest.TestCase):
378379

379380
def setUp(self):
380-
measurements_time = np.random.rand(20, 5, 15)
381+
self.rng = np.random.default_rng(0)
382+
measurements_time = self.rng.random((20, 5, 15))
381383
tim_des = {'time': np.linspace(0, 200, 15)}
382384
des = {'session': 0, 'subj': 0}
383385
obs_des = {
@@ -471,7 +473,7 @@ def test_calc_rdm_movie_crossnobis_no_descriptors(self):
471473
assert rdm.n_cond == 5
472474

473475
def test_calc_rdm_movie_crossnobis_noise(self):
474-
noise = np.random.randn(10, 5)
476+
noise = self.rng.standard_normal((10, 5))
475477
noise = np.matmul(noise.T, noise)
476478
rdm = rsr.calc_rdm_movie(
477479
self.test_data_time_balanced,
@@ -483,7 +485,7 @@ def test_calc_rdm_movie_crossnobis_noise(self):
483485
assert rdm.n_cond == 5
484486

485487
def test_calc_rdm_movie_rdm_movie_poisson(self):
486-
noise = np.random.randn(10, 5)
488+
noise = self.rng.standard_normal((10, 5))
487489
noise = np.matmul(noise.T, noise)
488490
rdm = rsr.calc_rdm_movie(
489491
self.test_data_time_balanced,

tests/test_calc_unbalanced.py

+14-13
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
class TestCalcUnbalancedRDM(unittest.TestCase):
3030

3131
def setUp(self):
32-
measurements = np.random.rand(20, 5)
32+
self.rng = np.random.default_rng(0)
33+
measurements = self.rng.random((20, 5))
3334
measurements_deterministic = np.array([
3435
[0.11, 0.12, 0.21, 0.22, 0.30, 0.31],
3536
[0.13, 0.14, 0.24, 0.21, 0.29, 0.28],
@@ -52,13 +53,13 @@ def setUp(self):
5253
descriptors=des,
5354
obs_descriptors=obs_des,
5455
channel_descriptors=chn_des
55-
)
56+
)
5657
self.test_data_balanced = rsa.data.Dataset(
5758
measurements=measurements,
5859
descriptors=des,
5960
obs_descriptors=obs_balanced,
6061
channel_descriptors=chn_des
61-
)
62+
)
6263
self.test_data_deterministic = rsa.data.Dataset(
6364
measurements=measurements_deterministic,
6465
descriptors=des,
@@ -80,10 +81,10 @@ def test_calc_euclid_nconds(self):
8081
def test_calc_euclid_as_scipy(self, _parse_input):
8182
from rsatoolbox.rdm import calc_rdm_unbalanced
8283
data = rsa.data.Dataset(
83-
np.random.rand(6, 5),
84+
self.rng.random((6, 5)),
8485
descriptors={'session': 0, 'subj': 0},
8586
obs_descriptors={'conds': [0, 1, 2, 3, 4, 5]}
86-
)
87+
)
8788
rdm_expected = pdist(data.measurements) ** 2 / 5
8889
rdms = calc_rdm_unbalanced(
8990
data,
@@ -94,17 +95,17 @@ def test_calc_euclid_as_scipy(self, _parse_input):
9495
assert_array_almost_equal(
9596
rdm_expected,
9697
rdms.dissimilarities.flatten()
97-
)
9898
)
99+
)
99100

100101
@patch('rsatoolbox.rdm.calc._parse_input')
101102
def test_calc_correlation(self, _parse_input):
102103
from rsatoolbox.rdm import calc_rdm_unbalanced
103104
data = rsa.data.Dataset(
104-
np.random.rand(6, 5),
105+
self.rng.random((6, 5)),
105106
descriptors={'session': 0, 'subj': 0},
106107
obs_descriptors={'conds': [0, 1, 2, 3, 4, 5]}
107-
)
108+
)
108109
rdm_expected = 1 - np.corrcoef(data.measurements)
109110
rdme = rsr.RDMs(
110111
dissimilarities=np.array([rdm_expected]),
@@ -143,7 +144,7 @@ def test_calc_mahalanobis(self):
143144
assert_array_almost_equal(
144145
rdm_bal.dissimilarities.flatten(),
145146
rdm_check.dissimilarities.flatten()
146-
)
147+
)
147148

148149
def test_calc_crossnobis(self):
149150
rdm = rsr.calc_rdm_unbalanced(self.test_data,
@@ -164,7 +165,7 @@ def test_calc_crossnobis(self):
164165
assert_array_almost_equal(
165166
rdm_bal.dissimilarities.flatten(),
166167
rdm_check.dissimilarities.flatten()
167-
)
168+
)
168169

169170
def test_calc_crossnobis_no_descriptor(self):
170171
rdm = rsr.calc_rdm_unbalanced(
@@ -174,7 +175,7 @@ def test_calc_crossnobis_no_descriptor(self):
174175
assert rdm.n_cond == 6
175176

176177
def test_calc_crossnobis_noise(self):
177-
noise = np.random.randn(10, 5)
178+
noise = self.rng.random((10, 5))
178179
noise = np.matmul(noise.T, noise)
179180
rdm = rsr.calc_rdm_unbalanced(
180181
self.test_data,
@@ -195,7 +196,7 @@ def test_calc_crossnobis_noise(self):
195196
assert_array_almost_equal(
196197
rdm_bal.dissimilarities.flatten(),
197198
rdm_check.dissimilarities.flatten()
198-
)
199+
)
199200

200201
def test_calc_poisson(self):
201202
""" for the poisson-KL the dissimilarities differ! This is explained
@@ -305,4 +306,4 @@ def test_calc_multi_ds_passes_on_descriptors(self, method):
305306
assert_array_equal(
306307
rdms.pattern_descriptors['conds'],
307308
self.test_data.obs_descriptors['conds']
308-
)
309+
)

0 commit comments

Comments
 (0)