Package: mindspore-quaternion
mindspore-quaternion--基于MindSpore深度学习框架的四元数数据结构四元数在自动化等领域有非常广泛的应用，其必要性在于解决了使用欧拉角旋转的过程中有可能出现的欧拉角死锁问题。
关于更多的四元数的原理和计算方法，可以阅读本readme末尾的参考博客。安装与更新本软件支持pip一键安装与更新（这里推荐使用pypi原始的资源，国内的一些镜像源同步的并不是很及时）：$python3-mpipinstallmindspore-quaternion--upgrade-ihttps://pypi.Python.org/simple/也可以使用源码进行安装：$gitclonehttps://gitee.com/dechin/mindspore-quaternion.git
$cdmindspore-quaternion
$python3setup.pyinstall定义四元数详细的代码可以参考该链接下的内容，这里我们只作为简单介绍。首先我们需要import一些必要的软件包：fromquaternionimportQuaternionimportnumpyasnpimportmindsporeasmsfrommindsporeimportTensor接下来我们可以看一下各个不同shape的四元数定义。首先是定义一个常数的四元数，其实也就是[s, 0, 0, 0]这样的一个四元数：element=Tensor([0.],ms.float32)element_quaternion=Quaternion(element)print('The type of element is:{}'.format(type(element_quaternion)))print('The value of element is:{}'.format(element_quaternion.to_tensor()))上述代码的执行结果为：Thetypeofelementis:<class'quaternion.Quaternion'>
Thevalueofelementis:[[0.0.0.0.]]还可以定义三维矢量所对应的四元数，是如同[0, vx, vy, vz]这样的形式：vector=Tensor(np.arange(3),ms.float32)vector_quaternion=Quaternion(vector)print('The type of vector is:{}'.format(type(vector_quaternion)))print('The value of vector is:{}'.format(vector_quaternion.to_tensor()))上述代码的执行结果为：Thetypeofvectoris:<class'quaternion.Quaternion'>
Thevalueofvectoris:[[0.0.1.2.]]当然，如果一开始我们就定义好了一个完整的四维的四元数[s, vx, vy, vz]，那么也是可以用来直接构造一个四元数对象的：quater=Tensor(np.arange(4),ms.float32)quater_quaternion=Quaternion(quater)print('The type of quater is:{}'.format(type(quater_quaternion)))print('The value of quater is:{}'.format(quater_quaternion.to_tensor()))上述代码的执行结果为：Thetypeofquateris:<class'quaternion.Quaternion'>
Thevalueofquateris:[[0.1.2.3.]]这里必须要提一个最重要的point，那就是当我们使用一个深度学习框架去实现四元数这样的数据结构的时候，我们当然更多的是考虑到GPU加速在多batch的四元数计算
下的性能优势。所以这里我们也可以去定义一个更高维度的，多batch的四元数：batch_quater=Tensor(np.arange(16).reshape((4,4)),ms.float32)batch_quater_quaternion=Quaternion(batch_quater)print('The type of batch_quater is:{}'.format(type(batch_quater_quaternion)))print('The value of batch_quater is:{}'.format(batch_quater_quaternion.to_tensor()))上述代码的执行结果为：Thetypeofbatch_quateris:<class'quaternion.Quaternion'>
Thevalueofbatch_quateris:[[0.1.2.3.][4.5.6.7.][8.9.10.11.][12.13.14.15.]]四元数运算在mindspore-quaternion中我们支持了一些四元数的基本运算，这里我们仅展示一些最常用的四元数基本运算：fromquaternionimportQuaternionimportmindsporeasmsfrommindsporeimportTensorq1=Tensor([1,2,3,4],ms.float32)q1_quaternion=Quaternion(q1)q2=Tensor([3,1,0,5],ms.float32)q2_quaternion=Quaternion(q2)print('The sum of q1 and q2 is:{}'.format(q1_quaternion+q2_quaternion))print('The product of q1 and q2 is:{}'.format(q1_quaternion*q2_quaternion))上述代码的运行结果如下：Thesumofq1andq2is:[[4.3.3.9.]]Theproductofq1andq2is:[[-19.22.3.14.]]除了普通的四元数运算之外，mindspore-quaternion还可用于计算四元数与向量的哈密顿积：vector=Tensor([1,2,3],ms.float32)hamiltonian=Tensor([0.5,0.5,0.5,0.5],ms.float32)hamiltonian_quaternion=Quaternion(hamiltonian)print('The Hamiltonian product of hamiltonian | vector > is:{}'.format(hamiltonian_quaternion|vector))上述代码的运行结果如下：TheHamiltonianproductofhamiltonian|vector>is:[[3.1.2.]]同时我们也可以使用逆变换：vector_transform=hamiltonian_quaternion.conjugate()|(hamiltonian_quaternion|vector)print('The Hamiltonian product of hamiltonian^(-1) | hamiltonian | vector > is:{}'.format(vector_transform))得到的结果如下所示：TheHamiltonianproductofhamiltonian^(-1)|hamiltonian|vector>is:[[1.2.3.]]可用发现，我们经过一重四元数的变换和一重对应的逆变换之后，又得到了跟原来一样的向量。除此之外，我们最经常使用四元数的场景，
是对空间向量之间进行一个变换，比如我们可以获取两个向量之间的旋转四元数。首先我们需要定义一些初始向量和目标向量：src_vector=Tensor([1,0,0],ms.float32)src_vector_quaternion=Quaternion(src_vector)dst_vector1=Tensor([0,0,1],ms.float32)dst_vector1_quaternion=Quaternion(dst_vector1)dst_vector2=Tensor([np.sqrt(3)/3,np.sqrt(3)/3,np.sqrt(3)/3],ms.float32)dst_vector2_quaternion=Quaternion(dst_vector2)然后可以研究其中从初始向量到目标向量的变换四元数，再使用变换四元数作用到初始向量上：transform_quaternion=src_vector_quaternion>>dst_vector1_quaternionprint('The quaternion transform from vector to target_vector is:{}'.format(transform_quaternion))print('The transform result is:{}'.format(transform_quaternion|src_vector))transform_quaternion=src_vector_quaternion>>dst_vector2_quaternionprint('The quaternion transform from vector to target_vector is:{}'.format(transform_quaternion))print('The transform result is:{}'.format(transform_quaternion|src_vector))运行的结果如下所示：Thequaterniontransformfromvectortotarget_vectoris:[[0.707106770.-0.70710680.]]Thetransformresultis:[[0.0.0.99999994]]Thequaterniontransformfromvectortotarget_vectoris:[[0.888073860.-0.325057630.32505763]]Thetransformresultis:[[0.577350260.57735040.5773504]]以上就是一些常用的四元数操作，更多操作可以参考examples/路径下的示例。函数式运算为了更好的支持MindSpore框架中对计算图的编译，这里如果我们使用MindSpore框架去构建一个Quaternion的对象，会引发Jit-FallBack
的报错，因此需要支持一些函数式的操作——保留Tensor的数据结构，仅引入一些四元数的操作。下述代码是一些比较简单的案例：fromquaternion.functionsimportquaternion_multiply,quaternion_inverse,hamiltonian_product,quaternion_diffimportmindsporeasmsfrommindsporeimportTensorimportnumpyasnphamiltonian=Tensor([0.5,0.5,0.5,0.5],ms.float32)q1=Tensor([1,2,3,4],ms.float32)q2=Tensor([3,1,0,5],ms.float32)vector=Tensor([1,2,3],ms.float32)src_vector=Tensor([1,0,0],ms.float32)dst_vector1=Tensor([0,0,1],ms.float32)dst_vector2=Tensor([np.sqrt(3)/3,np.sqrt(3)/3,np.sqrt(3)/3],ms.float32)assertnp.allclose(quaternion_inverse(hamiltonian).asnumpy(),np.array([[0.5,-0.5,-0.5,-0.5]],np.float32))assertnp.allclose(quaternion_multiply(q1,q2).asnumpy(),np.array([[-19.,22.,3.,14.]],np.float32))assertnp.allclose(quaternion_multiply(q2,q1).asnumpy(),np.array([[-19.,-8.,15.,20.]],np.float32))assertnp.allclose(hamiltonian_product(hamiltonian,vector).asnumpy(),np.array([[0.,3.,1.,2.]],np.float32))assertnp.allclose(quaternion_diff(src_vector,dst_vector1).asnumpy(),np.array([[0.70710677,0.,-0.7071068,0.]],np.float32))assertnp.allclose(quaternion_diff(src_vector,dst_vector2).asnumpy(),np.array([[0.88807386,0.,-0.32505763,0.32505763]],np.float32))如果运行正确，上述代码可以正常执行通过，否则会报错。Numpy函数式运算为了方便本地环境中没有MindSpore的用户使用，mindspore-quaternion也提供了numpy版本的四元数运算支持，使用方法与上述
函数式运算中的内容基本一致，相关接口为：fromquaternion.np_functionsimportinverse,multiply,hamiltonian,transform并且，基于numpy版本的四元数运算，用户可以对蛋白质的pdb文件进行旋转平移变换的操作，例如：importnumpyasnpfromquaternion.rotate_pdbimportrotateif__name__=='__main__':pdb_in='test_in.pdb'pdb_out='test_out.pdb'# 新原点o1=np.array([42.882,32.025,38.245],np.float32)# 新X轴x1=np.array([38.326,24.174,48.484],np.float32)# 新XY平面上的一个点，但不能在OX方向上m1=np.array([53.187,51.701,33.301],np.float32)rotate(pdb_in,pdb_out,o1,x1,m1)这样，就可以把经过旋转和平移变换之后的坐标保存到指定的新的pdb文件中。代码贡献欢迎外部协作者提PR过来，有如下几点PR要求：先提Issue再提交PR，说清楚特性；贡献代码部分的flake8需要清空。参考博客https://www.cnblogs.com/dechinphy/p/quaternion-calc.html