Contributing to Elephant¶
You are here to help with Elephant? Awesome, feel welcome to get in touch with us by asking questions, proposing features and improvements to Elephant.
For guidelines on code documentation, please see the Documentation Guide below.
Note
We highly recommend to get in touch with us before starting to implement a new feature in Elephant. This way, we can point out synergies with complementary efforts and help in designing your implementation such that its integration into Elephant will be an easy process.
Get in touch¶
Using the mailing list¶
General discussion of Elephant development takes place in the NeuralEnsemble Google group.
Please raise concrete issues, bugs, and feature requests on the issue tracker.
Using the issue tracker¶
If you find a bug in Elephant, please create a new ticket on the issue tracker. Choose one of the available templates - “Bug report”, “Feature request”, or “Questions”. Choose an issue title that is as specific as possible to the problem you’ve found, and in the description give as much information as you think is necessary to recreate the problem. The best way to do this is to create the shortest possible Python script that demonstrates the problem, and attach the file to the ticket.
If you have an idea for an improvement to Elephant, create a ticket with type “enhancement”. If you already have an implementation of the idea, open a pull request.
Setting up a development environment¶
In order to contribute to the Elephant code, you must set up a Python environment on your local machine.
Fork Elephant as described in Fork a repo. Download Elephant source code from your forked repo:
$ git clone git://github.com/<your-github-profile>/elephant.git $ cd elephant
Set up the virtual environment (either via pip or conda):
conda env create -f requirements/environment.yml
conda activate elephant
pip install -r requirements/requirements-tests.txt
python -m venv elephant-env
source elephant-env/bin/activate
pip install -r requirements/requirements.txt
pip install -r requirements/requirements-extras.txt # optional
pip install -r requirements/requirements-tests.txt
Install elephant development version:
pip install -e .
Before you make any changes, run the test suite to make sure all the tests pass on your system:
$ pytest .
You can specify a particular module to test, for example
test_statistics.py
:$ pytest elephant/test/test_statistics.py
At the end, if you see “OK”, then all the tests passed (or were skipped because certain dependencies are not installed), otherwise it will report on tests that failed or produced errors.
Adding new functionality¶
After you’ve set up a development environment, implement a functionality you want to add in Elephant. This includes, in particular:
fixing a bug;
improving the documentation;
adding a new functionality.
Writing code¶
Imagine that you want to add a novel
statistical measure of a list of spike trains that returns an analog signal in the existing module elephant/statistics.py
.
Let’s call it statistics_x
.
Elephant relies on Neo structures that use Quantities extensively, allowing the users to conveniently specify physical units (e.g., seconds and milliseconds) of input objects. Typically, to avoid computationally expensive quantities rescaling operation on large input arrays, we check that the main data objects - spike trains or analog signals - share the same units and rescale additional parameters (t_start, t_stop, bin_size, etc.) to the units of input objects.
import neo
import quantities as pq
from elephant.utils import check_same_units
def statistics_x(spiketrains, t_start=None, t_stop=None):
"""
Compute the X statistics of spike trains.
Parameters
----------
spiketrains : list of neo.SpikeTrain
Input spike trains.
t_start, t_stop : pq.Quantity or None
Start and stop times to compute the statistics over the specified
interval. If None, extracted from the input spike trains.
Returns
-------
signal : neo.AnalogSignal
The X statistics of input spike trains.
(More description follows.)
"""
check_same_units(spiketrains, object_type=neo.SpikeTrain)
# alternatively, if spiketrains are required to be aligned in time,
# when t_start and t_stop are not specified, use 'check_neo_consistency'
# check_neo_consistency(spiketrains, object_type=neo.SpikeTrain, t_start=t_start, t_stop=t_stop)
# convert everything to spiketrain units and strip off the units
if t_start is None:
t_start = spiketrains[0].t_start
if t_stop is None:
t_stop = spiketrains[0].t_stop
units = spiketrains[0].units
t_start = t_start.rescale(units).item()
t_stop = t_stop.rescale(units).item()
spiketrains = [spiketrain.magnitude for spiketrain in spiketrains]
# do the analysis here on unit-less spike train arrays
x = ...
signal = neo.AnalogSignal(x,
units=...,
t_start=t_start,
sampling_rate=...,
name="X statistics of spiketrains",
...)
return signal
Testing code¶
Write at least one test in elephant/test/test_module_name.py
file that
covers the functionality.
For example, to check the correctness of the implemented statistics_x
function, we add unittest code in elephant/test/test_statistics.py
,
something like
import unittest
import neo
import quantities as pq
from numpy.testing import assert_array_almost_equal
from elephant.statistics import statistics_x
class StatisticsXTestCase(unittest.TestCase):
def test_statistics_x_correctness(self):
spiketrain1 = neo.SpikeTrain([0.3, 4.5, 7.8], t_stop=10, units='s')
spiketrain2 = neo.SpikeTrain([2.4, 5.6], t_stop=10, units='s')
result = statistics_x([spiketrain1, spiketrain2])
self.assertIsInstance(result, neo.AnalogSignal)
self.assertEqual(result.t_start, 0 * pq.s)
expected_magnitude = [0, 1, 2]
assert_array_almost_equal(result.magnitude, expected_magnitude)
... # more checking
Pushing the changes and creating a pull request¶
Now you’re ready to share the code publicly.
Commit your changes:
git add . git commit -m "informative commit message" git push
If this is your first commitment to Elephant, please add your name and affiliation/employer in
doc/authors.rst
Open a pull request. Then we will guide you through the process of merging your code into Elephant.
That’s all! We’re happy to assist you throughout the process of contributing.
If you experience any problems during one of the steps below, please contact us and we’ll help you.
Documentation Guide¶
Writing documentation¶
Each module (python source file) should start with a short description of the listed functionality. Class and function docstrings should conform to the NumPy docstring standard.
Note
Please refer to our Coding Style Guide with Examples.
Building documentation¶
The documentation in doc/
folder is written in reStructuredText, using the
Sphinx documentation system. To build the
documentation locally on a Linux system, follow these steps:
Install requirements-docs.txt and requirements-tutorials.txt the same way it’s explained in Setting up a development environment step 3:
pip install -r requirements/requirements-docs.txt pip install -r requirements/requirements-tutorials.txt
Build the documentation:
cd doc export PYTHONPATH=${PYTHONPATH}.:../.. make html
PYTHONPATH
environmental variable is set in order to find Elephant package while executing jupyter notebooks that are part of the documentation. You may also need to install LaTeX support:sudo apt-get install texlive-full
Open
_build/html/index.html
in your browser.(Optional) To check that all URLs in the documentation are correct, run:
make linkcheck
Citations¶
The citations are in BibTeX format, stored in doc/bib/elephant.bib.
Entries in the .bib are built according to the following specification:
{Last name of first author}+{last two digits of publication year}+"_"+{first page of article}
Example
According to this specification, the following article:
Grün. Data-driven significance estimation of precise spike correlation. J. Neurophysiol., pages 1126–1140, 2009. doi:10.1152/jn.00093.2008.
is added to the .bib-file as Gruen09_1126
. The complete entry for this example is:
@article{Gruen09_1126,
title={Data-driven significance estimation of precise spike correlation},
author={Gr\"{u}n, S.},
year={2009},
journal={J. Neurophysiol.},
number={101},
pages={1126--1140},
doi={10.1152/jn.00093.2008}
}
Each module in doc/reference
folder ends with the reference section:
References
----------
.. bibliography::
:keyprefix: <module name>-
where <module name>
is (by convention) the Python source file name, and
<module name shortcut>
is what will be displayed to the users.
For example, :cite:'spade-Torre2013_132'
will be rendered as sp1
in
the built HTML documentation, if <module name shortcut>
is set to sp
and <module name>
- to spade
.
To cite Elephant itself, refer to Citing Elephant.