============================= Contributing to Psignifit 3.0 ============================= Psignifit 3.0 is free software. You are free to modify the software under the terms of the license that is distributed with Psignifit 3.0. We welcome developers that want to contribute to Psignifit 3.0. Software Architecture --------------------- The Psignifit 3.x code base is logically split into several components: :psi++: The C++ *engine* of Psignifit. :pypsignifit: High level Python interface, including visualisation methods. :swignifit: Python interface to ``psi++`` autogenerated using the ``swig`` tool. :cli: Pure C++ command-line interface to ``psi++`` :rpsignift: R interface to ``psi++``. :mpsignifit: MATLAB interface to ``cli``. We refer to previous versions of psignifit (2.5.6 and before) as **psignifit-classic**. The following UML inspired diagram shows the individual components of Psignifit 3.x, and how they relate: .. image:: architecture.png :alt: Software Architecture :scale: 75 % The diagram shows all components and how they are connected. The high-level interfaces ``pypsignifit``, ``mpsignifit`` all eventually access the ``psi++`` engine via an layer. Depending on the interface language, the layer may be either ``swignifit`` or ``cli``. In Linux, building the software begins with compiling the ``psi++`` headers and sources into a shared library ``libpsipp.so``. Then ``swignifit`` is compiled in two steps. First the swig tool translates the swig definition file ``swignifit_raw.i`` into the ``swignifit_raw.py`` and ``swignifit_raw.cxx``. Then, the shared library ``_swignifit_raw.so`` is compiled and linked with ``libpsipp.so``. When accessing the engine from Python, the high-level ``pypsignifit`` calls one of the Python files in swignifit ``interface_methods.py`` or ``swignifit_raw.py``, which in turn call ``_swignifit_raw.so``, which in turn calls ``libpsipp.so``. For Matlab The situation is similar, but instead of ``swignifit`` the ``cli`` handles calling the engine. Dependencies ------------ This section lists all dependencies. The version numbers are the Debian versions we used when we began development, and hence they will probably be outdated by the time you read this. Compile-Time ............ * `Make <http://www.gnu.org/software/make/>`_ (3.81-8) for building the software * `Gcc <http://gcc.gnu.org/>`_ (4:4.4.3-1)/ * `Python <python http://www.python.org/>`_ (2.5.5-6)/ * `Python/C API <http://docs.python.org/c-api/>`_ (2.5.5-2) for compiling the ``swignifit`` interface for Python * `Simplified Wrapper and Interface Generator (SWIG) <http://www.swig.org/>`_ (1.3.40-2) for generating the ``swignifit`` interface for Python Run-Time ........ * `Python <python http://www.python.org/>`_ (2.5.5-6)/ * `Numpy <http://numpy.scipy.org/>`_ (1:1.3.0-3)/ * `Scipy <http://www.scipy.org/>`_ (0.7.1-1)/ * `Matplotlib <http://matplotlib.sourceforge.net/>`_ (0.99.1.2-3) for the Python version Documentation ............. * `sphinx <http://sphinx.pocoo.org/>`_ (0.6.5-1) to generate the html documentation * `doxygen <http://www.stack.nl/~dimitri/doxygen/>`_ (1.6.3-1) to generate the C++ documentation * `epydoc <http://epydoc.sourceforge.net/>`_ (3.0.1-5) to generate the Python API documentation Testing ....... * `nosetest <http://somethingaboutorange.com/mrl/projects/nose/0.11.2/>`_ (0.11.1-1) for running some of the unit tests Build System ------------ We use a combination of `distutils <http://docs.python.org/library/distutils.html>`_ and `make <http://www.gnu.org/software/make/>`_ to build the software. There are several ``Makefiles``: :Makefile: main makefile. :src/Makefile: ``psi++`` makefile. :cli/Makefile: ``cli`` makefile. :cli/MakefileMinGW: ``cli`` makefile to compile ``mingw`` for windows. Note that main makefile contains targets to invoke the ``psi++`` and ``cli`` makefiles. The main targets are ``build``, ``install``, ``clean`` and ``test``. The main targets will invoke separate targets to build the individual components of the software. If during development you wish to build components separately, have a look at the main makefile, it should contain everything you need. There is a single ``setup.py`` file that can be used to compile and install ``pypsignifit`` including the ``swignifit`` interface. Since the source download we provide includes the already generated interface, this is the recommended method of installation for users. For more information about how to use the ``setup.py`` file, you may look at: `Installing Pyhon Modules <http://docs.python.org/install/>`_. Git-Repositories ---------------- We use `Git <http://git-scm.com/>`_ for version control. Our main repository is hosted at `Sourceforge <http://sourceforge.net/>`_ as `Psignifit <http://sourceforge.net/projects/psignifit/>`_. Clone the repository with the following command : .. code-block:: console $ git clone git://psignifit.git.sourceforge.net/gitroot/psignifit/psignifit You can also `browse the Sourceforge repository online <http://psignifit.git.sourceforge.net/git/gitweb.cgi?p=psignifit/psignifit;a=summary>`_. We also provide a alternative repository on `Github <https://github.com/>`_: `https://github.com/esc/Psignifit-3.x <https://github.com/esc/Psignifit-3.x>`_. This is a mirror of the sourceforge which is updated daily. If you prefer to use the Github workflow (fork -> clone -> pull-request) please fork from this repository. Layout ...... Every developer has his/her own branch, and we use the master branch to do integration. Hence we have the following layout in the sourceforge repository: :master: the integration branch :ingo/master: Ingo's main branch :val/master: Valentin's main branch In addition we also make heavy use of short-lived topic branches, which are deleted after being merged. All branches except ``master`` are subject to rewind/rebase. So please base you development either on ``master`` or better yet, on the latest development snapshot(see below). Commits ....... To make it easier to keep track of the development of Psignifit, we use the following marks forto identify what parts of the code base we worked on: :C++: C++ code base :swig: swig interface :py: Python code :R: R code :matlab: matlab code :build: Build system :docs: Documentation And the following marks to identify the type of change that was made :NF: new feature :BF: bug fix :RF: refactor :FO: formatting :UT: unit test Example:: [build/RF] do proper signed tags with new tag naming structure Also, If you wish to automate the process of creating such markers, to increase consistency, we suggest using the following git-hook: https://github.com/esc/commit-marker Merging ....... For easy tracking of what changes were absorbed during merge, we advise you to enable merge summary within git: .. code-block:: console $ git-config merge.summary true Execute without installation ---------------------------- Since it is tedious to install ``pypsignifit`` during development. We provide a so called in-place compilation. To compile the ``swignifit`` interface without installation simply type: .. code-block:: console $ make You can then run: .. code-block:: pycon >>> import pypsignifit as psi from the source directory. Furthermore you can use the environment variable ``PYTHONPATH`` in case you need to bring source directory into scope elsewhere in the filesystem. Maintainers Notes ----------------- This section contains notes about the release process. We also support this process with various ``Makefile`` targets. All targets for release are prefixed with ``dist-`` Since Psignift 3.x is still beta software we provide so called development snapshots as and when new features and bugfixes are available. Development Snapshots ..................... Development snapshots are made on a regular basis. They are invoked with: .. code-block:: console $ make dist-upload-archives This will create all the required zip files and windows installers, tag the git repository, and upload the files and tags to sourceforge. Tags .... Tags should mark critical points in the development history in the following way: * ``release/3.0_beta.YYYYMMDD.1`` marks the release of a development snapshot * ``doc-YYYYMMDD`` marks a modification of the documentation that has been uploaded to sourceforge. Older tags may have different versioning schemes. This scheme was established beginning of 2012. Extending --------- This section contains hints about writing code. Coding Style ............ We try to adhere to the: `Numpy Docstring Conventions <http://projects.scipy.org/numpy/wiki/CodingStyleGuidelines#docstring-standard>`_ as far as possible. Adding a new sigmoid .................... In principle every part of the library can be replaced. This is generally done by deriving from the fundamental base classes. An exception is adding a new sigmoid: Adding a new sigmoid requires two steps: 1. Write a new class that inherits from PsiSigmoid 2. If you want your new sigmoid to work with mwCore objects, you have to add a label for that, too. The mwCore class scales the second parameter such that w can be directly interpreted as the width of the region in which the sigmoid still rises significantly. What to "rise significantly" means is parameterized by the parameter alpha of the mwCore. The default alpha==0.1 indicates that w is the width of the range over which the sigmoid rises from 0.1 to 0.9. Thus, the scaling of the second parameter obviously depends on the sigmoid. The constructor for the mwCore class looks roughly like this:: mwCore::mwCore ( int sigmoid, double al ) : sigmtype(sigmoid), alpha(al), zshift(0) { switch (sigmoid) { case 1: ... break; /////////////// here //////////////// default: throw NotImplementedError(); } } At the position marked by:: /////////////// here //////////////// in the above code example, you should add a new case that defines all the scaling parameters depending on your sigmoid. zalpha scales w to the correct range, zshift is an additional shift to ensure the the sigmoid has an output value of 0.5 at an input value of 0. Adding a new source file ........................ When adding a new C++ source or header file you will have to: * add the file to the git repository * add the filename to the Makefile * add the filename to the Python setup file