# Path: paratemp/exceptions.py
# class UnknownEnergyError(Exception):
#     """
#     Exception raised when an object does not know it's energy, but it's queried
# 
#     """
# 
#     def __init__(self, msg=None):
#         self.msg = msg
# 
#     def __str__(self):
#         standard_response = (
#             "The energy is unknown either because it wasn't "
#             "in the original file or the coordinates have "
#             "changed.\nCould try XYZ.original_energy"
#         )
#         if self.msg is None:
#             return repr(standard_response)
#         else:
#             return repr(self.msg)
# 
# class InputError(Exception):
#     """Exception raised for errors in the input.
# 
#     Attributes:
#         expr -- input expression in which the error occurred
#         msg  -- explanation of the error
#     """
# 
#     def __init__(self, expr, msg):
#         self.expr = expr
#         self.msg = msg
# 
#     def __str__(self):
#         output = 'Incorrect input "{}". {}'.format(self.expr, self.msg)
#         return repr(output)


import re
import numpy as np
from numpy.linalg import norm
from .exceptions import UnknownEnergyError, InputError

def rotation_matrix(axis, theta):
    """
    Return the rotation matrix associated with counterclockwise rotation about
    the given axis by theta radians.

    copied from
    https://stackoverflow.com/questions/6802577/python-rotation-of-3d-vector
    """
    axis = np.asarray(axis)
    axis = axis / np.sqrt(np.dot(axis, axis))
    a = np.cos(theta / 2.0)
    b, c, d = -axis * np.sin(theta / 2.0)
    aa, bb, cc, dd = a * a, b * b, c * c, d * d
    bc, ad, ac, ab, bd, cd = b * c, a * d, a * c, a * b, b * d, c * d
    return np.array(
        [
            [aa + bb - cc - dd, 2 * (bc + ad), 2 * (bd - ac)],
            [2 * (bc - ad), aa + cc - bb - dd, 2 * (cd + ab)],
            [2 * (bd + ac), 2 * (cd - ab), aa + dd - bb - cc],
        ]
    )


class Vector(np.ndarray):
    def __new__(cls, *xyz):
        if len(xyz) != 3:
            try:
                xyz = xyz[0]
            except IndexError:

# Path: paratemp/exceptions.py
# class UnknownEnergyError(Exception):
#     """
#     Exception raised when an object does not know it's energy, but it's queried
# 
#     """
# 
#     def __init__(self, msg=None):
#         self.msg = msg
# 
#     def __str__(self):
#         standard_response = (
#             "The energy is unknown either because it wasn't "
#             "in the original file or the coordinates have "
#             "changed.\nCould try XYZ.original_energy"
#         )
#         if self.msg is None:
#             return repr(standard_response)
#         else:
#             return repr(self.msg)
# 
# class InputError(Exception):
#     """Exception raised for errors in the input.
# 
#     Attributes:
#         expr -- input expression in which the error occurred
#         msg  -- explanation of the error
#     """
# 
#     def __init__(self, expr, msg):
#         self.expr = expr
#         self.msg = msg
# 
#     def __str__(self):
#         output = 'Incorrect input "{}". {}'.format(self.expr, self.msg)
#         return repr(output)


# Path: paratemp/geometries.py
import re
import numpy as np
from numpy.linalg import norm
from .exceptions import UnknownEnergyError, InputError


def rotation_matrix(axis, theta):
    """
    Return the rotation matrix associated with counterclockwise rotation about
    the given axis by theta radians.

    copied from
    https://stackoverflow.com/questions/6802577/python-rotation-of-3d-vector
    """
    axis = np.asarray(axis)
    axis = axis / np.sqrt(np.dot(axis, axis))
    a = np.cos(theta / 2.0)
    b, c, d = -axis * np.sin(theta / 2.0)
    aa, bb, cc, dd = a * a, b * b, c * c, d * d
    bc, ad, ac, ab, bd, cd = b * c, a * d, a * c, a * b, b * d, c * d
    return np.array(
        [
            [aa + bb - cc - dd, 2 * (bc + ad), 2 * (bd - ac)],
            [2 * (bc - ad), aa + cc - bb - dd, 2 * (cd + ab)],
            [2 * (bd + ac), 2 * (cd - ab), aa + dd - bb - cc],
        ]
    )


class Vector(np.ndarray):
    def __new__(cls, *xyz):
        if len(xyz) != 3:
            try:
                xyz = xyz[0]
            except IndexError:

                raise InputError(xyz, "3 values are required to make a vector")