Git Product home page Git Product logo

quaternion's Introduction

Test Status Documentation Status PyPI Version Conda Version MIT License DOI

Quaternions in numpy

This Python module adds a quaternion dtype to NumPy.

The code was originally based on code by Martin Ling (which he wrote with help from Mark Wiebe), but was rewritten with ideas from rational to work with newer python versions (and to fix a few bugs), and greatly expands the applications of quaternions.

See also the pure-python package quaternionic.

Quickstart

conda install -c conda-forge quaternion

or

python -m pip install --upgrade --force-reinstall numpy-quaternion

Optionally add --user after install in the second command if you're not using a python environment — though you should start.

Dependencies

The basic requirements for this code are reasonably current versions of python and numpy. In particular, python versions 3.8 through 3.11 are routinely tested. Earlier python versions, including 2.7, will work with older versions of this package; they might still work with more recent versions of this package, but even numpy no longer supports python previous to 3.8, so your mileage may vary. Also, any numpy version greater than 1.13.0 should work, but the tests are run on the most recent release at the time of the test.

However, certain advanced functions in this package (including squad, mean_rotor_in_intrinsic_metric, integrate_angular_velocity, and related functions) require scipy and can automatically use numba. Scipy is a standard python package for scientific computation, and implements interfaces to C and Fortran codes for optimization (among other things) need for finding mean and optimal rotors. Numba uses LLVM to compile python code to machine code, accelerating many numerical functions by factors of anywhere from 2 to 2000. It is possible to run all the code without numba, but these particular functions can be anywhere from 4 to 400 times slower without it.

Both scipy and numba can be installed with pip or conda. However, because conda is specifically geared toward scientific python, it is generally more robust for these more complicated packages. In fact, the main anaconda package comes with both numba and scipy. If you prefer the smaller download size of miniconda (which comes with minimal extras), you'll also have to run this command:

conda install numpy scipy numba

Installation

Assuming you use conda to manage your python installation (which is currently the preferred choice for science and engineering with python), you can install this package simply as

conda install -c conda-forge quaternion

If you prefer to use pip, you can instead do

python -m pip install --upgrade --force-reinstall numpy-quaternion

(See here for a veteran python core contributor's explanation of why you should always use python -m pip instead of just pip or pip3.) The --upgrade --force-reinstall options are not always necessary, but will ensure that pip will update numpy if it has to.

If you refuse to use conda, you might want to install inside your home directory without root privileges. (Conda does this by default anyway.) This is done by adding --user to the above command:

python -m pip install --user --upgrade --force-reinstall numpy-quaternion

Note that pip will attempt to compile the code — which requires a working C compiler.

Finally, there's also the fully manual option of just downloading the code, changing to the code directory, and running

python -m pip install --upgrade --force-reinstall .

This should work regardless of the installation method, as long as you have a compiler hanging around.

Basic usage

The full documentation can be found on Read the Docs, and most functions have docstrings that should explain the relevant points. The following are mostly for the purposes of example.

>>> import numpy as np
>>> import quaternion
>>> np.quaternion(1,0,0,0)
quaternion(1, 0, 0, 0)
>>> q1 = np.quaternion(1,2,3,4)
>>> q2 = np.quaternion(5,6,7,8)
>>> q1 * q2
quaternion(-60, 12, 30, 24)
>>> a = np.array([q1, q2])
>>> a
array([quaternion(1, 2, 3, 4), quaternion(5, 6, 7, 8)], dtype=quaternion)
>>> np.exp(a)
array([quaternion(1.69392, -0.78956, -1.18434, -1.57912),
       quaternion(138.909, -25.6861, -29.9671, -34.2481)], dtype=quaternion)

Note that this package represents a quaternion as a scalar, followed by the x component of the vector part, followed by y, followed by z. These components can be accessed directly:

>>> q1.w, q1.x, q1.y, q1.z
(1.0, 2.0, 3.0, 4.0)

However, this only works on an individual quaternion; for arrays it is better to use "vectorized" operations like as_float_array.

The following ufuncs are implemented (which means they run fast on numpy arrays):

add, subtract, multiply, divide, log, exp, power, negative, conjugate,
copysign, equal, not_equal, less, less_equal, isnan, isinf, isfinite, absolute

Quaternion components are stored as double-precision floating point numbers — floats, in python language, or float64 in more precise numpy language. Numpy arrays with dtype=quaternion can be accessed as arrays of doubles without any (slow, memory-consuming) copying of data; rather, a view of the exact same memory space can be created within a microsecond, regardless of the shape or size of the quaternion array.

Comparison operations follow the same lexicographic ordering as tuples.

The unary tests isnan and isinf return true if they would return true for any individual component; isfinite returns true if it would return true for all components.

Real types may be cast to quaternions, giving quaternions with zero for all three imaginary components. Complex types may also be cast to quaternions, with their single imaginary component becoming the first imaginary component of the quaternion. Quaternions may not be cast to real or complex types.

Several array-conversion functions are also included. For example, to convert an Nx4 array of floats to an N-dimensional array of quaternions, use as_quat_array:

>>> import numpy as np
>>> import quaternion
>>> a = np.random.rand(7, 4)
>>> a
array([[ 0.93138726,  0.46972279,  0.18706385,  0.86605021],
       [ 0.70633523,  0.69982741,  0.93303559,  0.61440879],
       [ 0.79334456,  0.65912598,  0.0711557 ,  0.46622885],
       [ 0.88185987,  0.9391296 ,  0.73670503,  0.27115149],
       [ 0.49176628,  0.56688076,  0.13216632,  0.33309146],
       [ 0.11951624,  0.86804078,  0.77968826,  0.37229404],
       [ 0.33187593,  0.53391165,  0.8577846 ,  0.18336855]])
>>> qs = quaternion.as_quat_array(a)
>>> qs
array([ quaternion(0.931387262880247, 0.469722787598354, 0.187063852060487, 0.866050210100621),
       quaternion(0.706335233363319, 0.69982740767353, 0.933035590130247, 0.614408786768725),
       quaternion(0.793344561317281, 0.659125976566815, 0.0711557025000925, 0.466228847713644),
       quaternion(0.881859869074069, 0.939129602918467, 0.736705031709562, 0.271151494174001),
       quaternion(0.491766284854505, 0.566880763189927, 0.132166320200012, 0.333091463422536),
       quaternion(0.119516238634238, 0.86804077992676, 0.779688263524229, 0.372294043850009),
       quaternion(0.331875925159073, 0.533911652483908, 0.857784598617977, 0.183368547490701)], dtype=quaternion)

[Note that quaternions are printed with full precision, unlike floats, which is why you see extra digits above. But the actual data is identical in the two cases.] To convert an N-dimensional array of quaternions to an Nx4 array of floats, use as_float_array:

>>> b = quaternion.as_float_array(qs)
>>> b
array([[ 0.93138726,  0.46972279,  0.18706385,  0.86605021],
       [ 0.70633523,  0.69982741,  0.93303559,  0.61440879],
       [ 0.79334456,  0.65912598,  0.0711557 ,  0.46622885],
       [ 0.88185987,  0.9391296 ,  0.73670503,  0.27115149],
       [ 0.49176628,  0.56688076,  0.13216632,  0.33309146],
       [ 0.11951624,  0.86804078,  0.77968826,  0.37229404],
       [ 0.33187593,  0.53391165,  0.8577846 ,  0.18336855]])

It is also possible to convert a quaternion to or from a 3x3 array of floats representing a rotation matrix, or an array of N quaternions to or from an Nx3x3 array of floats representing N rotation matrices, using as_rotation_matrix and from_rotation_matrix. Similar conversions are possible for rotation vectors using as_rotation_vector and from_rotation_vector, and for spherical coordinates using as_spherical_coords and from_spherical_coords. Finally, it is possible to derive the Euler angles from a quaternion using as_euler_angles, or create a quaternion from Euler angles using from_euler_angles — though be aware that Euler angles are basically the worst things ever.1 Before you complain about those functions using something other than your favorite conventions, please read this page.

Bug reports and feature requests

Bug reports and feature requests are entirely welcome (with very few exceptions). The best way to do this is to open an issue on this code's github page. For bug reports, please try to include a minimal working example demonstrating the problem.

Pull requests are also entirely welcome, of course, if you have an idea where the code is going wrong, or have an idea for a new feature that you know how to implement.

This code is routinely tested on recent versions of both python (3.8 though 3.11) and numpy (>=1.13). But the test coverage is not necessarily as complete as it could be, so bugs may certainly be present, especially in the higher-level functions like mean_rotor_....

Acknowledgments

This code is, of course, hosted on github. Because it is an open-source project, the hosting is free, and all the wonderful features of github are available, including free wiki space and web page hosting, pull requests, a nice interface to the git logs, etc. Github user Hannes Ovrén (hovren) pointed out some errors in a previous version of this code and suggested some nice utility functions for rotation matrices, etc. Github user Stijn van Drongelen (rhymoid) contributed some code that makes compilation work with MSVC++. Github user Jon Long (longjon) has provided some elegant contributions to substantially improve several tricky parts of this code. Rebecca Turner (9999years) and Leo Stein (duetosymmetry) did all the work in getting the documentation onto Read the Docs.

Every change in this code is automatically tested on Github Actions. The code is downloaded and installed fresh each time, and then tested, on each of the different supported versions of python, on each of the supported platforms. This ensures that no change I make to the code breaks either installation or any of the features that I have written tests for. Github Actions also automatically builds the pip versions of the code hosted on pypi. Conda-forge also uses Github Actions to build the conda/mamba version hosted on anaconda.org. These are all free services for open-source projects like this one.

The work of creating this code was supported in part by the Sherman Fairchild Foundation and by NSF Grants No. PHY-1306125 and AST-1333129.



1 Euler angles are awful

Euler angles are pretty much the worst things ever and it makes me feel bad even supporting them. Quaternions are faster, more accurate, basically free of singularities, more intuitive, and generally easier to understand. You can work entirely without Euler angles (I certainly do). You absolutely never need them. But if you really can't give them up, they are mildly supported.

quaternion's People

Contributors

10220 avatar bcbnz avatar belm0 avatar duetosymmetry avatar eelregit avatar eric-wieser avatar eufrizz avatar hunter314 avatar johnzl-777 avatar longjon avatar martinling avatar mcflan avatar mirca avatar moble avatar mwiebe avatar odidev avatar stiiin avatar unnonouno avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

quaternion's Issues

Strange code, may be simplifiable

From @Rosuav on October 20, 2014 23:57

init.py has this:

if np.__dict__.get('quaternion') is not None:
    raise RuntimeError('The NumPy package already has a quaternion type')

This will raise an error if there's a np.quaternion, but only if it isn't None. If this is really what you mean, I would be looking for a comment; otherwise, you can simplify this down to the more direct check:

if 'quaternion' in np.__dict__:
    raise RuntimeError('The NumPy package already has a quaternion type')

Effectively, that means "if evaluating np.quaternion won't raise AttributeError".

Copied from original issue: moble/numpy_quaternion#6

Finish writing tests

From @moble on October 22, 2014 6:2

arrfuncs, ufuncs, and casts all still need to be tested

Copied from original issue: moble/numpy_quaternion#10

Quaternion arrays sometimes think they are object arrays

From @moble on October 22, 2014 4:39

Another not-quite-reproducible bug is that when I try to take a np.float view of an array with dtype=np.quaternion, it sometimes thinks that it has dtype=object, even immediately after I've specifically asserted that the array has dtype=np.quaternion. More specifically, I get the error

TypeError: Cannot change data-type for object array.

This only happens occasionally. I don't really see any pattern to it, but it seems to happen more often when I've just compiled the module with new stuff. But then I can run my tests in a loop hundreds of times and not get a single error.

Copied from original issue: moble/numpy_quaternion#8

Spherical Functions examples

The two examples on the Spherical Functions documentation page incorrectly place the quaternion module inside the np namespace:

>>> import numpy as np, quaternion
>>> vartheta, varphi = 0.1, 0.2
>>> R_tp = np.quaternion.from_spherical_coords(vartheta, varphi)
>>> import numpy as np, quaternion
>>> alpha, beta, gamma = 0.1, 0.2, 0.3
>>> R_euler = np.quaternion.from_euler_angles(alpha, beta, gamma)

The last line of these code snippets should reference quaternion.from_*, rather than np.quaternion.from_*

Allow std=c90 compilation

From @moble on October 18, 2014 4:19

When I use multiple macros for things like PyQuaternion_AsQuaternion, that ends up defining the various quaternion objects among the corresponding code. Travis fails on this, because he uses -std=c90 for py3k for some reason...

Copied from original issue: moble/numpy_quaternion#4

Documentation

How do I rotate a vector, let's say (0, 0, 1), using the quaternion? I couldn't find the function in the documentations (there is a lots of quaternion manipulation, but is there a transform/apply function)?

np.quaternion constructor sometimes returns a tuple

From @moble on October 21, 2014 19:29

This is not at all reproducible, but in some cases, if I do something like

import numpy as np, quaternion
q = np.quaternion(1,2,3,4)
print(type(q))

I get tuple. There doesn't seem to be any rhyme or reason. For example, I could run the tests just fine from my console (meaning that the constructor returned a quaternion object), but my ipython notebook would give me tuples at the same time. Or Travis could run on all 5 versions of python (2.6, 2.7, 3.2, 3.3, 3.4), but only get an error in one.

Copied from original issue: moble/numpy_quaternion#7

Error when using numpy.load

I want to save some quaternion data to a file and load it again later. The saving part works fine:

import numpy as np
import quaternion

q = np.quaternion(1, 2, 3, 4)
qarray = np.array([q, q])

filename = 'test.npy'
np.save(filename, qarray)

However, when I try to load the file, I get an error:

np.load(filename)

Here is the full error message:

Traceback (most recent call last):
  File "/Users/stetnermit/miniconda3/envs/neurophysvideo/lib/python3.5/site-packages/numpy/lib/format.py", line 510, in _read_array_header
    dtype = numpy.dtype(d['descr'])
TypeError: data type "<q32" not understood

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "test.py", line 9, in <module>
    np.load(filename)
  File "/Users/stetnermit/miniconda3/envs/neurophysvideo/lib/python3.5/site-packages/numpy/lib/npyio.py", line 406, in load
    pickle_kwargs=pickle_kwargs)
  File "/Users/stetnermit/miniconda3/envs/neurophysvideo/lib/python3.5/site-packages/numpy/lib/format.py", line 622, in read_array
    shape, fortran_order, dtype = _read_array_header(fp, version)
  File "/Users/stetnermit/miniconda3/envs/neurophysvideo/lib/python3.5/site-packages/numpy/lib/format.py", line 513, in _read_array_header
    raise ValueError(msg % (d['descr'],))
ValueError: descr is not a valid dtype descriptor: '<q32'

How can I load my saved data?

Installation issue with python 2.7

I currently have anaconda with python 2.7 on my PC.
I've tried to install the package using

conda install -c moble quaternion

but this leads to the following error:

UnsatisfiableError: The following specifications were found to be in conflict:

  • python 2.7*
  • quaternion -> python 3.5*
    Use "conda info " to see the dependencies for each package.

Does the package not work with python 2.7 alone?

Many thanks.

numpy and numpy-quaternion cannot be installed successfully at the same time

pip install numpy numpy-quaternion always fails. So we must firstly install numpy separately, then install numpy-quaternion.

The setup.py#L25 of numpy-quaternion requires numpy, but at installation time numpy is not available.

$ mkvirtualenv py2 --python=`which python2`

$ pip -V
pip 9.0.1 from /home/wonder/PyEnvs/py2/local/lib/python2.7/site-packages (python 2.7)

$ pip install --no-cache-dir numpy numpy-quaternion
Collecting numpy
  Downloading https://mirrors.aliyun.com/pypi/packages/dd/b5/47bd2174dbb14e5fa2dd6ad28fd1d54d38e84d29c1b131a00354ddb0cae0/numpy-1.13.0-cp27-cp27mu-manylinux1_x86_64.whl (16.6MB)
    100% |████████████████████████████████| 16.6MB 1.1MB/s 
Collecting numpy-quaternion
  Downloading https://mirrors.aliyun.com/pypi/packages/f0/99/f38033e0a90674a7e8a1df5e98d2aa73e73cec8b11955c2ae155d1da9369/numpy-quaternion-2017.06.28.13.11.35.dev177226304.tar.gz (43kB)
    100% |████████████████████████████████| 51kB 1.7MB/s 
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-build-5TY7nL/numpy-quaternion/setup.py", line 25, in <module>
        from numpy.distutils.core import setup
    ImportError: No module named numpy.distutils.core
    
    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-5TY7nL/numpy-quaternion/

Dividing quaternions

As it is known, division on quaternions can go in two ways, for example, here's an abstract from Wikipedia:

... it is possible to divide two quaternions p and q in two different ways (when q is non-zero). That is, their quotient can be either p q−1 or q−1p. The notation p/q is ambiguous because it does not specify whether q divides on the left or the right.

These ways give different answers, which is important for calculations. So, with this package, how do I do either left or right division in particular? I could not find a hint on that, both playing with the library or within the test suite. Could you please give a little example?

Inplace multiplication crashes interpreter

Multiple inline multiplications of single quaternions crashes the interpreter.

Minimal test case:

q0 = np.quaternion(1, 0, 0, 0)
q1 = np.quaternion(0, 0, 0, 0)
for i in range(10):
    q0 *= q1

This does not happen with q0 = q0 * q1 or if q0 and q1 are quaternion arrays instead of single quaternions.

My version is 2015.11.06.dev83a0f48 installed using conda

FTBFS on Windows with MSVC++ 9

Since quaternion.h looks for _MSC_VER, I assume that MSVC++ is an intended target for this package. However, after installing "Microsoft Visual C++ Compiler for Python 2.7" and invoking

pip install git+git://github.com/moble/quaternion

the build phase fails due to various problems that may be unique to MSVC++:

  • The <math.h> functions isnan, isinf, and isfinite are apparently not available in quaternion.h.
  • The C99 compound literal syntax (e.g. (quaternion) { w, x, y, z }) is not supported by MSVC++.

Can't install via pex

I wanted to create a single executable for a script I have that is using numpy-quaternion but pex can't find the right package:

$ pex numpy numpy-quaternion
Could not satisfy all requirements for numpy-quaternion:
    numpy-quaternion

It seems a bit odd since pip can install it fine.

Memory leak when assigning a numpy array to .vec atribute?

Dear all,
I ran into some memory problems when changing the values of a quaternion object's .vec -attribute. This becomes exceedingly problematic in for loops, where memory consumptions increases steadily after every iteration step.

C.f. using memory_profiler package, v. 0.41 ( conda install -c anaconda memory_profiler )

$ mprof run quaternion_minimal_example.py 
mprof: Sampling memory every 0.1s
running as a Python program...
Filename: quaternion_minimal_example.py

Line #    Mem usage    Increment   Line Contents
================================================
    10     66.8 MiB      0.0 MiB   @profile
    11                             def main():
    12     66.8 MiB      0.0 MiB       N = int(1e6)
    13     66.8 MiB      0.0 MiB       q = np.quaternion(0, 0, 0, 0)
    14                             
    15    136.5 MiB     69.8 MiB       for n in xrange(N):
    16    136.5 MiB      0.0 MiB           q.vec = np.array([0, 0, 0])

(use mprof plot to show the memory consumption trend.)

Here's the code for quaternion_minimal_example.py

import numpy as np
import quaternion
from memory_profiler import profile


@profile
def main():
    N = int(1e5)
    q = np.quaternion(0, 0, 0, 0)

    for n in xrange(N):
        q.vec = np.array([0, 0, 0])


main()

The problem can be solved if one replaces np.array([0, 0, 0]) with np.array([0, 0, 0]).tolist(). Is there perhaps a bug in the quaternion package, or am I just doing something wrong...(?)

My best,

  • J.

Wrong quaternion norm implementation

The quaternion norm implementation actually gives the square of the quaternion norm as can be seen from the following simple code:

import numpy as np
import quaternion

qv = np.array([1,2,3,4], dtype = np.float64)
q = np.quaternion(1,2,3,4)

print(np.linalg.norm(qv), q.norm(), np.sqrt(q.norm()))

which results in:

5.47722557505 30.0 5.47722557505

as_spherical_coords(from_spherical_coords(*x)) != x

I'm having trouble converting to quaternions from spherical coordinates and back. I'm not sure if this is from a gap in my understanding or a bug in the library.

>>> quaternion.as_spherical_coords(quaternion.from_spherical_coords(*np.array([0, pi])))
array([ 0.        ,  1.57079633])

I expected the output to be array([ 0. , 3.14159265]). I suspect this is a result of using two different spherical coordinate schemes for from_... and as_..., but I wasn't able to find the implementation of as_... in your source code to compare them.

Multiplication with scalar depend on order

Order of multiplication of scalar and quaternion matters. It works fine from right:

>>> q = np.quaternion(1,2,3,4)
>>> q * 5
quaternion(5, 10, 15, 20)

But not from left:

>>> 5 * q
TypeError: Input object is not a quaternion.

Even worse is that if you do this with an array of quaternions, there is no warning, but the result seems to be more or less random.

>>> q * np.arange(5)  # OK!
array([quaternion(0, 0, 0, 0), quaternion(1, 2, 3, 4),
   quaternion(2, 4, 6, 8), quaternion(3, 6, 9, 12),
   quaternion(4, 8, 12, 16)], dtype=quaternion)

>>> np.arange(5) * q  # Woops!
array([quaternion(4, 8, 12, 16), quaternion(0, 0, 0, 0),
   quaternion(0, 0, 0, 0), quaternion(0, 0, 0, 0),
   quaternion(0, 0, 0, 0)], dtype=quaternion)

Fix import with python3

From @moble on October 18, 2014 13:50

Something bad happens with python 3.4 (and presumably any py3k version...) that stops import from working.

> python -c 'import numpy as np, quaternion'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/Users/boyle/.continuum/anaconda/envs/py3numpy/lib/python3.4/site-packages/quaternion/__init__.py", line 3, in <module>
    from .numpy_quaternion import quaternion
TypeError: __import__() argument 1 must be str, not bytes

Copied from original issue: moble/numpy_quaternion#5

using quaternion.quaternion on a numpy array

Hello,
Along my way to find a method to apply the same rotation to an array of 3D points (x,y,z coordinates), I've experimented with the constructor quaternion.quaternion(0,*one_by_3_np_array).
In order to be able to directly construct a "pure" quaternion (no real part) from my array of 3D points, I thought I could do:

# define my test XYZ array
myxyz = np.random.rand(100,3)
# make it into a 100 rows quaternion array
myxyz_quat = quaternion.quaternion(0,*myxyz) 

But found out that obviously this doesn't work because unpacking my array will result in more than the 4 floats expected by the constructor.
I can define a function to build my quaternion line by line but doubt this would be efficient.
The solution I've came up with is to use quaternion.as_quat_array:

def npXYZary_to_quaternion (npary):
    tmpary = np.zeros((npary.shape[0],4))
    tmpary[:,1:] = npary
    qnpary = quaternion.as_quat_array(tmpary)
    return qnpary

But could it be possible to have the quaternion constructor take a Nx3 (Nx4 as well) numpy array ?
Ludovic

Add new functions

From @moble on October 17, 2014 14:16

// Apply in place; explain conventions carefully; only calculate what needs calculating;
// use R^{-1} instead of R.conj(); add to `pyquaternion_methods` as `rotate`
void rotate_vector_by_rotor(quaternion v, quaternion R);

/// ufuncs
RDelta
FrameFromXY

//// through numpy / numba?
MinimalRotation
PrescribedRotation
FrameFromZ
FrameFromPrescribedRotation

UnflipRotors

FrameAngularVelocity

ApproximateMeanRotor
MeanRotor
ApproximateOptimalAlignmentRotor
ApproximateOptimalAlignment
OptimalAlignment

Copied from original issue: moble/numpy_quaternion#3

as_float_array dimensions vary for python2 vs python3

The following code snippet yields slightly different answers depending on whether it is run in python2 or python3:

>>> import quaternion as q
>>> p = q.quaternion(1, 2, 3, 4)
>>> print(q.as_float_array(p))

In python2:

[ 1.  2.  3.  4.]

In python3:

[[ 1.  2.  3.  4.]]

I imagine that the second behavior is preferable, but either way should be fine as long as it's consistent.

Change name of repo and module to "quaternions"

From @moble on November 16, 2014 16:26

I think there's some name confusion with quaternion.quaternion. Also, I keep trying to import quaternions, and I hate the name of this repo.

Copied from original issue: moble/numpy_quaternion#16

Enable pickling

From @moble on November 16, 2014 16:22

I've tried to enable pickling in a few ways: (1) adding a __reduce__ method; (2) adding __setstate__ and __getstate__ methods; (3) using copy_reg. Copying works just fine, but pickling keeps giving me the same error:

PicklingError: Can't pickle <type 'quaternion'>: it's not found as __builtin__.quaternion

My best guess is that either something in the quaternion module is preventing pickling (in particular, some jit function might cause problems) or there might be name confusion with quaternion.quaternion.

Copied from original issue: moble/numpy_quaternion#15

Test involutions

The waveforms tests actually do this a little, but it'd be nice to test more explicitly here, in case the origin of any problem comes from this module.

unexpected behavior for imaginary part

Hi,
I found some unexpected behavior with the imaginery part of the quaternion:

In [35]: a
Out[35]: quaternion(0.00277, -0.97976, -0.00186, -0.20012)

In [36]: a.real
Out[36]: 0.00277

In [37]: a.imag
Out[37]: quaternion(0, 0, 0, 0)

In [38]: np.__version__
Out[38]: '1.11.1'

In [39]: quaternion.__version__
Out[39]: '2017.01.08.dev232822920'

So I would expect to retrieve array_like [-0.97976, -0.00186, -0.20012]

Cheers,
Michael

Correct behavior of squad at endpoints

From @moble on November 2, 2014 15:15

Currently, squad treats the endpoints like all other points, by using rolled loops (so indices are cyclic). Thus, the first input point and the last two input points of a squad interpolation will be nonsense -- which means that any output that uses such points will also be nonsense.

Copied from original issue: moble/numpy_quaternion#13

Can't see the list of functions available in quaternion.py

Hi,

I am using the quaternion.py library in my Python 3, together with the Anaconda package. I can't see the list of functions that are available in the quaternion library when I call it in my Anaconda. Follow a screen shot below. I am showing that when I call the quaternion library it will open a window with all the available functions in it, but when I call np.quaternion it won't show anything. If I call it as only quaternion.() (without the np. in front) it will show me functions, but they are different than when you call np.quaternion.() My friend, however, (who uses python 2.7) can see the functions by calling np.quaternion.(), and I am attaching his screen shot as well for reference. I hope it's not confusing! I have already tried to reinstall everything and it didn't help. I installed my quaternion library by going directly into my python's folder and commanding 'python setup.py install'. I can use all the functions, just can't see what's available on my screen. I hope you can help me! Thank you once again!

The screen shot below shows my functions when I call quaternion.()
capture1

The screen shot below shows that I cannot see the functions when I call np.quaternion.()
capture

Finally, the screen shot below shows my friend's screen shot, where he calls np.quaternion.() and are able to see all the functions:
capture2

Rosana

install errors

install from conda fails,

> conda install -c moble quaternion
Fetching package metadata ....Warning: you may need to login to anaconda.org again with 'anaconda login' to access private packages(https://co
nda.anaconda.org/moble/noarch/, 401 Client Error: UNAUTHORIZED for url: https://conda.anaconda.org/t/ar-74969af3-431a-426e-8ecb-75efaa76452b/m
oble/noarch/repodata.json)Warning: you may need to login to anaconda.org again with 'anaconda login' to access private packages(https://conda.
anaconda.org/moble/linux-64/,

Kernel never returns from `np.prod()` on quaternions

Performing the prod NumPy operation over an array of quaternions results in kernel becoming unresponsive and producing a 100% CPU load. Only restarting the kernel would bring the notebook back to life.

Example code:

np.prod([np.quaternion(1, 0, 0, 0), np.quaternion(0, 0, 0, 1)])

Add rotation conversion functions

Since quaternions are commonly used for representing rotations, I think having functions that convert a (unit) quaternion to a rotation matrix would be very useful.

The following Python snippet solves the task:

def quat2rot(q):
    "Convert unit quaternion to rotation matrix."
    assert np.isclose(q.norm(), 1.0)
    R = np.array([
    [1 - 2*q.y**2 - 2*q.z**2,   2*q.x*q.y - 2*q.z*q.w,      2*q.x*q.z + 2*q.y*q.w],
    [2*q.x*q.y + 2*q.z*q.w,     1 - 2*q.x**2 - 2*q.z**2,    2*q.y*q.z - 2*q.x*q.w],
    [2*q.x*q.z - 2*q.y*q.w,     2*q.y*q.z + 2*q.x*q.w,      1 - 2*q.x**2 - 2*q.y**2]
    ])

    return R

I could write the patch myself, but I am unsure where it should go, or if there are any constraints that I am unaware of (numba support, etc). The assert statement to check for unit norm should probably be changed as well, or at least not throw an AssertionError.

It would also be useful to add the inverse function (rot2quat) and maybe other rotation representations like axis-angle or Euler angles.

half integer ell

So I am using this code to generate Wigner rotation matrices quickly -- but when I rotate a normalized ket with the matrix derived in this way it produces a new ket with the wrong normalization IF the ket is a half integer spin ket, e.g. a qubit or spin 3/2 particle. (everything is fine when the state has integer spin, ell = 1,2,3,..)

am i missing the code for the half-integer case?

Make `quaternion.c` conform with pure numpy C-API style

From @moble on October 17, 2014 4:48

As demonstrated in, e.g., rational, it's considered good practice to define the member functions starting with

static NPY_INLINE 

to encourage the compiler to make various optimizations. This would only be applicable if the contents of that file are moved inside numpy_quaternion.c. Alternatively, I could use some macro for both, defining it to be inline if it's undefined at the top of quaternion.c, but defining it to be static NPY_INLINE just before including into numpy_quaternion.c.

Copied from original issue: moble/numpy_quaternion#2

changing the element of a quaternion

Say I have:
myq = np.quaternion(ww,xx,yy,zz)
I can do

myq_x=myq.x # a float
myq_y=myq.y # a float

but not
myq.x = myq.y # AttributeError: readonly attribute
I would find it useful to be able to have the quaternion attributes as write also, for example to easily change the axis of rotation. What is the reason to set them as readonly? And then how to, for example, swap 2 elements of a quaternion (such as swap xx with yy as above)?

Implement isclose() for quaternion

I was wondering if it is possible to implement np.isclose() or np.allclose() for quaternion which would be useful (especially for my project LOL).

round is not implemented

I was trying to use quaternion and rounding off to nearest decimals.
However it says, Not implemented (virtual attribute).

Fix the QUATERNION_nonzero function, and surrounds

From @moble on October 22, 2014 6:1

QUATERNION_nonzero is the most egregious example remaining, but the other functions don't make a whole lot of sense to me either. They should all be fixed up.

Copied from original issue: moble/numpy_quaternion#9

Inconsistency between `as_quat_array` and `as_float_array` for single quaternions

quaternion.as_quat_array returns a single scalar quaternion when a one-dimensional array is given, while quaternion.as_float_array returns a two-dimensional array when a single quaternion is given.

import numpy as np
import quaternion

print (quaternion.as_quat_array([1., 2., 3., 4.]))
print (quaternion.as_float_array(np.quaternion(1., 2., 3., 4.)))

Output:

quaternion(1, 2, 3, 4)
[[ 1.  2.  3.  4.]]

I don't know if that's on purpose but it seems to me that quaternion.as_float_array(quaternion.as_quat_array(array)) should always equal array.

Version: numpy-quaternion-0.0.0.dev2017.03.30.16.33.31

Quaternion division

Does anyone know how to use the division function? I am trying to use it as:
q1 = something
q2 = something else
div = quaternion.division(q2,q1)

Is that correct? I can't find any examples for this particular library. Thank you!

quaternion.py library function won't work

I am creating a function that does some math, creates an array, and ultimately transforms that array into a a quaternion. I was doing this using brute force, but I found out the library supports that transformation by using the command:

a = some 1x4 array
q = quaternion.as_quat_array(a)

When I use that command on my workspace, it works fine. If I try to code that up in my function, I get the following error:

AttributeError: 'list' object has no attribute 'dtype'

Follow a screen shot:
capture

I am not versed in Python and not very knowledgeable in command line. I only know some basics. I appreciate your help!

Enable conjugation

From @moble on October 16, 2014 2:6

If I have a np.quaternion object q, then q.conjugate() and q.conj() do nothing. In fact, I can't get the conjugate function to work in any case at all...

Copied from original issue: moble/numpy_quaternion#1

Add docs in various places

From @moble on October 22, 2014 12:15

  • PyQuaternion_Type->tp_doc
  • Py_InitModule goes to Py_InitModule3, with an extra char* doc argument

Copied from original issue: moble/numpy_quaternion#11

import quaternion as, e.g., quat?

Hi, I'm currently exploring your quaternion module. This is more of a curiosity question that I have rather than an issue, likely arising from to my limited knowledge in python rather than a limitation in your module.
When I try:

import numpy as np
import quaternion as quat
myq = np.quat(0,1,0,0)

I get
AttributeError: module 'numpy' has no attribute 'quat'
but

import numpy as np
import quaternion as quaternion
myq = np.quaternion(0,1,0,0)

is fine.
Why can't I import quaternion as whatever_name_I_chose?

Vectorized slerp

Is there anyway to run a vectorized form of quaternion.slerp? I have not been able to get this behavior even using numpy.frompyfunc or numpy.vectorize (which, on NumPy's own words, are more of "convenience functions" than actual performance boosters, but anyway), since I keep getting this ValueError: No cast function available..
Edit: Just in case it's not clear, I'm talking about the possibility of having, say, 100 start quaternions, 100 end quaternions and 100 alpha values and make the 100 interpolations in one step (or, also, using broadcasting rules, like just two quaternion and 100 alpha values, etc.)

Versioning fails when 'CI' is 'true'

I have written a package and would like to use quaternion as a dependency. On my local machine I installed it fine using pip and got everything working the way I wanted to and the tests passing. Then I pushed the new code to GitHub and started a TravisCI build, which failed with errors something like this:

Collecting numpy-quaternion (from suspect==0.3.0a0)
  Downloading numpy-quaternion-2017.03.16.21.51.57.dev242408302.tar.gz (42kB)
    100% |████████████████████████████████| 51kB 11.6MB/s 
    Complete output from command python setup.py egg_info:
    fatal: Not a git repository (or any of the parent directories): .git
    /tmp/pip-build-n4nfx3tp/numpy-quaternion/auto_version/__init__.py:87: UserWarning:
    The 'calculate_version' function failed to get the git version.Maybe your version of python (<2.7?) is too old.  Here's the exception:
    Command 'git show -s --format="%ci %h" HEAD' returned non-zero exit status 128
      warn(warning)
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-build-n4nfx3tp/numpy-quaternion/setup.py", line 35, in <module>
        version=calculate_version(validate, error_on_invalid),
      File "/tmp/pip-build-n4nfx3tp/numpy-quaternion/auto_version/__init__.py", line 91, in calculate_version
        raise e
      File "/tmp/pip-build-n4nfx3tp/numpy-quaternion/auto_version/__init__.py", line 57, in calculate_version
        git_revision = subprocess.check_output("""git show -s --format="%ci %h" HEAD""", shell=use_shell).decode('ascii').rstrip()
      File "/opt/python/3.5.2/lib/python3.5/subprocess.py", line 626, in check_output
        **kwargs).stdout
      File "/opt/python/3.5.2/lib/python3.5/subprocess.py", line 708, in run
        output=stdout, stderr=stderr)
    subprocess.CalledProcessError: Command 'git show -s --format="%ci %h" HEAD' returned non-zero exit status 128
    Raising exception because environment variable 'CI' is "true"
    
    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-n4nfx3tp/numpy-quaternion/
The command "pip install ." failed and exited with 1 during .

I am not sure but I think this might be because the auto_version assumes that if it is being installed on CI then it is being tested itself and so must be a git repo, whereas it is actually only a dependency without a repo of its own.

Minor suggestion: allowing the use of integer (or why not?)

If I pass an array of int to quaternion.as_quat_array it will complain.

import numpy as np
import quaternion
a = np.arange(12).reshape(3,4)
sin_a = np.sin(a) # no problem
quat_a = quaternion.as_quat_array(a) # AssertionError: assert a.dtype == np.dtype(np.float)

It is easy to fix by converting int to float or ensuring that floats are input, but there maybe some quaternion usage cases where the input array is int and should be kept as is, without the need for conversion or copy. Many maths functions in python and numpy accept integers as inputs, and though as_quat_array isn't a math function, is there a reason for requiring exclusively floats?
How about accepting int as well?

Macro for custom ufuncs

From @moble on November 2, 2014 15:11

The current macro mechanism adds ufuncs that are already part of numpy. I've added a clunky ufunc to quaternion that does the squad loop, though this could easily be trimmed down, and converted into a macro for use with other things like inverse, angle, normalized, sqrt, norm, slerp, and the metrics.

Copied from original issue: moble/numpy_quaternion#12

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.