# Path: openmodes/parts.py
# class Part(Identified):
#     """A part which has been placed into the simulation, and which can be
#     modified"""
# 
#     def __init__(self, location=None):
#         super(Part, self).__init__()
# 
#         self.initial_location = location
#         self.transformation_matrix = np.empty((4, 4))
#         self.reset()
#         self.parent_ref = None
# 
#     def reset(self):
#         """Reset this part to the default values of the original `Mesh`
#         from which this `Part` was created, and move it to its initial
#         location (the origin if not specified).
#         """
#         self.transformation_matrix[:] = np.eye(4)
#         if self.initial_location is not None:
#             self.translate(self.initial_location)
#         self._position_updated()
# 
#     def _position_updated(self):
#         "Called when position is updated"
#         pass
# 
#     @property
#     def complete_transformation(self):
#         """The complete transformation matrix, which takes into account
#         the transformation matrix of all parents"""
#         if self.parent_ref is None:
#             return self.transformation_matrix
#         else:
#             return self.parent_ref().complete_transformation.dot(
#                                                     self.transformation_matrix)
# 
#     def translate(self, offset_vector):
#         """Translate a part by an arbitrary offset vector
# 
#         Care needs to be take if this puts an object in a different layer
#         """
#         translation = np.eye(4)
#         translation[:3, 3] = offset_vector
# 
#         self.transformation_matrix[:] = translation.dot(
#                                                     self.transformation_matrix)
#         self._position_updated()
# 
#     def rotate(self, axis, angle):
#         """
#         Rotate about an arbitrary axis
# 
#         Parameters
#         ----------
#         axis : ndarray
#             the vector about which to rotate
#         angle : number
#             angle of rotation in degrees
# 
#         Algorithm taken from
#         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()


import numpy as np
import numbers
import collections
import six
import warnings
from openmodes.parts import Part
        return part_ranges_lowest(parent_part, basis_container)

    # get the size of each child part
    sizes = [len(basis_container[part]) for part in parent_part.iter_single()]
    offsets = np.cumsum([0]+sizes)

    ranges = {}

    # index of single parts to get the offsets
    single_part_num = 0

    # iterate with parents last, so they can get data from their child objects
    for part in parent_part.iter_all(parent_first=False):
        if hasattr(part, 'children'):
            # take slice information from first and last child
            start = ranges[part.children[0]].start
            stop = ranges[part.children[-1]].stop
            ranges[part] = slice(start, stop)
        else:
            ranges[part] = slice(offsets[single_part_num], offsets[single_part_num+1])
            single_part_num += 1

    return ranges


def build_lookup(index_data):
    "Create the lookup table for a LookupArray"
    lookup = []
    shape = []
    for index in index_data:

# Path: openmodes/parts.py
# class Part(Identified):
#     """A part which has been placed into the simulation, and which can be
#     modified"""
# 
#     def __init__(self, location=None):
#         super(Part, self).__init__()
# 
#         self.initial_location = location
#         self.transformation_matrix = np.empty((4, 4))
#         self.reset()
#         self.parent_ref = None
# 
#     def reset(self):
#         """Reset this part to the default values of the original `Mesh`
#         from which this `Part` was created, and move it to its initial
#         location (the origin if not specified).
#         """
#         self.transformation_matrix[:] = np.eye(4)
#         if self.initial_location is not None:
#             self.translate(self.initial_location)
#         self._position_updated()
# 
#     def _position_updated(self):
#         "Called when position is updated"
#         pass
# 
#     @property
#     def complete_transformation(self):
#         """The complete transformation matrix, which takes into account
#         the transformation matrix of all parents"""
#         if self.parent_ref is None:
#             return self.transformation_matrix
#         else:
#             return self.parent_ref().complete_transformation.dot(
#                                                     self.transformation_matrix)
# 
#     def translate(self, offset_vector):
#         """Translate a part by an arbitrary offset vector
# 
#         Care needs to be take if this puts an object in a different layer
#         """
#         translation = np.eye(4)
#         translation[:3, 3] = offset_vector
# 
#         self.transformation_matrix[:] = translation.dot(
#                                                     self.transformation_matrix)
#         self._position_updated()
# 
#     def rotate(self, axis, angle):
#         """
#         Rotate about an arbitrary axis
# 
#         Parameters
#         ----------
#         axis : ndarray
#             the vector about which to rotate
#         angle : number
#             angle of rotation in degrees
# 
#         Algorithm taken from
#         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()


# Path: openmodes/array.py
import numpy as np
import numbers
import collections
import six
import warnings
from openmodes.parts import Part

        return part_ranges_lowest(parent_part, basis_container)

    # get the size of each child part
    sizes = [len(basis_container[part]) for part in parent_part.iter_single()]
    offsets = np.cumsum([0]+sizes)

    ranges = {}

    # index of single parts to get the offsets
    single_part_num = 0

    # iterate with parents last, so they can get data from their child objects
    for part in parent_part.iter_all(parent_first=False):
        if hasattr(part, 'children'):
            # take slice information from first and last child
            start = ranges[part.children[0]].start
            stop = ranges[part.children[-1]].stop
            ranges[part] = slice(start, stop)
        else:
            ranges[part] = slice(offsets[single_part_num], offsets[single_part_num+1])
            single_part_num += 1

    return ranges


def build_lookup(index_data):
    "Create the lookup table for a LookupArray"
    lookup = []
    shape = []
    for index in index_data:

        if isinstance(index, collections.Iterable) and isinstance(index[0], Part):