# Path: tilde/core/common.py
# class ModuleError(Exception):
#     def __init__(self, value):
#         self.value = value
# 
# Path: tilde/core/constants.py
# class Perovskite_Structure:
#     A = 'Li, Na, K, Rb, Cs, Fr, Mg, Ca, Sr, Ba, Ra, Sc, Sc, Y, La, Ce, Pr, Nd, Pm, Sm, Eu, Gd, Tb, Dy, Ho, Er, Tm, Yb, Lu, Ag, Pb, Bi, Th, In, Mn, Zn'.split(', ')
#     B = 'Ti, V, Cr, Mn, Fe, Co, Ni, Cu, Zn, Ga, Zr, Nb, Mo, Tc, Ru, Rh, Pd, Ag, Cd, In, Sn, Sb, Hf, Ta, W, Re, Se, La, Pr, Pb'.split(', ')
#     C = 'H, O, F, Cl, Br, I'.split(', ')
# 
# Path: tilde/core/symmetry.py
# class SymmetryFinder:
#     accuracy = 1e-04
# 
#     def __init__(self, accuracy=None):
#         self.error = None
#         self.accuracy=accuracy if accuracy else SymmetryFinder.accuracy
#         self.angle_tolerance = -1
# 
#     def get_spacegroup(self, tilde_obj):
#         try:
#             symmetry = spg.get_spacegroup(tilde_obj['structures'][-1], symprec=self.accuracy, angle_tolerance=self.angle_tolerance)
#         except Exception as ex:
#             self.error = 'Symmetry finder error: %s' % ex
#         else:
#             try:
#                 self.sg, self.ng = symmetry.split()
#                 self.ng = int(self.ng.strip("()"))
#             except (ValueError, IndexError, AttributeError):
#                 self.ng = 0
#                 self.error = 'Symmetry finder error (probably, coinciding atoms)'
# 
#     def refine_cell(self, tilde_obj):
#         '''
#         NB only used for perovskite_tilting app
#         '''
#         try: lattice, positions, numbers = spg.refine_cell(tilde_obj['structures'][-1], symprec=self.accuracy, angle_tolerance=self.angle_tolerance)
#         except Exception as ex:
#             self.error = 'Symmetry finder error: %s' % ex
#         else:
#             self.refinedcell = Atoms(numbers=numbers, cell=lattice, scaled_positions=positions, pbc=tilde_obj['structures'][-1].get_pbc())
#             self.refinedcell.periodicity = sum(self.refinedcell.get_pbc())
#             self.refinedcell.dims = abs(det(tilde_obj['structures'][-1].cell))


import math
from functools import reduce
from numpy.linalg import norm
from ase import Atom
from tilde.core.common import ModuleError #, generate_xyz
from tilde.core.constants import Perovskite_Structure
from tilde.core.symmetry import SymmetryFinder

# Perovskites octahedral tilting extraction
# based on Surf.Sci.602 3674 (2008)
# http://dx.doi.org/10.1016/j.susc.2008.10.002
# Author: Evgeny Blokhin
#
# KNOWN BUG: in some low-symmetry cases ("batio3_lda_hw12d_160_to.out"),
# octahedra are not adjusted with the axes, and their distortion origin is unknown.
# Even if the rotation is absent (i.e. pseudo-cubic structure),
# an "artificial" rotation can be extracted

from __future__ import division





class Perovskite_tilting():
    OCTAHEDRON_BOND_LENGTH_LIMIT = 2.5  # Angstrom
    OCTAHEDRON_ATOMS_Z_DIFFERENCE = 1.6 # Angstrom
    MAX_TILTING_DEGREE = 22.4           # degrees, this is for adjusting, may produce unphysical results

    def __init__(self, tilde_calc):
        self.prec_angles = {}    # non-rounded, non-unique, all-planes angles
        self.angles = {}         # rounded, unique, one-plane angles


# Path: tilde/core/common.py
# class ModuleError(Exception):
#     def __init__(self, value):
#         self.value = value
# 
# Path: tilde/core/constants.py
# class Perovskite_Structure:
#     A = 'Li, Na, K, Rb, Cs, Fr, Mg, Ca, Sr, Ba, Ra, Sc, Sc, Y, La, Ce, Pr, Nd, Pm, Sm, Eu, Gd, Tb, Dy, Ho, Er, Tm, Yb, Lu, Ag, Pb, Bi, Th, In, Mn, Zn'.split(', ')
#     B = 'Ti, V, Cr, Mn, Fe, Co, Ni, Cu, Zn, Ga, Zr, Nb, Mo, Tc, Ru, Rh, Pd, Ag, Cd, In, Sn, Sb, Hf, Ta, W, Re, Se, La, Pr, Pb'.split(', ')
#     C = 'H, O, F, Cl, Br, I'.split(', ')
# 
# Path: tilde/core/symmetry.py
# class SymmetryFinder:
#     accuracy = 1e-04
# 
#     def __init__(self, accuracy=None):
#         self.error = None
#         self.accuracy=accuracy if accuracy else SymmetryFinder.accuracy
#         self.angle_tolerance = -1
# 
#     def get_spacegroup(self, tilde_obj):
#         try:
#             symmetry = spg.get_spacegroup(tilde_obj['structures'][-1], symprec=self.accuracy, angle_tolerance=self.angle_tolerance)
#         except Exception as ex:
#             self.error = 'Symmetry finder error: %s' % ex
#         else:
#             try:
#                 self.sg, self.ng = symmetry.split()
#                 self.ng = int(self.ng.strip("()"))
#             except (ValueError, IndexError, AttributeError):
#                 self.ng = 0
#                 self.error = 'Symmetry finder error (probably, coinciding atoms)'
# 
#     def refine_cell(self, tilde_obj):
#         '''
#         NB only used for perovskite_tilting app
#         '''
#         try: lattice, positions, numbers = spg.refine_cell(tilde_obj['structures'][-1], symprec=self.accuracy, angle_tolerance=self.angle_tolerance)
#         except Exception as ex:
#             self.error = 'Symmetry finder error: %s' % ex
#         else:
#             self.refinedcell = Atoms(numbers=numbers, cell=lattice, scaled_positions=positions, pbc=tilde_obj['structures'][-1].get_pbc())
#             self.refinedcell.periodicity = sum(self.refinedcell.get_pbc())
#             self.refinedcell.dims = abs(det(tilde_obj['structures'][-1].cell))


# Path: tilde/apps/perovskite_tilting/perovskite_tilting.py
import math
from functools import reduce
from numpy.linalg import norm
from ase import Atom
from tilde.core.common import ModuleError #, generate_xyz
from tilde.core.constants import Perovskite_Structure
from tilde.core.symmetry import SymmetryFinder


# Perovskites octahedral tilting extraction
# based on Surf.Sci.602 3674 (2008)
# http://dx.doi.org/10.1016/j.susc.2008.10.002
# Author: Evgeny Blokhin
#
# KNOWN BUG: in some low-symmetry cases ("batio3_lda_hw12d_160_to.out"),
# octahedra are not adjusted with the axes, and their distortion origin is unknown.
# Even if the rotation is absent (i.e. pseudo-cubic structure),
# an "artificial" rotation can be extracted

from __future__ import division





class Perovskite_tilting():
    OCTAHEDRON_BOND_LENGTH_LIMIT = 2.5  # Angstrom
    OCTAHEDRON_ATOMS_Z_DIFFERENCE = 1.6 # Angstrom
    MAX_TILTING_DEGREE = 22.4           # degrees, this is for adjusting, may produce unphysical results

    def __init__(self, tilde_calc):
        self.prec_angles = {}    # non-rounded, non-unique, all-planes angles
        self.angles = {}         # rounded, unique, one-plane angles


        symm = SymmetryFinder()