Skip to content

Commit

Permalink
Merge branch 'doc/test' into r/0.38
Browse files Browse the repository at this point in the history
  • Loading branch information
christianbrodbeck committed Dec 10, 2022
2 parents cfc5930 + aeff61a commit 9ebbe1c
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 39 deletions.
20 changes: 20 additions & 0 deletions doc/publications.bib
Original file line number Diff line number Diff line change
Expand Up @@ -764,3 +764,23 @@ @article{matarmodels
url = "https://2022.ccneuro.org/proceedings/0000331.pdf",
google_result_id = "mBZCoKR6Va4J"
}

@article{gillis2022heard,
author = "Gillis, Marlies and Vanthornhout, Jonas and Francart, Tom",
title = "Heard or understood? Neural tracking of language features in a comprehensible story, an incomprehensible story and a word list",
journal = "bioRxiv",
year = "2022",
publisher = "Cold Spring Harbor Laboratory",
doi = "10.1101/2022.11.22.517477",
google_result_id = "7w3_G4qWqWUJ"
}

@article{schmidt2022age,
author = "Schmidt, Fabian and Danboeck, Sarah K and Trinka, Eugen and Demarchi, Gianpaolo and Weisz, Nathan",
title = "Age-related changes in'cortical'1/f dynamics are explained by cardiac activity",
journal = "bioRxiv",
year = "2022",
publisher = "Cold Spring Harbor Laboratory",
doi = "10.1101/2022.11.07.515423",
google_result_id = "ERvT26o8AlUJ"
}
Binary file modified doc/scripts/bibtex.pickle
Binary file not shown.
109 changes: 108 additions & 1 deletion doc/scripts/cache.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,41 @@
"summary": "VNKC Puvvada - 2017 - search.proquest.com"
}
},
"4D5RTBi0ub8J": {
"title": "Neural tracking as a diagnostic tool to assess the auditory pathway",
"result_id": "4D5RTBi0ub8J",
"link": "https://www.biorxiv.org/content/10.1101/2021.11.26.470129.abstract",
"snippet": "When a person listens to sound, the brain time-locks to specific aspects of the sound. This is called neural tracking and it can be investigated by analysing neural responses (eg, \u2026",
"publication_info": {
"summary": "M Gillis, J Van Canneyt, T Francart, J Vanthornhout - bioRxiv, 2022 - biorxiv.org",
"authors": [
{
"name": "M Gillis",
"link": "https://scholar.google.com/citations?user=_3DlZ_EAAAAJ&hl=en&num=20&oi=sra",
"serpapi_scholar_link": "https://serpapi.com/search.json?author_id=_3DlZ_EAAAAJ&engine=google_scholar_author&hl=en",
"author_id": "_3DlZ_EAAAAJ"
},
{
"name": "J Van Canneyt",
"link": "https://scholar.google.com/citations?user=Nd9x9FIAAAAJ&hl=en&num=20&oi=sra",
"serpapi_scholar_link": "https://serpapi.com/search.json?author_id=Nd9x9FIAAAAJ&engine=google_scholar_author&hl=en",
"author_id": "Nd9x9FIAAAAJ"
},
{
"name": "T Francart",
"link": "https://scholar.google.com/citations?user=rv2nwCEAAAAJ&hl=en&num=20&oi=sra",
"serpapi_scholar_link": "https://serpapi.com/search.json?author_id=rv2nwCEAAAAJ&engine=google_scholar_author&hl=en",
"author_id": "rv2nwCEAAAAJ"
},
{
"name": "J Vanthornhout",
"link": "https://scholar.google.com/citations?user=I0EdEu0AAAAJ&hl=en&num=20&oi=sra",
"serpapi_scholar_link": "https://serpapi.com/search.json?author_id=I0EdEu0AAAAJ&engine=google_scholar_author&hl=en",
"author_id": "I0EdEu0AAAAJ"
}
]
}
},
"4QAnG8imeE4J": {
"title": "A Python-based Brain-Computer Interface Package for Neural Data Analysis",
"result_id": "4QAnG8imeE4J",
Expand Down Expand Up @@ -264,6 +299,12 @@
"publication_info": {
"summary": "M Tulling, R Law, A Cournane, L Pylkk\u00e4nen - Eneuro, 2021 - ncbi.nlm.nih.gov",
"authors": [
{
"name": "M Tulling",
"link": "https://scholar.google.com/citations?user=rXzC82IAAAAJ&hl=en&num=20&oi=sra",
"serpapi_scholar_link": "https://serpapi.com/search.json?author_id=rXzC82IAAAAJ&engine=google_scholar_author&hl=en",
"author_id": "rXzC82IAAAAJ"
},
{
"name": "R Law",
"link": "https://scholar.google.com/citations?user=d06kiU8AAAAJ&hl=en&num=20&oi=sra",
Expand All @@ -285,6 +326,35 @@
]
}
},
"7w3_G4qWqWUJ": {
"title": "Heard or understood? Neural tracking of language features in a comprehensible story, an incomprehensible story and a word list",
"result_id": "7w3_G4qWqWUJ",
"link": "https://www.biorxiv.org/content/10.1101/2022.11.22.517477.abstract",
"snippet": "Speech comprehension is a complex neural process on which relies on activation and integration of multiple brain regions. In the current study, we evaluated whether speech \u2026",
"publication_info": {
"summary": "M Gillis, J Vanthornhout, T Francart - bioRxiv, 2022 - biorxiv.org",
"authors": [
{
"name": "M Gillis",
"link": "https://scholar.google.com/citations?user=_3DlZ_EAAAAJ&hl=en&num=20&oi=sra",
"serpapi_scholar_link": "https://serpapi.com/search.json?author_id=_3DlZ_EAAAAJ&engine=google_scholar_author&hl=en",
"author_id": "_3DlZ_EAAAAJ"
},
{
"name": "J Vanthornhout",
"link": "https://scholar.google.com/citations?user=I0EdEu0AAAAJ&hl=en&num=20&oi=sra",
"serpapi_scholar_link": "https://serpapi.com/search.json?author_id=I0EdEu0AAAAJ&engine=google_scholar_author&hl=en",
"author_id": "I0EdEu0AAAAJ"
},
{
"name": "T Francart",
"link": "https://scholar.google.com/citations?user=rv2nwCEAAAAJ&hl=en&num=20&oi=sra",
"serpapi_scholar_link": "https://serpapi.com/search.json?author_id=rv2nwCEAAAAJ&engine=google_scholar_author&hl=en",
"author_id": "rv2nwCEAAAAJ"
}
]
}
},
"8dBIoRFtXiMJ": {
"title": "Morphological representations are extrapolated from morpho-syntactic rules",
"result_id": "8dBIoRFtXiMJ",
Expand Down Expand Up @@ -436,6 +506,29 @@
]
}
},
"ERvT26o8AlUJ": {
"title": "Age-related changes in'cortical'1/f dynamics are explained by cardiac activity",
"result_id": "ERvT26o8AlUJ",
"link": "https://www.biorxiv.org/content/10.1101/2022.11.07.515423.abstract",
"snippet": "The power of electrophysiologically measured cortical activity decays 1/fX. The slope of this decay (ie the spectral exponent) is modulated by various factors such as age, cognitive \u2026",
"publication_info": {
"summary": "F Schmidt, SK Danboeck, E Trinka, G Demarchi\u2026 - bioRxiv, 2022 - biorxiv.org",
"authors": [
{
"name": "SK Danboeck",
"link": "https://scholar.google.com/citations?user=6s-AmMwAAAAJ&hl=en&num=20&oi=sra",
"serpapi_scholar_link": "https://serpapi.com/search.json?author_id=6s-AmMwAAAAJ&engine=google_scholar_author&hl=en",
"author_id": "6s-AmMwAAAAJ"
},
{
"name": "G Demarchi",
"link": "https://scholar.google.com/citations?user=GiarXIUAAAAJ&hl=en&num=20&oi=sra",
"serpapi_scholar_link": "https://serpapi.com/search.json?author_id=GiarXIUAAAAJ&engine=google_scholar_author&hl=en",
"author_id": "GiarXIUAAAAJ"
}
]
}
},
"F1tmJHAXx5IJ": {
"title": "Data for: Eelbrain: A Python toolkit for time-continuous analysis with temporal response functions",
"result_id": "F1tmJHAXx5IJ",
Expand Down Expand Up @@ -1533,6 +1626,12 @@
"publication_info": {
"summary": "J Li, L Pylkk\u00e4nen - Journal of Neuroscience, 2021 - Soc Neuroscience",
"authors": [
{
"name": "J Li",
"link": "https://scholar.google.com/citations?user=T5EokYYAAAAJ&hl=en&num=20&oi=sra",
"serpapi_scholar_link": "https://serpapi.com/search.json?author_id=T5EokYYAAAAJ&engine=google_scholar_author&hl=en",
"author_id": "T5EokYYAAAAJ"
},
{
"name": "L Pylkk\u00e4nen",
"link": "https://scholar.google.com/citations?user=yGIs62YAAAAJ&hl=en&num=20&oi=sra",
Expand Down Expand Up @@ -1718,7 +1817,15 @@
"link": "https://search.proquest.com/openview/bae98a7cd0e7c6bbb436ed364ed00e8e/1.pdf?pq-origsite=gscholar&cbl=18750&diss=y",
"snippet": "This dissertation investigates the neural bases and development of displacement, which is a language property that allows us to communicate about situations outside the here-and-now\u2026",
"publication_info": {
"summary": "MA Tulling - 2022 - search.proquest.com"
"summary": "MA Tulling - 2022 - search.proquest.com",
"authors": [
{
"name": "MA Tulling",
"link": "https://scholar.google.com/citations?user=rXzC82IAAAAJ&hl=en&num=20&oi=sra",
"serpapi_scholar_link": "https://serpapi.com/search.json?author_id=rXzC82IAAAAJ&engine=google_scholar_author&hl=en",
"author_id": "rXzC82IAAAAJ"
}
]
}
},
"t5g817um_mQJ": {
Expand Down
5 changes: 4 additions & 1 deletion doc/scripts/selection.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,5 +80,8 @@
"5m5W40xRnIQJ": true,
"jQmGaEK_518J": true,
"lC-KuCZxkksJ": true,
"mBZCoKR6Va4J": true
"mBZCoKR6Va4J": true,
"4D5RTBi0ub8J": false,
"7w3_G4qWqWUJ": true,
"ERvT26o8AlUJ": true
}
3 changes: 1 addition & 2 deletions eelbrain/_experiment/mne_experiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -6238,8 +6238,7 @@ def run_mne_browse_raw(self, modal=False):
Sets the current directory to raw-dir, and sets the SUBJECT and
SUBJECTS_DIR to current values
"""
subp.run_mne_browse_raw(self.get('raw-dir'), self.get('mrisubject'),
self.get('mri-sdir'), modal)
subp.run_mne_browse_raw(self.get('raw-dir'), self.get('mrisubject'), self.get('mri-sdir'), modal)

def set(self, subject=None, match=True, allow_asterisk=False, **state):
"""
Expand Down
5 changes: 2 additions & 3 deletions eelbrain/_stats/glm.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,8 +347,7 @@ def map(self, y, perm=None):
A list with maps of F values (order corresponding to self.effects).
"""
if y.shape[0] != self._n_obs:
raise ValueError("y has wrong number of observations (%i, model "
"has %i)" % (y.shape[0], self._n_obs))
raise ValueError(f"y has wrong number of observations ({y.shape[0]}, model has {self._n_obs})")

# find result container
if self._flat_f_map is None:
Expand Down Expand Up @@ -402,7 +401,7 @@ def preallocate(self, y_shape):
content of this array will change (and map() will not return
anything)
"""
shape = (self.n_effects,) + y_shape
shape = (self.n_effects, *y_shape)
f_map = np.empty(shape)
self._flat_f_map = f_map.reshape((self.n_effects, -1))
return f_map
Expand Down
65 changes: 33 additions & 32 deletions eelbrain/_stats/testnd.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,7 @@ class NDTest:
Map of the test statistic processed with the threshold-free cluster
enhancement algorithm (or None if no TFCE was performed).
"""
_state_common = ('y', 'match', 'sub', 'samples', 'tfce', 'pmin', '_cdist',
'tstart', 'tstop', '_dims')
_state_common = ('y', 'match', 'sub', 'samples', 'tfce', 'pmin', '_cdist', 'tstart', 'tstop', '_dims')
_state_specific = ()
_statistic = None
_statistic_tail = 0
Expand Down Expand Up @@ -224,21 +223,20 @@ def _assert_has_cdist(self):
"with threshold-based clustering and tests with "
"a permutation distribution (samples > 0)")

def masked_parameter_map(self, pmin=0.05, **sub):
"""Create a copy of the parameter map masked by significance
def masked_parameter_map(self, pmin: float = 0.05, **sub) -> NDVar:
"""Statistical parameter map masked by significance
Parameters
----------
pmin : scalar
pmin
Threshold p-value for masking (default 0.05). For threshold-based
cluster tests, ``pmin=1`` includes all clusters regardless of their
p-value.
Returns
-------
masked_map : NDVar
NDVar with data from the original parameter map wherever p <= pmin
and 0 everywhere else.
NDVar
Parameter map with a mask that is ``True`` (masked) where p > pmin.
"""
self._assert_has_cdist()
return self._cdist.masked_parameter_map(pmin, **sub)
Expand Down Expand Up @@ -1298,26 +1296,26 @@ class TTestRelated(NDMaskedC1Mixin, NDDifferenceTest):
0: both (two-tailed, default);
1: upper tail (one-tailed);
-1: lower tail (one-tailed).
samples : int
samples
Number of samples for permutation test (default 10,000).
pmin : None | scalar (0 < pmin < 1)
pmin
Threshold for forming clusters: use a t-value equivalent to an
uncorrected p-value.
tmin : scalar
tmin
Threshold for forming clusters as t-value.
tfce : bool | scalar
tfce
Use threshold-free cluster enhancement. Use a scalar to specify the
step of TFCE levels (for ``tfce is True``, 0.1 is used).
tstart : scalar
tstart
Start of the time window for the permutation test (default is the
beginning of ``y``).
tstop : scalar
tstop
Stop of the time window for the permutation test (default is the
end of ``y``).
parc : str
parc
Collect permutation statistics for all regions of the parcellation of
this dimension. For threshold-based test, the regions are disconnected.
force_permutation: bool
force_permutation
Conduct permutations regardless of whether there are any clusters.
mintime : scalar
Minimum duration for clusters (in seconds).
Expand Down Expand Up @@ -1502,14 +1500,14 @@ class MultiEffectNDTest(NDTest):
def _repr_test_args(self):
args = [repr(self.y), repr(self.x)]
if self.match is not None:
args.append('match=%r' % self.match)
args.append(f'match={self.match!r}')
return args

def _repr_cdist(self):
args = self._cdist[0]._repr_test_args(self.pmin)
for cdist in self._cdist:
effect_args = cdist._repr_clusters()
args.append("%r: %s" % (cdist.name, ', '.join(effect_args)))
args.append(f"{cdist.name!r}: {', '.join(effect_args)}")
return args

def _asfmtext(self, **_):
Expand Down Expand Up @@ -1612,23 +1610,27 @@ def compute_probability_map(self, effect=0, **sub):
i = self._effect_index(effect)
return self._cdist[i].compute_probability_map(**sub)

def masked_parameter_map(self, effect=0, pmin=0.05, **sub):
"""Create a copy of the parameter map masked by significance
def masked_parameter_map(
self,
effect: Union[str, int] = 0,
pmin: float = 0.05,
**sub,
) -> NDVar:
"""Statistical parameter map masked by significance
Parameters
----------
effect : int | str
Index or name of the effect from which to use the parameter map.
pmin : scalar
effect
Index or name of the effect for which to retrieve the parameter map.
pmin
Threshold p-value for masking (default 0.05). For threshold-based
cluster tests, ``pmin=1`` includes all clusters regardless of their
p-value.
Returns
-------
masked_map : NDVar
NDVar with data from the original parameter map wherever p <= pmin
and 0 everywhere else.
NDVar
Parameter map with a mask that is ``True`` (masked) where p > pmin.
"""
self._assert_has_cdist()
i = self._effect_index(effect)
Expand Down Expand Up @@ -1805,30 +1807,29 @@ def __init__(
dfs_denom = lm.dfs_denom
fmaps = lm.map(y.x)

# Cluster-based tests
n_threshold_params = sum((pmin is not None, fmin is not None, bool(tfce)))
if n_threshold_params == 0 and not samples:
cdists = None
thresholds = tuple(repeat(None, len(effects)))
thresholds = repeat(None, len(effects))
elif n_threshold_params > 1:
raise ValueError("Only one of pmin, fmin and tfce can be specified")
else:
if pmin is not None:
thresholds = tuple(stats.ftest_f(pmin, e.df, df_den) for e, df_den in zip(effects, dfs_denom))
thresholds = [stats.ftest_f(pmin, e.df, df_den) for e, df_den in zip(effects, dfs_denom)]
elif fmin is not None:
thresholds = tuple(repeat(abs(fmin), len(effects)))
else:
thresholds = tuple(repeat(None, len(effects)))

cdists = [
NDPermutationDistribution( y, samples, thresh, tfce, 1, 'f', e.name, tstart, tstop, criteria, parc, force_permutation)
for e, thresh in zip(effects, thresholds)]
cdists = [NDPermutationDistribution(y, samples, thresh, tfce, 1, 'f', e.name, tstart, tstop, criteria, parc, force_permutation) for e, thresh in zip(effects, thresholds)]

# Find clusters in the actual data
do_permutation = 0
for cdist, fmap in zip(cdists, fmaps):
cdist.add_original(fmap)
do_permutation += cdist.do_permutation

# Generate null distribution
if do_permutation:
iterator = permute_order(len(y), samples, unit=match)
run_permutation_me(lm, cdists, iterator)
Expand Down

0 comments on commit 9ebbe1c

Please sign in to comment.