Skip to content

Commit

Permalink
Merge branch 'release-1.2.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
vyasr committed May 30, 2019
2 parents 1472f91 + dc0c2c2 commit 9b4090f
Show file tree
Hide file tree
Showing 16 changed files with 160 additions and 63 deletions.
13 changes: 13 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# How to contribute to the project

## Feedback

Issue reports and feature proposals are very welcome.
Please use the [GitHub issue page](https://github.com/glotzerlab/rowan/issues/) for this.

## Contributing code

Code contributions to the rowan open-source project are welcomed via pull requests on [GitHub](https://github.com/glotzerlab/rowan/).
Prior any work you should contact the developers to ensure that the planned development meshes well with the directions and standards of the project.
All contributors must agree to the Contributor Agreement ([ContributorAgreement.md](ContributorAgreement.md)) before their pull request can be merged.
All code should follow the guidelines listed in the [Development Guide](https://rowan.readthedocs.io/en/stable/development.html).
11 changes: 11 additions & 0 deletions ChangeLog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@ This project adheres to `Semantic Versioning <http://semver.org/spec/v2.0.0.html
Unreleased
----------

Added
+++++

* Official ContributorAgreement.

Fixed
+++++

* Broadcasting for nD arrays of quaternions in to\_axis\_angle is fixed.
* Providing equivalent quaternions to mapping.procrustes properly performs rotations.

v1.2.0 - 2019-02-12
-------------------

Expand Down
29 changes: 29 additions & 0 deletions ContributorAgreement.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
rowan Contributor Agreement

These terms apply to your contribution to the rowan Open Source Project ("Project") owned or managed by the Regents of the University of Michigan ("Michigan"), and set out the intellectual property rights you grant to Michigan in the contributed materials. If this contribution is on behalf of a company, the term "you" will also mean the company you identify below. If you agree to be bound by these terms, fill in the information requested below and provide your signature.

1. The term "contribution" means any source code, object code, patch, tool, sample, graphic, specification, manual, documentation, or any other material posted or submitted by you to a project.
1. With respect to any worldwide copyrights, or copyright applications and registrations, in your contribution:
* you hereby assign to Michigan joint ownership, and to the extent that such assignment is or becomes invalid, ineffective or unenforceable, you hereby grant to Michigan a perpetual, irrevocable, non-exclusive, worldwide, no-charge, royalty-free, unrestricted license to exercise all rights under those copyrights. This includes, at Michigan's option, the right to sublicense these same rights to third parties through multiple levels of sublicensees or other licensing arrangements;
* you agree that both Michigan and you can do all things in relation to your contribution as if each of us were the sole owners, and if one of us makes a derivative work of your contribution, the one who makes the derivative work (or has it made) will be the sole owner of that derivative work;
* you agree that you will not assert any moral rights in your contribution against us, our licensees or transferees;
* you agree that we may register a copyright in your contribution and exercise all ownership rights associated with it; and
* you agree that neither of us has any duty to consult with, obtain the consent of, pay or render an accounting to the other for any use or distribution of your contribution.
1. With respect to any patents you own, or that you can license without payment to any third party, you hereby grant to Michigan a perpetual, irrevocable, non-exclusive, worldwide, no-charge, royalty-free license to:
* make, have made, use, sell, offer to sell, import, and otherwise transfer your contribution in whole or in part, alone or in combination with or included in any product, work or materials arising out of the project to which your contribution was submitted; and
* at Michigan's option, to sublicense these same rights to third parties through multiple levels of sublicensees or other licensing arrangements.
1. Except as set out above, you keep all right, title, and interest in your contribution. The rights that you grant to Michigan under these terms are effective on the date you first submitted a contribution to Michigan, even if your submission took place before the date you sign these terms. Any contribution Michigan makes available under any license will also be made available under a suitable Free Software Foundation or Open Source Initiative approved license.
1. With respect to your contribution, you represent that:
* it is an original work and that you can legally grant the rights set out in these terms;
* it does not to the best of your knowledge violate any third party's copyrights, trademarks, patents, or other intellectual property rights; and
you are authorized to sign this contract on behalf of your company (if identified below).
1. The terms will be governed by the laws of the State of Michigan and applicable U.S. Federal Law. Any choice of law rules will not apply.

** By making contribution, you electronically sign and agree to the terms of the rowan Contributor Agreement.**

![by-sa.png](https://licensebuttons.net/l/by-sa/3.0/88x31.png)

Based on the Sun Contributor Agreement - version 1.5.
This document is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License
http://creativecommons.org/licenses/by-sa/3.0/

1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ include README.md
include LICENSE.txt
include Credits.rst
include ChangeLog.rst
include ContributorAgreement.md
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
[![CircleCI](https://circleci.com/gh/glotzerlab/rowan.svg?style=svg)](https://circleci.com/gh/glotzerlab/rowan)
[![Codecov](https://codecov.io/gh/glotzerlab/rowan/branch/master/graph/badge.svg)](https://codecov.io/gh/glotzerlab/rowan)
[![PyPI](https://img.shields.io/pypi/v/rowan.svg)](https://pypi.org/project/rowan/)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/44a7677f2d7341e68a8338d1513f71e9)](https://www.codacy.com/app/vramasub/rowan)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/rowan.svg)](https://github.com/glotzerlab/rowan/)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/2ff6c23cb9be4f77827428a87e0e9cfc)](https://www.codacy.com/app/vramasub/rowan?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=glotzerlab/rowan&amp;utm_campaign=Badge_Grade)
[![Zenodo](https://zenodo.org/badge/DOI/10.5281/zenodo.1323676.svg)](https://doi.org/10.5281/zenodo.1323676)
[![JOSS](http://joss.theoj.org/papers/10.21105/joss.00787/status.svg)](https://doi.org/10.21105/joss.00787)

Expand Down
4 changes: 2 additions & 2 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@

# General information about the project.
project = 'rowan'
copyright = '2018, Vyas Ramasubramani'
copyright = '2010-2019, Regents of the University of Michigan'
author = 'Vyas Ramasubramani'

# The version info for the project you're documenting, acts as replacement for
Expand All @@ -64,7 +64,7 @@
#
# The full version, including alpha/beta/rc tags.

release = '1.2.0'
release = '1.2.1'

# The short X.Y version.
version = release[:3]
Expand Down
113 changes: 71 additions & 42 deletions doc/development.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,72 @@ Development Guide
=================


Philosophy
==========
All contributions to **rowan** are welcome!
Developers are invited to contribute to the framework by pull request to the package repository on `github`_, and all users are welcome to provide contributions in the form of **user feedback** and **bug reports**.
We recommend discussing new features in form of a proposal on the issue tracker for the appropriate project prior to development.

The goal of rowan is to provide a flexible, easy-to-use, and scalable approach to dealing with rotation representations.
To ensure maximum flexibility, rowan operates entirely on NumPy arrays, which serve as the *de facto* standard for efficient multi-dimensional arrays in Python.
To be available for a wide variety of applications, rowan aims to work for arbitrarily shaped NumPy arrays, mimicking `NumPy broadcasting <https://docs.scipy.org/doc/numpy/user/basics.broadcasting.html>`_ to the extent possible.
Functions for which this broadcasting is not available should be documented as such.

Since rowan is designed to work everywhere, all hard dependencies aside from NumPy are avoided, although soft dependencies for specific functions are allowed.
To avoid any dependencies on compilers or other software, all rowan code is written in **pure Python**.
This means that while rowan is intended to provide good performance, it may not be the correct choice in cases where performance is critical.
The package was written principally for use-cases where quaternion operations are not the primary bottleneck, so it prioritizes portability, maintainability, and flexibility over optimization.
Design Philosophy and Code Guidelines
=====================================

The goal of **rowan** is to provide a flexible, easy-to-use, and scalable approach to dealing with rotation representations.
To ensure maximum flexibility, **rowan** operates entirely on NumPy arrays, which serve as the *de facto* standard for efficient multi-dimensional arrays in Python.
To be available for a wide variety of applications, **rowan** works for arbitrarily shaped NumPy arrays, mimicking `NumPy broadcasting <https://docs.scipy.org/doc/numpy/user/basics.broadcasting.html>`_ to the maximum extent possible.
**rowan** is meant to be as lightweight and easy to install as possible.
Although it is designed to provide good performance, it is written in **pure Python** and as such may not be the correct choice in cases where the performance of quaternion operations is a critical bottleneck.

PEP 20
------
In general, all code in rowan should follow the principles in `PEP 20 <https://www.python.org/dev/peps/pep-0020/>`_.
In particular, prefer simple, explicit code where possible, avoiding unnecessary convolution or complicated code that could be written more simply.
Avoid writing code that is not easy to parse up front.
All code contributed to **rowan** must adhere to the following guidelines:

Inline comments are **highly encouraged**; however, code should be written in a way that it could be understood without comments.
Comments such as "Set x to 10" are not helpful and simply clutter code.
The most useful comments in a package such as rowan are the ones that explain the underlying algorithm rather than the implementations, which should be simple.
For example, the comment "compute the spectral decomposition of A" is uninformative, since the code itself should make this obvious, *e.g*, ``np.linalg.eigh``.
On the other hand, the comment "the eigenvector corresponding to the largest eigenvalue of the A matrix is the quaternion" is instructive.
* Use the OneFlow_ model of development:
- Both new features and bug fixes should be developed in branches based on ``master``.
- Hotfixes (critical bugs that need to be released *fast*) should be developed in a branch based on the latest tagged release.
* All code must be compatible with all supported versions of Python (listed in the package ``setup.py`` file).
* Avoid external dependencies where possible, and avoid introducing **any** hard dependencies. Soft dependencies are allowed for specific functionality, but such dependencies cannot impede the installation of **rowan** or the use of any other features.
* All code should adhere to the source code conventions discussed below.
* Follow the rules for documentation discussed below.
* Create `unit tests <https://en.wikipedia.org/wiki/Unit_testing>`_ and `integration tests <https://en.wikipedia.org/wiki/Integration_testing>`_ that cover the common cases and the corner cases of the code (more information below).
* Preserve backwards-compatibility whenever possible. Make clear if something must change, and notify package maintainers that merging such changes will require a major release.
* Enable broadcasting if at all possible. Functions for which broadcasting is not available must be documented as such.
* For consistency, NumPy should **always** be imported as ``np`` in code: ``import numpy as np``.

.. _github: https://github.com/glotzerlab/rowan
.. _OneFlow: https://www.endoflineblog.com/oneflow-a-git-branching-model-and-workflow

.. tip::

During continuous integration, the code is checked automatically with `Flake8`_.
Run the following commands to set up a pre-commit hook that will ensure your code is compliant before committing:

.. code-block:: bash
flake8 --install-hook git
git config --bool flake8.strict true
.. _Flake8: http://flake8.pycqa.org/en/latest/

.. note::

Please see the individual package documentation for detailed guidelines on how to contribute to a specific package.


Source Code Conventions
=======================
-----------------------

All code in rowan should follow `PEP 8 <https://www.python.org/dev/peps/pep-0008/>`_ guidelines, which are the *de facto* standard for Python code.
In addition, follow the `Google Python Style Guide <https://google.github.io/styleguide/pyguide.html>`_, which is largely a superset of PEP 8.
Note that Google has amended their standards to match PEP 8's 4 spaces guideline, so write code accordingly.
In particular, write docstrings in the Google style.

All code should follow the principles in `PEP 20 <https://www.python.org/dev/peps/pep-0020/>`_.
In particular, always prefer simple, explicit code where possible, avoiding unnecessary convolution or complicated code that could be written more simply.
Avoid writing code in a manner that will be difficult for others to understand.


Documentation
-------------

API documentation should be written as part of the docstrings of the package.
All docstrings should be written in the Google style.

Python example:

Expand Down Expand Up @@ -69,11 +100,18 @@ Python example:
:rtype: float
"""
Documentation must be included for all files, and is then generated from the docstrings using `sphinx <http://www.sphinx-doc.org/en/stable/index.html>`_.
Documentation must be included for all functions in all files.
The `official documentation <https://rowan.readthedocs.io/>`_ is generated from the docstrings using `Sphinx <http://www.sphinx-doc.org/en/stable/index.html>`_.

In addition to API documentation, inline comments are **highly encouraged**.
Code should be written as transparently as possible, so the primary goal of documentation should be explaining the algorithms or mathematical concepts underlying the code.
Avoid comments that simply restate the nature of lines of code.
For example, the comment "compute the spectral decomposition of A" is uninformative, since the code itself should make this obvious, *e.g*, ``np.linalg.eigh``.
On the other hand, the comment "the eigenvector corresponding to the largest eigenvalue of the A matrix is the quaternion" is instructive.


Unit Tests
==========
----------

All code should include a set of unit tests which test for correct behavior.
All tests should be placed in the ``tests`` folder at the root of the project.
Expand All @@ -83,28 +121,19 @@ Tests should be written in the style of the standard Python `unittest <https://d
At all times, tests should be executable by simply running ``python -m unittest discover tests`` from the root of the project.


General Notes
=============

* For consistency, NumPy should **always** be imported as ``np`` in code: ``import numpy as np``.
* Avoid external dependencies where possible, and avoid introducing **any** hard dependencies. Dependencies other than NumPy should always be soft, enabling the rest of the package to function as-is.

Release Guide
=============

To make a new release of rowan, follow the following steps:

#. Make a new branch off of develop based on the expected new version, *e.g.*
release-2.3.1.
#. Ensure all tests are passing as expected on the new branch. Make any final
changes as desired on this branch.
#. Once the branch is completely finalized, run bumpversion with the appropriate
type (patch, minor, major) so that the version now matches the version number
in the branch name.
#. Once all tests pass on the release branch, merge the branch back into
develop.
#. Merge develop into master.
#. Generate new source and binary distributions as described in the Python guide
for `Packaging and distributing projects
<https://packaging.python.org/tutorials/distributing-packages/#packaging-your-project>`_.
#. Update the conda recipe.
#. Make any final changes as desired on this branch. Push the changes and
ensure all tests are passing as expected on the new branch.
#. Once the branch is completely finalized, run bumpversion with the
appropriate type (patch, minor, major) so that the version now matches the
version number in the branch name.
#. Merge the branch back into master, then push master and push tags. The
tagged commit will automatically trigger generation of binaries and upload
to PyPI and conda-forge.
#. Delete the release branch both locally and on the remote.
7 changes: 2 additions & 5 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ rowan
|Codecov|
|PyPI|
|Codacy|
|Versions|
|Zenodo|
|JOSS|

Expand All @@ -22,10 +21,8 @@ rowan
:target: https://codecov.io/gh/glotzerlab/rowan
.. |PyPI| image:: https://img.shields.io/pypi/v/rowan.svg
:target: https://pypi.org/project/rowan/
.. |Codacy| image:: https://api.codacy.com/project/badge/Grade/44a7677f2d7341e68a8338d1513f71e9
:target: https://www.codacy.com/app/vramasub/rowan
.. |Versions| image:: https://img.shields.io/pypi/pyversions/rowan.svg
:target: https://github.com/glotzerlab/rowan/
.. |Codacy| image:: https://api.codacy.com/project/badge/Grade/2ff6c23cb9be4f77827428a87e0e9cfc
:target: https://www.codacy.com/app/vramasub/rowan?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=glotzerlab/rowan&amp;utm_campaign=Badge_Grade
.. |Zenodo| image:: https://zenodo.org/badge/DOI/10.5281/zenodo.1323676.svg
:target: https://doi.org/10.5281/zenodo.1323676
.. |JOSS| image:: http://joss.theoj.org/papers/10.21105/joss.00787/status.svg
Expand Down
2 changes: 1 addition & 1 deletion rowan/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
vector_vector_rotation)

# Get the version
__version__ = '1.2.0'
__version__ = '1.2.1'

__all__ = ['calculus', 'geometry', 'interpolate', 'mapping', 'random',
'allclose', 'conjugate', 'divide', 'exp', 'expb', 'exp10', 'equal',
Expand Down
4 changes: 2 additions & 2 deletions rowan/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1031,8 +1031,8 @@ def to_axis_angle(q):
sines = np.sin(angles/2)
# Avoid divide by zero issues; these values will not be used
sines[sines == 0] = 1
axes = np.where(angles != 0,
q[..., 1:]/sines,
axes = np.where(angles[..., np.newaxis] != 0,
q[..., 1:]/sines[..., np.newaxis],
0)

return axes, angles
Expand Down
1 change: 1 addition & 0 deletions rowan/mapping/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,7 @@ def procrustes(X, Y, method='best', equivalent_quaternions=None):
else:
method = getattr(thismodule, 'davenport')
if equivalent_quaternions is not None:
equivalent_quaternions = np.atleast_2d(equivalent_quaternions)
qs = []
ts = []
for eq in equivalent_quaternions:
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 1.2.0
current_version = 1.2.1
commit = True
tag = True
message = Bump up to version {new_version}.
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import os

# Gets the version
version = '1.2.0'
version = '1.2.1'

# Read README for PyPI, fallback if it fails.
desc = 'Perform quaternion operations using NumPy arrays'
Expand Down
15 changes: 13 additions & 2 deletions tests/test_axis_angle.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,19 @@ def test_complex(self):
class TestToAxisAngle(unittest.TestCase):
"""Test converting to axis angle representation"""

def test_div_zero(self):
q = (1, 0, 0, 0)
axes, angles = rowan.to_axis_angle(q)
self.assertTrue(np.allclose(axes, [0, 0, 0]))
self.assertEqual(angles, 0)

def test_to_axis_angle(self):
axes, angles = rowan.to_axis_angle(
np.array((np.sqrt(2)/2, np.sqrt(2)/2, 0, 0)))
q = (np.sqrt(2)/2, np.sqrt(2)/2, 0, 0)
axes, angles = rowan.to_axis_angle(q)
self.assertTrue(np.allclose(axes, np.array([1, 0, 0])))
self.assertTrue(np.allclose(angles, np.pi/2))

q2 = np.stack((q, q), axis=0)
axes, angles = rowan.to_axis_angle(q2)
self.assertTrue(np.allclose(axes, np.array([[1, 0, 0], [1, 0, 0]])))
self.assertTrue(np.allclose(angles, [np.pi/2, np.pi/2]))

0 comments on commit 9b4090f

Please sign in to comment.