diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 751c801b2c5ae294ea8433384535882c25f49a5a..06ad387edb3200b58c07a608298af55884f2e21d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ There are many ways to contribute: writing tutorials or blog posts, improving th documentation, submitting bug reports and feature requests or writing code which can be incorporated into Arbor itself. -[On our wiki](https://github.com/arbor-sim/arbor/wiki/How-to-contribute) we have laid out how you +The Arbor documentation has a [Contributing section](https://arbor.readthedocs.io/en/latest/contrib) where we have laid out how you can go about making your contribution. ## Get in touch diff --git a/doc/contrib/coding-style.rst b/doc/contrib/coding-style.rst new file mode 100644 index 0000000000000000000000000000000000000000..cd5b79a8905651450a524fc6be47be0bd5803c2f --- /dev/null +++ b/doc/contrib/coding-style.rst @@ -0,0 +1,489 @@ +.. _contribcodingstyle + +Coding Guidelines +================= + +The main development language of Arbor is C++. For Arbor we start with +the community guidelines set out in the `C++ Core +Guidelines <http://isocpp.github.io/CppCoreGuidelines/>`__. These +guidelines are quite generic, and only give loose guidelines for some +important topics like variable naming and indentation. + +This wiki will describe the specific extensions and differences to the +C++ Core Guidelines - variable naming. - code formatting (indentation, +placement of curly braces, ``int const&`` vs ``const int&`` etc.) - +rules for topics not covered in the Core Guidelines (e.g. CUDA). - +exceptions to the rules given in the Core Guidelines. - rules for the +CMake build system and directory structure. - rules for external +dependencies (e.g. Boost). + +.. TODO:: + This page needs revision. + +Code organisation +----------------- + +Source files naming conventions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. TODO:: describe the public/private header and source code organization. + +- ``.cpp`` extension for source files +- ``.hpp`` extension for header files +- Names must be lowercase with words separated with underscores. + +Namespaces +---------- + +All code is in ``namespace arb``. + +As an example, the ``std::make_unique<>`` function template was not +provided as part of C++11 (it wasn’t introduced until C++14), and we +would like to use it in Arbor. The code sample below shows how +namespaces are declared and formatted in Arbor: + +:: + + namespace arb { + namespace util { + + // just because we aren't using C++14, doesn't mean we shouldn't have make_unique + template <typename T, typename... Args> + std::unique_ptr<T> make_unique(Args&&... args) { + return std::unique_ptr<T>(new T(std::forward<Args>(args) ...)); + } + + } // namespace util + } // namespace arb + +In the example above the namespaces are not indented. However, +namespaces should be indented if they are declared in the middle of +code, to make their existance obvious to the person reading the code. + +Use an ``impl`` namespace to hide implementation details that should not +be exposed to user space. + +You can use ``using`` statements to import individual types or functions +from a namespace - only if it really improves the readability of your +code - only in a function or class scope: don’t pollute namespaces + +Formatting statements +--------------------- + +A lot of the rules here are purely a matter of personal taste, imposed +by the guy who got to set the rules. That said, it follows accepted +practice in the C++ community (if we accept that not everybody has the +same accepted practice), and if followed consistently will make code +easier to understand. + +.. code:: c++ + + template <typename T> + class array { + public: + using value_type = T; + + value_type& operator[] (std::size_t i) { + return data_[i]; + } + + const value_type& operator[] (std::size_t i) const { + return data_[i]; + } + + std::size_t size() const { + return size_; + } + + private: + value_type* data_; + std::size_t size_; + }; + + // use new lines and indentation to make complex template expressions + // human readable + template < + typename T, + typename = typename // assert that T is a built-in arithmetic type + std::enable_if< + std::is_arithmetic<T>::value + > + > + T sum(const array<T>& in) { + return std::accumulate(in.begin(), in.end(), 0); + } + +TODO: When declaring an operator, should we leave a space between the +operator and the following opening parenthesis or should we follow the +convention we use for functions, where we don’t leave a space? + +Indentation and whitespace cleanup +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- No tabs, 4 spaces +- Take the extra effort to remove trailing whitespace (at the end of + the lines and the file). +- Respect 80-column limit, but go for longer lines when they make sense + (and make the code clearer) + +Variable naming conventions +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +All lowercase, words separated by ``_``, but template parameters follow +camel case: + +.. code:: c++ + + template <typename ValueType> + class my_class { + public: + // ... + private: + ValueType val_; + }; + +Single letter template parameters should be preferred. + +TODO: Or should we force single letter parameters aliased by more +meaningful type names inside the class (either public or private +depending on our intent)? + +*Avoid* obfuscated names of old C heritage. + +Recurring variables naming conventions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +TODO: Some variable names are recurring a lot inside every code. It +would be nice if we could decide on the most common ones. + +- ``count`` or ``cnt`` +- ``index`` or ``idx`` +- ``iter`` or ``it`` +- … + +Ben says “depends… I would use ``count`` or ``index`` unless the scope +of the variable is very small. Using ``it`` is standard C++ short hand, +but again for fairly limited scope.†+ +Member variables +~~~~~~~~~~~~~~~~ + +Private member variables must be suffixed by ``_``, while public member +variables must not. + +TODO: Any conventions about ``static`` variables, ``const``\ s or global +``const``\ s? + +Member initialisation lists +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Constructors member initialisation lists should be as follows: + +.. code:: c++ + + // everything goes on one line if clear + class my_class { + public: + my_class(int a): + a_(a) + {} + + my_class(int a, int b, int c): + a_(a), b_(b) , c_(c) + {} + + private: + int a_ = 0; + int b_ = 0; + int c_ = 0; + }; + + // use one entry per line if multiple lines needed + class my_class { + public: + my_class(int a, int o, int p): + apple_(a), + orange_(o), + pear_(find_pair_type(p)) + {} + + private: + int apple_; + int orange_; + int pear_; + }; + +Member functions +~~~~~~~~~~~~~~~~ + +Make sure to declare ``const`` if it is not changing the object’s state. + +Getters and Setters +~~~~~~~~~~~~~~~~~~~ + +Before filling up a class with getters and setters, consider seriously +if those members are meant actually to be public. If nonetheless getters +and/or setters are needed, don’t use the ``get_`` and ``set_`` prefixes. + +.. code:: c++ + + template <typename T> + class my_class { + public: + // ... + T value() const { + return value_; + } + + void value(const T& val) { + // perhaps do something before assigning, otherwise it could be just public + value_ = val; + } + private: + T value_; + }; + +Declaring references and pointers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code:: c++ + + // ok + std::string& s = ...; + const std::string& s = ...; + std::string* s = ...; + const std::string* s = ...; + std::string* const s = ...; + + // not ok + std::string &s = ...; + const std::string &s = ...; + std::string *s = ...; + const std::string *s = ...; + std::string *const s = ...; + +Generally, we follow C++’s convention for references and pointers, as it +is the style used in the C++ standard, and also the recommendation of +the `C++ Core Guidelines +NL.18 <http://isocpp.github.io/CppCoreGuidelines/#nl18-use-c-style-declarator-layout>`__. +Precedence and the C++ language grammar may offer some support the other +convention, but not enough support! + +Macros +~~~~~~ + +Macros are C-ish, so they must be avoided. If not possible, they must be +written in capitals, with words separated by underscores. + +Always use ``{}``, even for single statement ``if``, ``for``, etc +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It makes code clearer, and avoids nasty bugs that occur when +refactoring. It also avoids some errors when merging with git. + +:: + + + // ok + for (auto& v: vector) { + // increment the value! + v++; + } + + // bad + for (auto& v: vector) + // increment the value! + v++; + +don’t put ``{`` on a new line +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Except when indentation of arguments or when doing member initialization +in constructors. + +:: + + // it makes sense to have the { on a new line here for clarity + std::vector<std::string> foo( + std::vector<std::vector<int>>& values, + std::map<int, std::string>& name_table) + { + // do some work + } + +leave a space between ``if``, ``for`` etc and following parenthesis +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Accords with `K&R +style <http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html#Rl-knr>`__, +and makes a visual distinction with function evaluation + +:: + + // ok + for (auto& v: vector) { + v++; + } + + // not ok + for(auto& v: vector) { + v++; + } + +use ``using`` instead of ``typedef`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It is easier to read, consistent with ``auto``: + +:: + + // good + using int_container = std::vector<int>; + + // bad + typedef std::vector<int> int_container; + +and can be used for template aliases + +:: + + template <typename T> + using aligned_container = std::vector<T, my_fancy_aligned_allocator<T>>; + +Use scoped enum instead of enum +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + // good + enum class ionKind {sodium, calcium}; + // bad + enum ionKind {ion_sodium, ion_calcium}; + +And stick to the naming scheme for all enums of ``xxxKind`` to make it +clear throughout the code whenever an enum is being used, for example: + +:: + + auto i = current(voltage, ionKind::calcium); + +Use ``struct`` for POD wrappers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +But ``class`` if it has any sort of fancy logic associated with it + +Memory management +----------------- + +use ``unique_ptr`` +~~~~~~~~~~~~~~~~~~ + +Actually, feel free to use naked pointers in your code, but make sure +that you use smart pointers to handle allocation and freeing of memory. +When a developer sees a naked pointer in Arbor they can think “good, I +don’t have to worry about responsibility for freeing that memoryâ€. +Furthermore, if ``unique_ptr`` handles allocation and freeing of memory, +the user doesn’t have to concern themselves with freeing memory ever. + +This practice implies that care must be taken to ensure that the +resource managed by a ``unique_ptr`` has to outlive any raw pointers +that are obtained from its ``get()`` member. + +while avoiding ``shared_ptr`` whenever possible +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you think long and hard, you will probably realise that you actually +want a ``unique_ptr``. Shared pointers have performance overheads, and +are quite easy to misuse. For example by creating circular references +that ironically lead to memory never being freed. + +Header files +------------ + +use pragma once +~~~~~~~~~~~~~~~ + +Use ``#pragma once`` to guard against including the same header twice. +This might not be completely standard compliant, but it is supported by +every compiler under the sun, and is much cleaner than ``#ifdef`` +guards. + +don’t rely on headers being included elsewhere +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For example, if you use ``std::vector<int>`` in a file, make sure to +have ``#include <vector>`` at the top of the source file. + +Relying on headers being include elsewhere can lead to portability +problems, for example on OS X you have to ``#include <cmath>`` for some +math functions that are imported via other header files with gcc on +Linux. + +Sort headers alphabetically +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To make it easy to search for a header in a long list of includes. + +For example: + +.. code:: c++ + + #include <algorithm> + #include <fstream> + #include <map> + #include <queue> + #include <set> + +use C++ wrappers for C standard headers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code:: c++ + + // good + #include <cmath> + #include <cstdio> + + // bad + #include <math.h> + #include <stdio.h> + +when calling C stdlib functions, use the ``std::``-prefix versions, +e.g., ``std::printf(...)`` instead of ``printf``. Most of the times C++ +wrappers just bring into ``std`` the C declarations, but sometimes the +wrappers have more syntactic sugar and call the same internal builtins +that their C counterparts call (for example GCC). + +group headers together +~~~~~~~~~~~~~~~~~~~~~~ + +In the following order + +1. C++ standard libary +2. system C headers (POSIX, kernel interfaces etc.) +3. external libraries +4. public arbor headers +5. private arbor headers + +For example: + +.. code:: c++ + + // first C++ standard headers + #include <algorithm> + #include <fstream> + #include <map> + + // then system C headers + #include <signal.h> + #include <sys/select.h> + + // externals + #include <vector/Vector.hpp> + + // public arbor headers + #include <arbor/common_types.hpp> + #include <arbor/simulation.hpp> + + // private arbor headers (note we use quotes for private project headers). + #include "cell_group.hpp" + #include "util/optional.hpp" diff --git a/doc/contrib/doc.rst b/doc/contrib/doc.rst new file mode 100644 index 0000000000000000000000000000000000000000..0dca60271ea239d350ef74f64ff20ee5ebc757c2 --- /dev/null +++ b/doc/contrib/doc.rst @@ -0,0 +1,53 @@ +.. _contribdoc: + +Documentation +===================== + +The source for `the documentation <https://arbor.readthedocs.io>`__ is +found in the ``/doc`` subdirectory. You can add your contribution to the documentation +in the same way you would contribute code, please see the :ref:`contribpr` section. + +.. todo:: + This page is under construction. + +.. _contribdoc-update: + +Update policy +------------- + +How to we decide if documentation is good? By observing how effective it is used +in practice. If a question on Arbor (regardless of medium) is satisfactorily +resolved (on both sides!) by with a pointer to the (relevant section in the) docs, +the documentation was good. If, on the other hand, explanation was needed, the +documentation was bad. + +If you found the documentation to be insufficiently clear or elaborate, you must +consider this a bug and find or file an `issue <https://github.com/arbor-sim/arbor/issues>`__ and if you are able, make a :ref:`pull request <contribpr>`. + +.. _contribdoc-namingconventions: + +Labels and filename conventions +------------------------------- + +Although it is not absolutely essential to do so, we try to keep to the following conventions +for naming files and labels, with the goal of making it easy to construct one from the other +such that you don't have to remember or look anything up. We try to cross-link where we can, +which means we label where we can, which translates to a large number of labels. + +Wherever possible, observe: + +* file names: avoid underscores as much as possible. E.g. `cpp/cable_cell.rst` -> `cpp/cablecell.rst`. +* page-level labels in each file: the path concatenated without spaces. E.g. `cpp/cablecell.rst` -> `cppcablecell`. +* heading labels in a file: `pagelevel-sectionname`. Feel free to slugify long headings. +E.g. the morphology section in the C++ cable cell docs could be `cppcablecell-morph`. + +.. _contribdoc-lang: + +Language +-------- + +Although the primary language of Arbor is C++, we use English for most of the non-code. +If in doubt, we recommend following the European Union's +`English style guide <https://ec.europa.eu/info/sites/info/files/styleguide_english_dgt_en.pdf>`_. + +In general we try to have a relaxed and concise approach to the language. diff --git a/doc/contrib/example.rst b/doc/contrib/example.rst new file mode 100644 index 0000000000000000000000000000000000000000..423ac49ca17d72041dede2451cd0fbb031ef2eec --- /dev/null +++ b/doc/contrib/example.rst @@ -0,0 +1,11 @@ +.. _contribexample: + +Examples +=============== + +The source for C++ examples are located in ``/example`` and +Python examples in ``/python/example``. You can add yours in the same +way you would contribute code, please see the :ref:`contribpr` section. + +.. todo:: + This page is under construction. diff --git a/doc/contrib/index.rst b/doc/contrib/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..8ac99092651dd6c23c33b7c4504e4c4b80b2644e --- /dev/null +++ b/doc/contrib/index.rst @@ -0,0 +1,114 @@ +.. _contribindex: + +Contributing to Arbor +===================== + +First off, thank you for considering contributing to Arbor! It’s people +like you that make Arbor such a great tool. Feel welcome and read the +following sections in order to know how to ask questions and how to work +on something. + +.. _contribindex-types: + +Types of contributions +---------------------- + +There are many ways to contribute: writing tutorials or blog posts, +improving the documentation, helping other users, submitting bug reports +and feature requests or writing code which can be incorporated into +Arbor itself. + +Use the `Arbor Discussions <https://github.com/arbor-sim/arbor/discussions>`__ +page for support questions. + +.. _contribindex-github: + +Github +------ + +Arbor uses Git for version control and Github to host its code +repository and nearly all of its infrastructure. + +- If you’re not familiar with Git or Github, please have at look at + `this introduction <https://docs.github.com/en/free-pro-team@latest/github/getting-started-with-github/set-up-git>`__. +- Make sure you have a `GitHub + account <https://github.com/signup/free>`__. + +.. _contribindex-discuss: + +Start a discussion +~~~~~~~~~~~~~~~~~~ + +You can use the `Arbor +Discussions <https://github.com/arbor-sim/arbor/discussions>`__ to help +other users of Arbor, or get help with you own simulations. Also, we’re +eager to discover what you’re using Arbor for, so don’t hesitate to +share your Arbor simulations or publications! + +.. _contribindex-fileissue: + +Filing an issue +~~~~~~~~~~~~~~~ + +If you have found a bug or problem in Arbor, or want to request a +feature, you can use our `issue +tracker <https://github.com/arbor-sim/arbor/issues>`__. If you issue is +not yet filed in the issue tracker, please do so and describe the +problem, bug or feature as best you can. You can add supporting data, +code or documents to help make your point. + +.. _contribindex-solveissue: + +Help solving an Issue +~~~~~~~~~~~~~~~~~~~~~ + +If you want to help solve an issue, that’s great! Issue labels can help +you find an something that fits your expertise or interest, and if +you’re just getting started, you can look for the “`good 1st +issue <https://github.com/arbor-sim/arbor/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+1st+issue%22>`__†+label. Don’t hesitate to post a comment to the Issue if you want to ask +clarifying questions. If you have implemented a fix, you can make a pull +request. + +Write code +~~~~~~~~~~ + +See :ref:`contribpr`. + +Add examples or unit tests +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +See :ref:`contribexample` and :ref:`contribtest`. + +Modify documentation +~~~~~~~~~~~~~~~~~~~~ + +See :ref:`contribdoc`. + +Making a pull request +~~~~~~~~~~~~~~~~~~~~~ + +See :ref:`contribpr`. + +.. _contribindex-other: + +Other contributions +------------------- + +We're always happy to hear about Arbor being used! Have you used Arbor to create a model? +Have you used Arbor in a publication? Do you have a workflow or tool that involves Arbor? +Get in touch and we'd be very happy to showcase your work through our channels. + +.. _contribindex-contact: + +Get in touch +------------ + +You can reach out in the following ways: + +- `Discussions <https://github.com/arbor-sim/arbor/discussions>`__. Any + questions or remarks regarding using Arbor for your research are + welcome. +- `Slack <https://mcnest.slack.com>`__. If you’re interested in + developing Arbor itself, you can visit our Slack. +- `Email <mailto:arbor-sim@fz-juelich.de>`__. diff --git a/doc/contrib/pr.rst b/doc/contrib/pr.rst new file mode 100644 index 0000000000000000000000000000000000000000..32c075500da53417de1f478b7764801d7c39bca7 --- /dev/null +++ b/doc/contrib/pr.rst @@ -0,0 +1,90 @@ +.. _contribpr: + +PR workflow +=========== + +.. _contribpr-make: + +Making a pull request +--------------------- + +If you want to contribute code that implements a solution or feature, +the workflow is as follows: + +1. Fork the Arbor repository +2. Create a branch off of master and implement your feature +3. Make a pull request (PR) and refer to the issue(s) that the PR + addresses. +4. An administrative matter: Arbor requests `an explicit copyright + assignment <https://en.wikipedia.org/wiki/Copyright_transfer_agreement>`__ + on your contribution. This grants us the right to defend copyright on + your contributions on your behalf, and allows us to change the + license on your contribution to another open source license should + that become necessary in the future. You can upload a filled out copy + of the agreement as a file attached to the PR, or if you prefer not + to disclose private information, you can send it to + `arbor-sim@fz-juelich.de <mailto:arbor-sim@fz-juelich.de>`__. + + - `Please find the Copyright Transfer Agreement + here <https://github.com/arbor-sim/arbor-materials/tree/master/copyright-transfer-agreement>`__. + +5. A PR on Github is automatically tested by our CI bot called Travis. + You can also run these tests yourself by building them first + (``make tests``) and then running them (``./bin/*unit*``). +6. A member of the Arbor development team will review your contribution. + If they approve, your PR will be merged! Normally this should happen + within a few days. + +Refer to the `Github +documentation <https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request>`__ +for more explanation of the Git workflow described above. + +.. _contribpr-review: + +Reviewing a PR +-------------- + +Each pull request is reviewed according to these guidelines: + +- At least one core Arbor team member needs to mark your PR with a + positive review. Some tips to help you get a positive review: + + - You can use labels to categorize your PR. For very large PRs, it + is likely the reviewer will have many questions and comments. It + can be helpful to reach out on our Slack, Discussions or by email + beforehand if you’ve big things planned for Arbor! + - Commit logical units with clear commit messages. + - Add change summary to the PR message. If you remembered to commit + logical units, this could simply be a bulleted list of all commit + messages in the PR. If during the review process you make changes + to the features in the PR, keep the PR description updated. + - Make sure your code conforms to our `coding + guidelines <https://github.com/arbor-sim/arbor/wiki/Coding-Style-Guidelines>`__ + - If you add functionality, please update the documentation + accordingly. + - If you add functionality, add tests if applicable. This helps make + sure Arbor is stable and functionality does what it’s supposed to + do. + - If you make changes to GPU simulations, you can post a reply to + your PR with ``bors try``. This will run our GPU test-suite. + - If you add/change the public C++ API, provide Python wrappings. + - Make sure Arbor compiles and has no new warnings. + +- Travis CI must produce a favourable result on your PR. +- An Arbor team member will (squash) merge the PR with the PR change + summery as commit message. + +.. _contribpr-merge: + +Merging a PR +------------ + +- Use PR comment as commit message and verify it covers the changes in + the PR. +- ONLY squash-and-merge (Github should not allow anything else + anymore). +- The creator of a pull request should not review or merge their own + pull request. +- A reviewer can merge if their own review is favourable and other + criteria are met. +- A reviewer can poke another Arbor core team member to do the merge. diff --git a/doc/contrib/test.rst b/doc/contrib/test.rst new file mode 100644 index 0000000000000000000000000000000000000000..11107a266f647995394d275ba1ca1d2e6263f7d6 --- /dev/null +++ b/doc/contrib/test.rst @@ -0,0 +1,7 @@ +.. _contribtest: + +Tests +============ + +.. todo:: + This page is under construction. diff --git a/doc/index.rst b/doc/index.rst index 79b701138ac1a14441125083d9430a224cb4413b..746b51dfab58a4466143d7e6d6cb2e42f6ed923c 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -9,7 +9,7 @@ Welcome to the documentation for Arbor, the multi-compartment neural network sim You can find out how to :ref:`get Arbor<in_install>`; get started quickly with our :ref:`tutorials<gs_other_examples>`; or continue reading to learn more about Arbor. What is Arbor? -------------- +-------------- Arbor is a high-performance library for computational neuroscience simulations with multi-compartment, morphologically-detailed cells, from single cell models to very large networks. Arbor is written from the ground up with many-cpu and gpu architectures in mind, to @@ -27,6 +27,7 @@ Documentation organisation * :ref:`modelintro` describes the design and concepts used in Arbor. The breakdown of concepts is mirrored (as much as possible) in the :ref:`pyoverview` and :ref:`cppoverview`, so you can easily switch between languages and concepts. * :ref:`hpc-overview` details Arbor-features for distribution of computation over supercomputer nodes. * :ref:`internals-overview` describes Arbor code that is not user-facing; convenience classes, architecture abstractions, etc. +* Contributions to Arbor are very welcome! Under :ref:`contribindex` describe conventions and procedures for all kinds of contributions. Citing Arbor ------------ @@ -65,3 +66,14 @@ Arbor is an `eBrains project <https://ebrains.eu/service/arbor/>`_. cpp/index hpc/index internals/index + +.. toctree:: + :caption: Contributing: + :maxdepth: 1 + + contrib/index + contrib/pr + contrib/coding-style + contrib/doc + contrib/example + contrib/test