123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638 |
- .. _style_guide:
- ********************************
- Coding Style Guide with Examples
- ********************************
- This guide follows mostly:
- https://github.com/numpy/numpy/blob/master/doc/example.py.
- In the Python code blocks below, some remarks are included using JavaScript
- style notation <!-- comment -->. They provide additional information regarding
- the code that is being presented as example.
- Module docstring
- ----------------
- The module should start with its own docstring in the first line.
- The example below illustrates show it should be implemented.
- .. code-block:: python
- """
- Here comes the module description
- Detailed introduction and tutorial of method goes here.
- You can even link tutorials here, if appropriate.
- If you have references you can insert them here, otherwise in the corresponding
- functions, methods or classes.
- For a working example see
- :py:mod:`unitary_event_analysis.py<elephant.unitary_event_analysis>`
- """
- Function docstring. Naming conventions
- --------------------------------------
- The function below illustrates how arguments and functions should be named
- throughout Elephant.
- .. code-block:: python
- def pair_of_signals_example(spiketrain_i, spiketrain_j):
- # Add '_i' and '_j' suffixes to a pair of signals, spiketrains or any
- # other variables that come in pairs.
- def perfect_naming_of_parameters(spiketrains, spiketrain, reference_spiketrain,
- target_spiketrain, signal, signals, max_iterations,
- min_threshold, n_bins, n_surrogates, bin_size, max_size,
- time_limits, time_range, t_start, t_stop, period, order,
- error, capacity, source_matrix, cov_matrix,
- selection_method='aic'
- ):
- r"""
- Full example of the docstring and naming conventions.
- Function names should be in lowercase, with words written in full, and
- separated by underscores. Exceptions are for common abbreviations, such
- as "psd" or "isi". But words such as "coherence" must be written in full,
- and not truncated (e.g. "cohere").
- If the truncation or abbreviation not in conformity to this naming
- convention was adopted to maintain similarity to a function used
- extensively in another language or package, mention this in the "Notes"
- section, like the comment below:
- <!--
- Notes
- -----
- This function is similar to `welch_cohere` function in MATLAB.
- -->
- The rationale for the naming of each parameter in this example will be
- explained in the relevant "Parameters" section. Class parameters and
- attributes also follow the same naming convention.
- Parameters
- ----------
- <!-- As a general rule, each word is written in full lowercase, separated
- by underscores. Special cases apply according to the examples below -->
- spiketrains : neo.SpikeTrain or list of neo.SpikeTrain
- Within Elephant, this is how to name an input parameter that contains
- at least one spike train. The parameter name is in plural (i.e.,
- `spiketrains`). The function will deal with converting a single
- `neo.SpikeTrain` to a list of `neo.SpikeTrain` if needed.
- Note that although these are two words, they are NOT separated by
- underscore because Neo does not use underscore, and Elephant must keep
- compatibility. Do not use names such as `sts`, `spks`, or
- `spike_trains`.
- spiketrain: neo.SpikeTrain
- If the function EXPLICITLY requires only a single spike train, then
- the parameter should be named in singular (i.e., `spiketrain`). Do
- not use names such as `st`, `spk`, or `spike_train`.
- reference_spiketrain : neo.SpikeTrain
- If a function uses more than one parameter with single spike trains,
- then each parameter name begins with a meaningful name,
- followed by "_spiketrain" in singular form.
- target_spiketrain: neo.SpikeTrain
- Second parameter that is a single spike train. Note that the difference
- from `reference_spiketrain` is indicated by a meaningful name at the
- beginning.
- signal : neo.AnalogSignal
- If a single `neo.AnalogSignal` object is passed to the function, even if
- it contains several signals (arrays).
- signals : list of neo.AnalogSignal
- If the parameter is a container that has at least one `neo.AnalogSignal`
- object. The name of the parameter is `signals` (plural).
- max_iterations : int
- Parameters that represent a maximum value should start with "max_"
- prefix, followed by the description as a full word. Therefore, do not
- use names such as `max_iter` or `maxiter`.
- min_threshold : float
- Same case as for maximum. Parameters that represent a minimum value
- should start with "min_" prefix, followed by the description as a full
- word. Therefore, do not use names such as `min_thr` or `minthr`.
- n_bins : int
- Parameters that represent a number should start with the prefix "n_".
- Do not use `numbins`, `bin_number`, or `num_bins`. The prefix should
- be followed by a meaningful word in full.
- n_surrogates : int
- The description should always be meaningful an without abbreviations.
- Therefore, do not use terms as `n` or `n_surr`, that are not
- immediately understood.
- bin_size : pq.Quantity or int
- Separate the words by underscore. Do not use `bin_size`. Old functions
- which use `binsize` are deprecated.
- max_size : float
- Another example showing that words should be separated by underscores.
- This intersects with the naming convention for a maximum value.
- time_limits: list or tuple
- For parameters that define minimum and maximum values as a list or
- tuple (e.g., [-2, 2]), the parameter must start with a meaningful
- word followed by the suffix "_limits". Preferentially, one should use
- two separated parameters (e.g., `max_time` and `min_time` following
- the convention for maximum and minimum already mentioned). But should
- the function require the definition of limits in this form, use the
- name `_limits` and not `_range` (see next parameter).
- time_range: list
- For parameters that behave like a Python range (e.g. [1, 2, 3, 4])), in
- the sense that it is a sequence, not only the lower and upper limits
- as in the example above, the parameter should start with a meaningful
- name followed by the suffix "_range".
- t_start : pq.Quantity
- Standard name within Elephant for defining starting times.
- t_stop : pq.Quantity
- Standard name within Elephant for defining stopping times.
- period : pq.Quantity
- Oscillation period.
- Always use informative names. In this case, one could name the
- parameter as simply as `T`, since this is standard for referring to
- periods. If the function is implementing computations based on a paper
- that has a formula with a variable "T", acknowledge this after
- describing the formula in the docstring. Therefore, write a sentence
- like "`period` refers to :math:`T`"
- If the Elephant function uses an external function (such as from
- `scipy`), and such function has an argument named `T`, also
- acknowledge this in the docstring. Therefore, write a sentence like
- "`period` is forwarded as argument `T` of `scipy.uses_T` function".
- If the external function already has an informative parameter name
- (such as `period`), the same parameter name can be used in the Elephant
- function if forwarded.
- If several input parameters are forwarded or are members
- of a formula, the docstring can present them together as a list.
- But always use informative names, not single letter names if this is
- how they are described in the paper or implemented in another function.
- order : int
- Order of the Butterworth filter.
- This is an example of how the `N` parameter of `scipy.signal.butter`
- function could be provided by the user of the Elephant function.
- The docstring would present a text similar to
- "`order` is passed as the `N` argument for `scipy.signal.butter` function".
- Also, in the code implementation, use keyword arguments to make this
- explicit (see the implementation of the function below)
- error : float
- In the case the function has an input parameter that corresponds to a
- greek letter in a formula (in a paper, for instance) always use the
- meaning of the greek letter. Therefore, should :math:`\epsilon` refer
- to the error in the formula, the parameter should be named `error`. As
- already mentioned, this is acknowledged in the docstring after the
- description of the formula.
- capacity : float
- Capacity value.
- When using parameters based on a paper (which, e.g., derives some
- formula), and the parameter's name in this paper is a single letter
- (such as `C` for capacity), always use the meaning
- of the letter. Therefore, the parameter should be named `capacity`,
- not `C`. Acknowledge this in the docstring as already mentioned.
- source_matrix: np.ndarray
- Parameters that are matrices should end with the suffix "_matrix", and
- start with a meaningful name.
- cov_matrix: np.ndarray
- A few exceptions allow the use of abbreviations instead of full words
- in the name of the parameter. These are:
- * "cov" for "covariance" (e.g., `cov_matrix`)
- * "lfp" for "local_field_potential" (e.g. `lfp_signal`)
- * "corr" for "correlation" (e.g. `corr_matrix`).
- THESE EXCEPTIONS ARE NOT ACCEPTED FOR FUNCTION NAMES. Therefore, a
- parameter would be named `cov_matrix`, but the function would be named
- `calculate_covariance_matrix`. If the function name becomes very long,
- then an alias may be created and described appropriately in the "Notes"
- section, as mentioned above. For aliases, see example below.
- selection_method : {'aic', 'bic'}
- Metric for selecting the autoregressive model.
- If 'aic', uses the Akaike Information Criterion (AIC).
- If 'bic', uses Bayesian Information Criterion (BIC).
- Default: 'bic', because it is more reliable than AIC due to the
- mathematical properties (see Notes [3]).
- <!-- Note that the default value that comes in the last line is
- followed by comma and a brief reasoning for defining the default
- `selection_method`). -->
- <!-- Other remarks:
- 1. Do not use general parameter names, such as `data` or `matrix`.
- 2. Do not use general result names, such as `result` or `output`.
- 3. Avoid capitalization (such as the examples mentioned for parameters
- such as `T` for period, or `C` for capacity or a correlation matrix.
- -->
- Returns
- -------
- frequency : float
- The frequency of the signal.
- filtered_signal : np.ndarray
- Signal filtered using Butterworth filter.
- Notes
- -----
- 1. Frequency is defined as:
- .. math::
- f = \frac{1}{T}
- `period` corresponds to :math:`T`
- 2. `order` is passed as the `N` parameter when calling
- `scipy.signal.butter`.
- 3. According to [1]_, BIC should be used instead of AIC for this
- computation. The brief rationale is .......
- References
- ----------
- .. [1] Author, "Why BIC is better than AIC for AR model", Statistics,
- vol. 1, pp. 1-15, 1996.
- """
- # We use Butterworth filter from scipy to perform some calculation.
- # Note that parameter `N` is passed using keys, taking the value of the
- # `order` input parameter
- filtered_signal = scipy.signal.butter(N=order, ...)
- # Here we calculate a return value using a function variable. Note that
- # this variable is named in the "Returns" section
- frequency = 1 / period
- return frequency, filtered_signal
- Class docstring
- ---------------
- Class docstrings follow function docstring format. Here is an example.
- .. code-block:: python
- class MyClass(object): # Classes use CamelCase notation
- """
- One line description of class.
- Long description of class, may span several lines. Possible sections are
- the same as for a function doc, with additional "Attributes" and "Methods"
- after "Parameters" (cf. numpydoc guide). Do not put a blank line after
- section headers, do put a blank line at the end of a long docstring.
- When explaining the algorithm, you can use mathematical notation, e.g.:
- .. math::
- E = m c^2
- To insert an equation use `.. math::` and surround the whole expression in
- blank lines. To use math notation in-line, write :math:`E` corresponds to
- energy and :math:`m` to mass. Embed expressions after `:math:` in
- backticks, e.g. :math:`x^2 + y^2 = z^2`.
- To refer to a paper in which formula is described, use the expression
- "see [1]_" - it will become an interactive link on the readthedocs website.
- The underscore after the closing bracket is mandatory for the link to
- work.
- To refer to a note in the "Notes" section, simply write "see Notes [1]".
- Variable, module, function, and class names should be written
- between single back-ticks (`kernels.AlphaKernel`), NOT *bold*.
- For common modules such as Numpy and Quantities, use the notation
- according to the import statement. For example:
- "this function uses `np.diff`", not "uses `numpy.diff`".
- Prefixes for common packages in Elephant are the following:
- 1. Neo objects = neo (e.g. `neo.SpikeTrain`)
- 2. Numpy = np (e.g. `np.ndarray`)
- 3. Quantities = pq (e.g. `pq.Quantity`)
- For other objects, list the full path to the object (e.g., for the
- BinnedSpikeTrain, this would be `elephant.conversion.BinnedSpikeTrain`)
- For None and NaNs, do not use backticks. NaN is referred as np.NaN (i.e.,
- with the Numpy prefix "np").
- Use backticks also when referring to arguments of a function (e.g., `x` or
- `y`), and :attr:`attribute_name` when referring to attributes of a class
- object in docstrings of this class.
- To refer to attributes of other objects, write
- `other_object.relevant_attribute` (e.g. `neo.SpikeTrain.t_stop`).
- When mentioning a function from other module, type `other_module.function`
- (without parentheses after the function name; e.g., `scipy.signal.butter`).
- If you refer values to True/False/None, do not use backticks, unless an
- emphasis is needed. In this case, write `True` and not bold, like **True**.
- Parameters
- ----------
- <!-- List the arguments of the constructor (__init__) here!
- Arguments must come in the same order as in the constructor or function -->
- parameter : int or float
- Description of parameter `parameter`. Enclose variables in single
- backticks. The colon must be preceded by a space.
- no_type_parameter
- Colon omitted if the type is absent.
- x : float
- The X coordinate.
- y : float
- The Y coordinate.
- Default: 1.0. <!-- not "Default is 1.0." (it is just a convention) -->
- z : float or int or pq.Quantity
- This is Z coordinate.
- If it can take multiple types, separate them by "or", do not use commas
- (numpy style).
- If different actions will happen depending on the type of `z`, explain
- it briefly here, not in the main text of the function/class docstring.
- s : {'valid', 'full', 'other'}
- This is the way to describe a list of possible argument values, if the
- list is discrete and predefined (typically concerns strings).
- If 'valid', the function performs some action.
- If 'full', the function performs another action.
- If 'other', the function will ignore the value defined in `z`.
- Default: 'valid'.
- spiketrains : neo.SpikeTrain or list of neo.SpikeTrain or np.ndarray
- When the parameter can be a container (such as list or tuple), you can
- specify the type of elements using "of". But use the Python type name
- (do not add "s" to make it plural; e.g., do not write
- "list of neo.SpikeTrains" or "list of neo.SpikeTrain objects").
- counts_matrix : (N, M) np.ndarray
- This is the way to indicate dimensionality of the required array
- (i.e.,if the function only works with 2D-arrays). `N` corresponds to
- the number of rows and `M` to the number of columns. Refer to the same
- `N` and `M` to describe the dimensions of the returned values when
- they are determined by the dimensions of the parameter.
- is_true : bool
- True, if 1.
- False, if 0.
- Default: True.
- other_parameter : int
- Some value.
- If value is None and the function takes some specific action (e.g.,
- calculate some value based on the other inputs), describe here.
- Default: None.
- Attributes
- ----------
- <!-- Here list the attributes of class object which are not simply copies
- of the constructor parameters. Property decorators (@property) are also
- considered attributes -->
- a : list
- This is calculated based on `x` and `y`.
- b : int
- This is calculated on the way, during some operations.
- Methods
- -------
- <!-- Here list the most important/useful class methods (not all the
- methods) -->
- Returns
- -------
- <!-- This section is rarely used in class docstrings, but often in
- function docs. Follow the general recommendation of numpydoc.
- If there is more than one returned value, use variable names for the
- returned value, like `error_matrix` below. -->
- error_matrix : np.ndarray
- A matrix is stored in a variable called `error_matrix`, containing
- errors estimated from some calculations. The function "return"
- statement then returns the variable (e.g. "return error_matrix").
- Format is the same as for any parameter in section "Parameters".
- Use meaningful names, not general names such as `output` or `result`.
- list
- The returned object is created on the fly and is never assigned to
- a variable (e.g. "return [1, 2, 3]"). Simply name the type and
- describe the content. This should be used only if the function returns
- a single value.
- dict
- key_1 : type
- Description of key_1, formatted the same as in "Parameters".
- key_2 : type
- Description of key_2
- particular_matrix : (N, N, M) np.ndarray
- The dimensionality of this array depends on the dimensionality of
- `counts_matrix` input parameter. Note that `N` and `M` are used since
- these were the names of the dimensions of `counts_matrix` in the
- "Parameters" section.
- list_variable : list of np.ndarray
- Returns a list of numpy arrays.
- signal : int
- Description of `signal`.
- Raises
- ------
- <!-- List the errors explicitly raised by the constructor (raise
- statements), even if they are in fact raised by other Elephant functions
- called inside the constructor. Enumerate them in alphabetical order. -->
- TypeError
- If `x` is an `int` or None.
- If `y` is not a `float`.
- ValueError
- If this and that happens.
- Warns
- -----
- <!-- Here apply the same rules as for "Raises". -->
- UserWarning
- If something may be wrong but does not prevent execution of the code.
- The default warning type is UserWarning.
- Warning
- -------
- <!-- Here write a message to the users to warn them about something
- important.
- Do not enumerate Warnings in this section! -->
- See Also
- --------
- <!-- Here refer to relevant functions (also from other modules). Follow
- numpydoc recommendations.
- If the function name is not self-explanatory, you can add a brief
- explanation using a colon separated by space.
- This items will be placed as links to the documentation of the function
- referred.
- -->
- statistics.isi
- scipy.signal.butter : Butterworth filter
- Notes
- -----
- <!-- Here you can add some additional explanations etc. If you have several
- short notes (at least two), use a list -->
- 1. First remark.
- 2. Second much longer remark, which will span several lines. To refer to a
- note in other parts of the docstring, use a phrase like "See Notes [2]".
- To make sure that the list displays correctly, keep the indentation to
- match the first word after the point (as in this text).
- 3. If you want to explain why the default value of an argument is
- something particular, you can give a more elaborate explanation here.
- 4. If the function has an alias (see the last function in this file), the
- information about it should be in this section in the form:
- Alias: bla.
- Aliases should be avoided.
- 5. Information about validation should be here, and insert bibliographic
- citation in the "References". Also specify in parenthesis the unit test
- that implements the validation. Example:
- "This function reproduces the paper Riehle et al., 1997 [2]_.
- (`UETestCase.test_Riehle_et_al_97_UE`)."
- 6. Do not create new section names, because they will not be displayed.
- Place the relevant information here instead.
- 7. This is an optional section that provides additional information about
- the code, possibly including a discussion of the algorithm. This
- section may include mathematical equations, written in LaTeX format.
- Inline: :math:`x^2`. An equation:
- .. math::
- x(n) * y(n) \Leftrightarrow X(e^{j\omega } )Y(e^{j\omega } )
- 8. Python may complain about backslashes in math notation in docstrings.
- To prevent the complains, precede the whole docstring with "r" (raw
- string).
- 9. Images are allowed, but should not be central to the explanation;
- users viewing the docstring as text must be able to comprehend its
- meaning without resorting to an image viewer. These additional
- illustrations are included using:
- .. image:: filename
- References
- ----------
- .. [1] Smith J., "Very catchy title," Elephant 1.0.0, 2020. The ".." in
- front makes the ref referencable in other parts of the docstring.
- The indentation should match the level of the first word AFTER the
- number (in this case "Smith").
- Examples
- --------
- <!-- If applicable, provide some brief description of the example, then
- leave a blank line.
- If the second example uses an import that was already used in the first
- example, do not write the import again.
- Examples should be very brief, and should avoid plotting. If plotting
- is really needed, use simple matplotlib plots, that take only few lines.
- More complex examples, that require lots of plotting routines (e.g.,
- similar to Jupyter notebooks), should be placed as tutorials, with links
- in the docstring. Examples should not load any data, but only use easy
- generated data.
- Finally, avoid using abbreviations in examples, such as
- "import elephant.conversion as conv" -->
- >>> import neo
- >>> import numpy as np
- >>> import quantities as pq
- ...
- ... # This is a way to make a blank line within the example code.
- >>> st = neo.SpikeTrain([0, 1, 2, 3] * pq.ms, t_start=0 * pq.ms,
- ... t_stop=10 * pq.ms, sampling_rate=1 * pq.Hz)
- ... # Use "..." also as a continuation line.
- >>> print(st)
- SpikeTrain
- Here provide a brief description of a second example. Separate examples
- with a blank line even if you do not add any description.
- >>> import what_you_need
- ...
- >>> st2 = neo.SpikeTrain([5, 6, 7, 8] * pq.ms, t_start=0 * pq.ms,
- ... t_stop=10 * pq.ms, sampling_rate=1 * pq.Hz)
- >>> sth = what_you_need.function(st2)
- >>> sth_else = what_you_need.interesting_function(sth)
- """
- def __init__(self, parameter):
- """
- Constructor
- (actual documentation is in class documentation, see above!)
- """
- self.parameter = parameter
- self.function_a() # creates new attribute of self 'a'
- def function_a(self, parameter, no_type_parameter, spiketrains,
- is_true=True, string_parameter='C', other_parameter=None):
- """
- One-line short description of the function.
- Long description of the function. Details of what the function is doing
- and how it is doing it. Used to clarify functionality, not to discuss
- implementation detail or background theory, which should rather be
- explored in the "Notes" section below. You may refer to the parameters
- and the function name, but detailed parameter descriptions still
- belong in the "Parameters" section.
- Parameters
- ----------
- <!-- See class docstring above -->
- Returns
- -------
- <!-- See class docstring above -->
- Raises
- ------
- <!-- See class docstring above.
- List only exceptions explicitly raised by the function -->
- Warns
- -----
- <!-- See class docstring above. -->
- See Also
- --------
- <!-- See class docstring above -->
- Notes
- -----
- <!-- See class docstring above -->
- References
- ----------
- <!-- See class docstring above -->
- Examples
- --------
- <!-- See class docstring above -->
- """
- # Variables use underscore notation
- dummy_variable = 1
- a = 56 # This mini comment uses two spaces after the code!
- # Textual strings use double quotes
- error = "An error occurred. Please fix it!"
- # Textual strings are usually meant to be printed, returned etc.
- # Non-textual strings use single quotes
- default_character = 'a'
- # Non textual strings are single characters, dictionary keys and other
- # strings not meant to be returned or printed.
- # Normal comments are proceeded by a single space, and begin with a
- # capital letter
- dummy_variable += 1
- # Longer comments can have several sentences. These should end with a
- # period. Just as in this example.
- dummy_variable += 1
- # Class functions need only 1 blank line.
- # This function is deprecated. Add a warning!
- def function_b(self, **kwargs):
- """
- This is a function that does b.
- .. deprecated:: 0.4
- `function_b` will be removed in elephant 1.0, it is replaced by
- `function_c` because the latter works also with Numpy Ver. 1.6.
- Parameters
- ----------
- kwargs : dict
- kwarg1 : type
- Same style as docstring of class `MyClass`.
- kwarg2 : type
- Same style as docstring of class `MyClass`.
- """
- pass
|