Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DOC] Clean up docstring formatting #283

Merged
merged 8 commits into from
Feb 5, 2025

Conversation

tsbinns
Copy link
Collaborator

@tsbinns tsbinns commented Jan 31, 2025

Addresses in particular #222 and #282 to fix all ambiguous single backtick entries, either giving them explicit intersphinx roles or making them double backticks like mentioned here.

Also generally brings the docstrings in line with what seem to be more modern MNE principles, including:

  • converts the old docstrings to take advantage of the 88 line length.
  • uses literals for str params (except in spec_conn_epochs/time() method param since that has loads of possibilities)
  • fixes instances of missing or incorrect types in docstrings.
  • changes instances where information could be rendered as code, code blocks, or lists.
  • remove optional from docstring types and replace with None, e.g. param : type, optional -> param : type | None.
  • use only array as a type instead of np.ndarray or ndarray.
  • use array_like as a type where that is allowed in place of array.
  • make syntax for optional dims in arrays better match the format elsewhere in MNE (I had done this wrong before).
  • replace instances of array of shape (...) or array, shape=(...) with array, shape (...).

I realise it's a lot to go through so I'll try to highlight where actual changes to content have been made as opposed to line length shifts.

Copy link
Collaborator Author

@tsbinns tsbinns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Outline of what changes were made part 1

Comment on lines -27 to +28
Note: In mne-connectivity, we associate the word
"spectral" with time-frequency. Reference to
eigenvalue structure is not captured in this mixin.
Note: In mne-connectivity, we associate the word "spectral" with time-frequency.
Reference to eigenvalue structure is not captured in this mixin.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line length

If these are computed over a frequency band, it will
be the median frequency of the frequency band.
If these are computed over a frequency band, it will be the median frequency of
the frequency band.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line length

Comment on lines -140 to +141
combine : 'mean' | 'median' | callable
How to combine correlation estimates across epochs.
Default is 'mean'. If callable, it must accept one
positional input. For example::
combine : ``'mean'`` | ``'median'`` | callable
How to combine correlation estimates across epochs. Default is ``'mean'``.
If callable, it must accept one positional input. For example::
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line length and use literals

Comment on lines 149 to 147
conn : instance of Connectivity
conn : instance of Connectivity | SpectralConnectivity | TemporalConnectivity | SpectroTemporalConnectivity
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return matches the non-epoched class type of whatever class is being combined. Is specifying that it could be more than just Connectivity too verbose?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for the return types, verbosity is fine if it's needed to be accurate. If there's a succinct way to sum it up, that can go in the textual description, so in addition to "The combined connectivity data structure" it could say something like "type will reflect the input data type (plain, spectral, temporal, spectrotemporal) but without the epoch dimension."

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. In that case I might return to just Connectivity and add context in the description.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps:

Returns
-------
conn : instance of Connectivity
The combined connectivity data structure. Instance type reflects that of the
current instance, without the epoch dimension.

Comment on lines -219 to +218
data : array
Epoched or continuous data set. Has shape
(n_epochs, n_signals, n_times) or (n_signals, n_times).
data : array, shape ([n_epochs,] n_signals, n_times)
Epoched or continuous data set.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line length and shape alongside type

Comment on lines -265 to +266
For multivariate methods, this is handled differently. If "indices" is
None, connectivity between all signals will be computed and a single
connectivity spectrum will be returned (this is not possible if a Granger
causality method is called). If "indices" is specified, seed and target
indices for each connection should be specified as nested array-likes. For
example, to compute the connectivity between signals (0, 1) -> (2, 3) and
(0, 1) -> (4, 5), indices should be specified as::
For multivariate methods, this is handled differently. If ``indices`` is ``None``,
connectivity between all signals will be computed and a single connectivity spectrum
will be returned (this is not possible if a Granger causality method is called). If
``indices`` is specified, seed and target indices for each connection should be
specified as nested array-likes. For example, to compute the connectivity between
signals (0, 1) -> (2, 3) and (0, 1) -> (4, 5), indices should be specified as::
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line length and doubleticks

Comment on lines -300 to +299
where: :math:`\boldsymbol{D}(\Phi)` is the cross-spectral density
between seeds and targets transformed for a given phase angle
:math:`\Phi`; and :math:`\boldsymbol{a}` and :math:`\boldsymbol{b}`
are eigenvectors for the seeds and targets, such that
:math:`\boldsymbol{a}^T\boldsymbol{D}(\Phi)\boldsymbol{b}`
maximises coherency between the seeds and targets. Taking the
absolute value of the results gives maximised coherence.
where: :math:`\boldsymbol{D}(\Phi)` is the cross-spectral density between
seeds and targets transformed for a given phase angle :math:`\Phi`; and
:math:`\boldsymbol{a}` and :math:`\boldsymbol{b}` are eigenvectors for the
seeds and targets, such that :math:`\boldsymbol{a}^T\boldsymbol{D}(\Phi)
\boldsymbol{b}` maximises coherency between the seeds and targets. Taking
the absolute value of the results gives maximised coherence.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only line length changes for eqs.

Comment on lines -845 to +831
``method``. Each element is an array of shape (n_cons, [n_comps], n_freqs) or
(n_cons, [n_comps], n_fbands) if ``faverage`` is `True`. ``n_comps`` is present
for valid multivariate methods if ``n_components > 0``.
``method``. Each element is an array of shape (n_cons, [n_comps,] n_freqs) or
(n_cons, [n_comps,] n_fbands) if ``faverage`` is ``True``. ``n_comps`` is
present for valid multivariate methods if ``n_components > 0``.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional dim syntax

Comment on lines -1108 to +1094
List of connectivity estimates between signals ``x`` and ``y``
corresponding to the methods in ``method``. Each element is an array
with shape (n_freqs,) or (n_fbands) depending on ``faverage``.
List of connectivity estimates between signals ``x`` and ``y`` corresponding to
the methods in ``method``. Each element is an array with shape ``(n_freqs,)`` or
``(n_fbands)`` depending on ``faverage``.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line length, backticks

Comment on lines -1201 to +1188
seed and target patterns, respectively, each with shape ([n_comps], n_channels,
n_freqs) or ([n_comps], n_channels, n_fbands) depending on ``faverage``.
``n_comps`` is present for valid multivariate methods if ``n_components > 0``.
``n_channels`` is the largest number of channels across all connections, with
missing entries padded with ``np.nan``.
seed and target patterns, respectively, each with shape ``([n_comps,]
n_channels, n_freqs)`` or ``([n_comps], n_channels, n_fbands) depending on
``faverage``. ``n_comps`` is present for valid multivariate methods if
``n_components > 0``. ``n_channels`` is the largest number of channels across
all connections, with missing entries padded with ``np.nan``.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Backticks

Copy link
Collaborator Author

@tsbinns tsbinns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview part 2

Comment on lines -20 to +24
data : np.ndarray ([epochs], n_estimated_nodes, [components], [freqs], [times])
The connectivity data that is a raveled array of ``(n_estimated_nodes, ...)`` shape.
The ``n_estimated_nodes`` is equal to ``n_nodes_in * n_nodes_out`` if one is
computing the full connectivity, or a subset of nodes equal to the length of
``indices`` passed in.
data : array, shape ([epochs,] n_estimated_nodes[, components, freqs, times])
The connectivity data that is a raveled array of ``(..., n_estimated_nodes, ...)``
shape. The ``n_estimated_nodes`` is equal to ``n_nodes_in * n_nodes_out`` if one has
computed the full connectivity, or a subset of nodes equal to the length of the
arrays in ``indices`` passed in.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional dim syntax, possibility of epochs dim before nodes

Comment on lines -28 to +30
names : list | np.ndarray | None
The names of the nodes of the dataset used to compute
connectivity. If 'None' (default), then names will be
a list of integers from 0 to ``n_nodes``. If a list
names : array_like | None
The names of the nodes of the dataset used to compute connectivity. If ``None``
(default), then names will be a list of integers from 0 to ``n_nodes``. If a list
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line length, backticks, simplify list or array to array-like

Comment on lines -36 to +40
indices : tuple of arrays | str | None
The indices of relevant connectivity data. If ``'all'`` (default),
then data is connectivity between all nodes. If ``'symmetric'``,
then data is symmetric connectivity between all nodes. If a tuple,
then the first list represents the "in nodes", and the second list
represents the "out nodes". See "Notes" for more information.
indices : tuple of array_like | ``'all'`` | ``'symmetric'`` | None
The indices of relevant connectivity data. If ``'all'`` (default), then data is
connectivity between all nodes. If ``'symmetric'``, then data is symmetric
connectivity between all nodes. If a tuple, then contains two array-likes where the
first array represents the "in nodes" (seeds), and the second array represents the
"out nodes" (targets).
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use literals, line length.
Also removed See "Notes" for more information since connectivity classes (only place this is used) have no notes section explaining indices.
Also suggest adding more context for in nodes as seeds and out nodes as targets, in line with terminology used elsewhere.

Comment on lines -60 to +59
mode : str (default 'multitaper')
The cross-spectral density computation method. Can be ``'multitaper'``,
``'fourier'``, or ``'cwt_morlet'``.
mode : ``'multitaper'`` | ``'fourier'`` | ``'cwt_morlet'``
The cross-spectral density computation method.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use literals

Comment on lines -127 to +124
method : str, optional
The method name used to compute connectivity.
method : str | None
The method name used to compute connectivity (default ``None``).
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace optional -> None

Comment on lines -133 to +128
f'"model" parameter must be one of ' f"(avg-epochs, dynamic), not {model}."
f'"model" parameter must be one of (avg-epochs, dynamic), not {model}.'
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line length

Comment on lines -269 to +267
``(model_order * (n_times - model_order),
n_signals * model_order)``. See Notes.
Y : np.ndarray
``(model_order * (n_times - model_order), n_signals * model_order)``. See Notes.
Y : array
The predicted multivariate time-series. This will have shape
``(model_order * (n_times - model_order),
n_signals * model_order)``. See Notes.
``(model_order * (n_times - model_order), n_signals * model_order)``. See Notes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line length

mne_connectivity/viz/_3d.py Show resolved Hide resolved
Comment on lines 38 to +39
con : array, shape (n_channels, n_channels) | Connectivity
The computed connectivity measure(s).
The connectivity data to plot.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a suggestion

Comment on lines -45 to +46
Connectivity scores. Can be a square matrix, or a 1D array. If a 1D
array is provided, "indices" has to be used to define the connection
indices.
Connectivity scores. Can be a square matrix, or a 1D array. If a 1D array is
provided, ``indices`` has to be used to define the connection indices.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Below is all just line length, backticks and array-likes

Copy link
Member

@drammock drammock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the self-review, it sped things up for me a lot. Just a couple questions to consider

Comment on lines 149 to 147
conn : instance of Connectivity
conn : instance of Connectivity | SpectralConnectivity | TemporalConnectivity | SpectroTemporalConnectivity
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for the return types, verbosity is fine if it's needed to be accurate. If there's a succinct way to sum it up, that can go in the textual description, so in addition to "The combined connectivity data structure" it could say something like "type will reflect the input data type (plain, spectral, temporal, spectrotemporal) but without the epoch dimension."

mne_connectivity/base.py Show resolved Hide resolved
Comment on lines -50 to +56
sm_times=0,
sm_times=0.0,
sm_freqs=1,
sm_kernel="hanning",
padding=0,
padding=0.0,
mode="cwt_morlet",
mt_bandwidth=None,
n_cycles=7,
n_cycles=7.0,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no harm, slightly better IMO

@@ -239,13 +229,13 @@

# Decoding attrs
docdict["filters_"] = """
filters_ : tuple of array, shape=(n_signals, n_components)
filters_ : tuple of array, shape (2, n_signals, n_components)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be (2, (n_signals, n_components)) then? or maybe length-2 tuple of array, shape (n_signals, n_components)? Or even:

Suggested change
filters_ : tuple of array, shape (2, n_signals, n_components)
filters_ : tuple, shape (2,), of array, shape (n_signals, n_components)

(which I don't love, but is in some sense the most consistent). I'm assuming that since this is seeds/targets, there's no guarantee of the two arrays actually having the same shape, so array_like, shape (2, n_signals, n_components) would be inaccurate right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming that since this is seeds/targets, there's no guarantee of the two arrays actually having the same shape

You're completely right.
The variable dim size was being handled like this elsewhere:

indices : tuple of array, shape (2, n_cons, variable)

So that should be updated depending on what is decided upon.


There are also these existing instances (not for multivariate connectivity) that use a similar pattern:

indices : tuple of array_like, shape (2, n_cons)

indices : tuple of array, shape (2, n_cons)

So they should also be updated.


Would you prefer something like tuple, shape (2,), of array, shape (n_signals, n_components) to length-2 tuple of array, shape (n_signals, n_components)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@larsoner which do you like better?

  • length-2 tuple of array, shape (n_signals, n_components)
  • tuple, shape (2,), of array, shape (n_signals, n_components)

or something else?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm in this case the two elements in the tuple can be different shapes, right? In that case the above all somewhat misleadingly make it seem like they have to be the same size... in which case you could just say it needs to be array-like of shape (2, n_signals, n_components). So here I would probably say

indices : tuple of length 2
    The seed and target indices. The `ndarray`s inside the tuple have
    shape `(n_seeds, n_components)` and `(n_targets, n_components)`, respectively.

... assuming n_components does match between the two. If it doesn't, then I'd name them differently like n_seed_components and n_target_components etc.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, that is indeed better than anything I suggested.

Copy link
Collaborator Author

@tsbinns tsbinns Feb 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, so for the decomposition filters and patterns there is this (n_components is the same for seeds and targets):

docdict["filters_"] = """
filters_ : tuple of length 2
A tuple of two arrays containing the spatial filters for transforming the seed and
target data, respectively. The arrays have shape ``(n_seeds, n_components)`` and
``(n_targets, n_components)``.
"""

docdict["patterns_"] = """
patterns_ : tuple of length 2
A tuple of two arrays containing the spatial patterns corresponding to the spatial
filters for the seed and target data, respectively. The arrays have shape
``(n_components, n_seeds)`` and ``(n_components, n_targets)``.
"""


In check_indices this:

Parameters
----------
indices : tuple of length 2 of array_like, shape (n_cons)
A tuple of 2 arrays containing the seed and target channel indices,
respectively.
Returns
-------
indices : tuple of length 2 of array_like, shape (n_cons)
The indices to use for connectivity computation.


In seed_target_indices this:

indices : tuple of length 2 of array, shape (n_cons)
A tuple of 2 arrays containing the seed and target indices, respectively, to use
for connectivity computation.


And in seed_target_multivariate indices this (I don't see a clean way of getting around the variable dim size since here the number of channels can vary not only between seeds and targets, but also differ for each connection):

indices : tuple of length 2 of array, shape (n_cons, variable)
A tuple of two numpy object arrays containing the seed and target indices,
respectively, to use for connectivity computation. The number of channels within
each connection can vary.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And in seed_target_multivariate indices this (I don't see a clean way of getting around the variable dim size since here the number of channels can vary not only between seeds and targets, but also differ for each connection):

If they vary I wouldn't put the shape in the top line at all, instead opting to describe them in the text more verbosely, like
".. can vary, resulting in seed and target shapes of (n_cons, n_channels_seed) and (n_cons, n_channels_target), respectively" or whatever makes sense.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is the updated version:

Parameters
----------
seeds : array_like
Indices of signals for which to compute connectivity from. Has
``n_unique_seeds`` array-like entries containing the channel indices for each
seed. The number of channels within each seed can vary.
targets : array_like
Indices of signals for which to compute connectivity to. Has
``n_unique_targets`` array-like entries containing the channel indices for each
target. The number of channels within each target can vary.
Returns
-------
indices : tuple of length 2 of array
A tuple of two numpy object arrays containing the seed and target indices,
respectively, to use for connectivity computation. Each array has ``n_cons``
array entries containing the channel indices for each connection, where
``n_cons = n_unique_seeds * n_unique_targets``. The number of channels within
each connection can vary.

The notes section also has examples that provide further context.

mne_connectivity/viz/_3d.py Show resolved Hide resolved
@larsoner
Copy link
Member

larsoner commented Feb 5, 2025

Just made one quick comment I noticed based on the comments above @tsbinns.

@drammock I think only one of us needs to read through the +/-1k lines changed, did you want to do it? If not, I'll take a look

@drammock
Copy link
Member

drammock commented Feb 5, 2025

Just made one quick comment I noticed based on the comments above @tsbinns.

@drammock I think only one of us needs to read through the +/-1k lines changed, did you want to do it? If not, I'll take a look

I already did a pass through the whole diff yesterday. The "length-2 tuple of arrays" issue is the only thing left to sort out.

Copy link
Member

@drammock drammock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a few nits / tweaks. thanks for the diligent docstring work @tsbinns

mne_connectivity/base.py Outdated Show resolved Hide resolved
mne_connectivity/utils/docs.py Show resolved Hide resolved
mne_connectivity/utils/docs.py Show resolved Hide resolved
mne_connectivity/utils/docs.py Outdated Show resolved Hide resolved
mne_connectivity/utils/utils.py Show resolved Hide resolved
@drammock drammock enabled auto-merge (squash) February 5, 2025 17:09
@tsbinns
Copy link
Collaborator Author

tsbinns commented Feb 5, 2025

Thanks both for the suggestions, and thanks @drammock for trawling through this mega diff!

@drammock drammock merged commit ee3aad3 into mne-tools:main Feb 5, 2025
12 of 13 checks passed
@tsbinns tsbinns deleted the fix_intersphinx branch February 5, 2025 17:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants