# Path: openmodes/helpers.py
# class Identified(object):
#     """An object which can be uniquely identified by an id number. It is
#     assumed that any object which subclasses Identified is immutable, so that
#     its id can be used for caching complex results which depend on this object.
#     """
# 
#     def __init__(self):
#         self.id = uuid.uuid4()
# 
#     def __hash__(self):
#         return self.id.__hash__()
# 
#     def __eq__(self, other):
#         return hasattr(other, 'id') and (self.id == other.id)
# 
#     def __repr__(self):
#         "Represent the object by its id, in addition to its memory address"
#         return ("<%s at 0x%08x with id %s>" % (str(self.__class__)[8:-2],
#                                                id(self),
#                                                str(self.id)))
# 
# class PicklableRef(object):
#     """A weak reference which can be pickled. This is achieved by
#     creating a strong reference to the object at pickling time, then restoring
#     the weak reference when unpickling. Note that unless the object being
#     referenced is also pickled and referenced after unpickling, the weak
#     reference will be dead after unpickling.
#     """
# 
#     def __init__(self, obj, callback=None):
#         self.ref = weakref.ref(obj, callback)
# 
#     def __call__(self):
#         return self.ref()
# 
#     def __getstate__(self):
#         return {'ref': self.ref()}
# 
#     def __setstate__(self, state):
#         self.ref = weakref.ref(state['ref'])
# 
# Path: openmodes/material.py
# class IsotropicMaterial(Identified):
#     def __init__(self, name, epsilon_r, mu_r):
#     def eta(self, s):
#     def eta_r(self, s):
#     def n(self, s):


from openmodes.helpers import Identified, PicklableRef
from openmodes.material import PecMaterial
import numpy as np
import uuid
        http://en.wikipedia.org/wiki/Euler%E2%80%93Rodrigues_parameters
        """

        # TODO: enable rotation about arbitrary coordinates, and about the
        # centre of the object

        axis = np.array(axis, np.float64)
        axis /= np.sqrt(np.dot(axis, axis))

        angle = angle*np.pi/180.0

        a = np.cos(0.5*angle)
        b, c, d = axis*np.sin(0.5*angle)

        matrix = np.array([[a**2 + b**2 - c**2 - d**2,
                            2*(b*c - a*d), 2*(b*d + a*c), 0],
                           [2*(b*c + a*d), a**2 + c**2 - b**2 - d**2,
                            2*(c*d - a*b), 0],
                           [2*(b*d - a*c), 2*(c*d + a*b),
                            a**2 + d**2 - b**2 - c**2, 0],
                           [0, 0, 0, 1.0]])

        self.transformation_matrix[:] = matrix.dot(self.transformation_matrix)
        self._position_updated()


class SinglePart(Part):
    """A single part, which corresponds exactly to one set of basis
    functions"""


# Path: openmodes/helpers.py
# class Identified(object):
#     """An object which can be uniquely identified by an id number. It is
#     assumed that any object which subclasses Identified is immutable, so that
#     its id can be used for caching complex results which depend on this object.
#     """
# 
#     def __init__(self):
#         self.id = uuid.uuid4()
# 
#     def __hash__(self):
#         return self.id.__hash__()
# 
#     def __eq__(self, other):
#         return hasattr(other, 'id') and (self.id == other.id)
# 
#     def __repr__(self):
#         "Represent the object by its id, in addition to its memory address"
#         return ("<%s at 0x%08x with id %s>" % (str(self.__class__)[8:-2],
#                                                id(self),
#                                                str(self.id)))
# 
# class PicklableRef(object):
#     """A weak reference which can be pickled. This is achieved by
#     creating a strong reference to the object at pickling time, then restoring
#     the weak reference when unpickling. Note that unless the object being
#     referenced is also pickled and referenced after unpickling, the weak
#     reference will be dead after unpickling.
#     """
# 
#     def __init__(self, obj, callback=None):
#         self.ref = weakref.ref(obj, callback)
# 
#     def __call__(self):
#         return self.ref()
# 
#     def __getstate__(self):
#         return {'ref': self.ref()}
# 
#     def __setstate__(self, state):
#         self.ref = weakref.ref(state['ref'])
# 
# Path: openmodes/material.py
# class IsotropicMaterial(Identified):
#     def __init__(self, name, epsilon_r, mu_r):
#     def eta(self, s):
#     def eta_r(self, s):
#     def n(self, s):


# Path: openmodes/parts.py
from openmodes.helpers import Identified, PicklableRef
from openmodes.material import PecMaterial
import numpy as np
import uuid

        http://en.wikipedia.org/wiki/Euler%E2%80%93Rodrigues_parameters
        """

        # TODO: enable rotation about arbitrary coordinates, and about the
        # centre of the object

        axis = np.array(axis, np.float64)
        axis /= np.sqrt(np.dot(axis, axis))

        angle = angle*np.pi/180.0

        a = np.cos(0.5*angle)
        b, c, d = axis*np.sin(0.5*angle)

        matrix = np.array([[a**2 + b**2 - c**2 - d**2,
                            2*(b*c - a*d), 2*(b*d + a*c), 0],
                           [2*(b*c + a*d), a**2 + c**2 - b**2 - d**2,
                            2*(c*d - a*b), 0],
                           [2*(b*d - a*c), 2*(c*d + a*b),
                            a**2 + d**2 - b**2 - c**2, 0],
                           [0, 0, 0, 1.0]])

        self.transformation_matrix[:] = matrix.dot(self.transformation_matrix)
        self._position_updated()


class SinglePart(Part):
    """A single part, which corresponds exactly to one set of basis
    functions"""


    def __init__(self, mesh, material=PecMaterial, location=None):