# Path: imusim/maths/transforms.py
# class AffineTransform(object):
#     """
#     Affine transform composed of a linear transform matrix and translation.
#     """
#     def __init__(self, transform=None, rz=0, ry=0, rx=0, scale=1,
#             translation=vector(0,0,0)):
#         """
#         Construct an affine transform.
# 
#         A generic transformation matrix can be supplied, or a transform
#         composed of rotation and scaling can be built.
# 
#         Generating rotations using supplied Euler angles is performed from the
#         perspective of a fixed camera viewing a rotating object, i.e. points
#         rotate within a fixed reference frame. Rotations are applied in
#         aerospace (ZYX) order.
# 
#         @param transform: 3x3 linear transformation matrix.
#         @param rx: X rotation angle in radians.
#         @param ry: Y rotation angle in radians.
#         @param rz: Z rotation angle in radians.
#         @param scale: Scaling factor
#         @param translation: 3x1 translation vector.
#         """
#         if transform is not None:
#             self._transform = transform
#         else:
#             self._transform = scale * matrixFromEuler((rz,ry,rx),'zyx',False)
# 
#         self._inverseTransform = np.linalg.inv(self._transform)
#         self._translation = translation
# 
#     def apply(self,v):
#         """
#         Apply transform to an array of column vectors.
#         """
#         return np.tensordot(self._transform, v, axes=([1],[0])) \
#                 + self._translation
# 
#     def reverse(self,v):
#         """
#         Apply the inverse of this transform to an array of column vectors.
#         """
#         return np.tensordot(self._inverseTransform,
#                 v-self._translation,axes=([1],[0]))


from imusim.environment.magnetic_fields import EarthMagneticField
from imusim.environment.magnetic_fields import DistortedMagneticField
from imusim.environment.magnetic_fields import SolenoidMagneticField
from numpy.testing import assert_almost_equal
from imusim.maths.vectors import vector
from imusim.maths.transforms import AffineTransform
from numpy import random
        ]

def checkBaseField(field, nominal):
    assert_almost_equal(field.nominalValue, nominal)
    assert_almost_equal(field(vector(0,0,0), 0), nominal)

def testEarthField():
    for args, nominal in TEST_PARAMS:
        yield checkBaseField, EarthMagneticField(*args), nominal

def checkZeroHeadingVariation(field, position):
    assert_almost_equal(field.headingVariation(position, 0), 0)

def testUndistortedField():
    random.seed(0)
    for args, nominal in TEST_PARAMS:
        base = EarthMagneticField(*args)
        field = DistortedMagneticField(base)
        yield checkBaseField, field, nominal
        for i in xrange(10):
            yield checkZeroHeadingVariation, field, random.uniform(size=(3,1),
                    low=-10, high=10)

def checkNonZeroHeadingVariation(field, position):
    assert abs(field.headingVariation(position, 0)) > 0.01

def testDistortedField():
    random.seed(0)
    field = DistortedMagneticField(EarthMagneticField())
    field.addDistortion(SolenoidMagneticField(200,20,0.05,0.2,

# Path: imusim/maths/transforms.py
# class AffineTransform(object):
#     """
#     Affine transform composed of a linear transform matrix and translation.
#     """
#     def __init__(self, transform=None, rz=0, ry=0, rx=0, scale=1,
#             translation=vector(0,0,0)):
#         """
#         Construct an affine transform.
# 
#         A generic transformation matrix can be supplied, or a transform
#         composed of rotation and scaling can be built.
# 
#         Generating rotations using supplied Euler angles is performed from the
#         perspective of a fixed camera viewing a rotating object, i.e. points
#         rotate within a fixed reference frame. Rotations are applied in
#         aerospace (ZYX) order.
# 
#         @param transform: 3x3 linear transformation matrix.
#         @param rx: X rotation angle in radians.
#         @param ry: Y rotation angle in radians.
#         @param rz: Z rotation angle in radians.
#         @param scale: Scaling factor
#         @param translation: 3x1 translation vector.
#         """
#         if transform is not None:
#             self._transform = transform
#         else:
#             self._transform = scale * matrixFromEuler((rz,ry,rx),'zyx',False)
# 
#         self._inverseTransform = np.linalg.inv(self._transform)
#         self._translation = translation
# 
#     def apply(self,v):
#         """
#         Apply transform to an array of column vectors.
#         """
#         return np.tensordot(self._transform, v, axes=([1],[0])) \
#                 + self._translation
# 
#     def reverse(self,v):
#         """
#         Apply the inverse of this transform to an array of column vectors.
#         """
#         return np.tensordot(self._inverseTransform,
#                 v-self._translation,axes=([1],[0]))


# Path: imusim/tests/environment/magnetic_test.py
from imusim.environment.magnetic_fields import EarthMagneticField
from imusim.environment.magnetic_fields import DistortedMagneticField
from imusim.environment.magnetic_fields import SolenoidMagneticField
from numpy.testing import assert_almost_equal
from imusim.maths.vectors import vector
from imusim.maths.transforms import AffineTransform
from numpy import random

        ]

def checkBaseField(field, nominal):
    assert_almost_equal(field.nominalValue, nominal)
    assert_almost_equal(field(vector(0,0,0), 0), nominal)

def testEarthField():
    for args, nominal in TEST_PARAMS:
        yield checkBaseField, EarthMagneticField(*args), nominal

def checkZeroHeadingVariation(field, position):
    assert_almost_equal(field.headingVariation(position, 0), 0)

def testUndistortedField():
    random.seed(0)
    for args, nominal in TEST_PARAMS:
        base = EarthMagneticField(*args)
        field = DistortedMagneticField(base)
        yield checkBaseField, field, nominal
        for i in xrange(10):
            yield checkZeroHeadingVariation, field, random.uniform(size=(3,1),
                    low=-10, high=10)

def checkNonZeroHeadingVariation(field, position):
    assert abs(field.headingVariation(position, 0)) > 0.01

def testDistortedField():
    random.seed(0)
    field = DistortedMagneticField(EarthMagneticField())
    field.addDistortion(SolenoidMagneticField(200,20,0.05,0.2,

        AffineTransform()))