Development

Contributions to ramannoodle - in the form of bug reports, feature suggestions, pull requests, etc. - are always welcome! We are particularly interested in adding new interfaces to first-principles codes as well as developing new polarizability models. This document provides a few development guidelines. Please reach out on Github with any questions or if you want to collaborate :)

Workflow

Ramannoodle is hosted on Github:

https://github.com/wolearyc/ramannoodle

The project uses pre-commit with a range of hooks that help ensure high code quality and consistency. You are strongly encouraged to use it frequently, as all pull requests need to pass CI pre-commit before merge! Pre-commit can be installed with pip

$ pip install pre-commit

and can be run from the repository’s root directory with

$ pre-commit run --all

Ramannoodle includes a test suite that uses the pytest framework. Pull requests must pass all CI tests in order to be merged. New tests should be developed for any new functionality.

Ramannoodle’s documentation is built with Sphinx. The documentation can be built by running

$ make html

from within the docs directory. The resulting html is available in docs/build/html. After adding new modules, Sphinx source files must be generated with sphinx-apidoc. This can be done by running

$ bash gen_api_sources.sh

from within the docs directory.

Test coverage reports and badges can be generated by running

$ bash gen_test_coverage_badges.sh

from within the docs directory. The coverage report html can be found in reports/coverage

Guidelines

In no particular order, here are some development guidelines:

  • Since mypy is used, type hints are mandatory.

  • Whenever possible, use the EAFP (as opposed to LBYL) principle when raising exceptions.

  • Use numpy-style docstrings.

  • All public-facing functions should raise descriptive TypeError and ValueError exceptions when invalid arguments are provided. These sorts of exceptions should not be documented in the docstring.

  • All array arguments containing floats should be numpy arrays. This should be enforced, when appropriate, through exceptions. Although this is admittedly rather antithetical to Python’s duck typing philosophy, it helps avoid problems that are difficult to debug.

  • Docstring descriptions for array arguments should provide a dimension and shape. Uppercase letters can be used for cases where shape is variable. For example, “4D array with shape (M,N,3) where M is … and N is …”.

  • For all coordinates, vectors, displacements, etc, ramannoodle works in fractional coordinates. Variables and arguments are occasionally in cartesian coordinates; these are distinguished by the “cart_” prefix.

  • Ramannoodle uses a mix of object oriented programming and a more “imperative” style (by which me mean using functions, in a similar manner to C).

  • With IO functions, ramannoodle attempts to strike a balance between simplicity and flexibility. ramannoodle.io.generic provides file readers and writers for a variety of file formats. These generic functions are rather inflexible but are necessary for certain functionality. In most cases, users are strongly encouraged to use modules contained in the code-specific IO packages – for example ramannoodle.io.vasp.poscar or ramannoodle.io.vasp.outcar – to read the write files.