# Path: pyDFTutils/ase_utils/symbol.py
# def get_symdict(filename='POSCAR',atoms=None):
#     """
#     get a symbol_number: index dict.
#     """
#     if atoms is not None:
#         syms=atoms.get_chemical_symbols()
#     elif filename is not None and atoms is None:
#         syms=read(filename).get_chemical_symbols()
# 
#     symdict=symbol_number(syms)
#     return symdict
# 
# def symbol_number(symbols):
#     """
#     symbols can be also atoms. Thus the chemical symbols will be used.
#     Fe Fe Fe O -> {Fe1:0 Fe2:1 Fe3:2 O1:3}
#     """
#     try:
#         symbs=symbols.copy().get_chemical_symbols()
#     except Exception:
#         symbs=symbols
#     symdict={}
#     result=OrderedDict()
#     for i,sym in enumerate(symbs):
#         if sym in symdict:
#             symdict[sym]=symdict[sym]+1
#         else:
#             symdict[sym]=1
#         result[sym+str(symdict[sym])]=i
#     return result
# 
# def symnum_to_sym(symbol_number):
#     """
#     symnum-> sym. eg: Fe1-> Fe
#     """
#     try:
#         a=re.search('[A-Za-z]+',symbol_number).group()
#         return a
#     except AttributeError:
#         raise AttributeError('%s is not a good symbol_number'%symbol_number)


from ase.utils.geometry import rotate
from ase.io import read
from ase.geometry.cell import cellpar_to_cell, cell_to_cellpar
from pyDFTutils.ase_utils.symbol import get_symdict,symbol_number,symnum_to_sym
from pyDFTutils.ase_utils.ase_utils import scaled_pos_to_pos,force_near_0,pos_to_scaled_pos
from collections import OrderedDict,Iterable
from ase.calculators.neighborlist import NeighborList
    from scipy.sparse import csr_matrix
    from scipy.sparse.csgraph import dijkstra
import numpy as np
    import argparse


def vec_ang(a,b):
    """angle of two vectors, 0 ~ 180"""
    return np.arccos(np.inner(a,b)/(np.linalg.norm(a)*np.linalg.norm(b)))/np.pi*180

def atom_angle(a1,a2,a3):
    """
    angle a1-a2-a3
    a1 a2 a3 are atom objects
    """
    vec1=a2.position-a1.position
    vec2=a2.position-a3.position
    return vec_ang(vec1,vec2)


def even_or_odd_path(atoms,from_symnum,node_sym_list,to_symnum_list=None,first_neighbor_min=2.5,first_neighbor_max=4.5):
    """
    Find whether the distance of the atoms with symnum in to_list to the atom(from_symnum) is even or odd.
    The distance to the first neighbor is 1. The 1st neighbor's 1st neighbor is 2. etc....
    Args:
      atoms:
      from_symnum
      to_sym_list: The symbol of the atoms, eg:['Fe','Ni' ], Note the from_symnum should be start with the symbol in this list
      to_symnum_list: The symbol_number of the atoms, eg:['Fe1','Fe2','Ni1'].Only one of the to_sym_list and to_symnum_list should should be specified.
      first_neighbor_min/max: The min/max distance to the first neighbor
    Returns:
      a dict.  The values are 1/-1. 1 is odd, -1: even eg {'Fe1':1,'Ni1':-1}
    """
    #1. Get the first neighbor list

# Path: pyDFTutils/ase_utils/symbol.py
# def get_symdict(filename='POSCAR',atoms=None):
#     """
#     get a symbol_number: index dict.
#     """
#     if atoms is not None:
#         syms=atoms.get_chemical_symbols()
#     elif filename is not None and atoms is None:
#         syms=read(filename).get_chemical_symbols()
# 
#     symdict=symbol_number(syms)
#     return symdict
# 
# def symbol_number(symbols):
#     """
#     symbols can be also atoms. Thus the chemical symbols will be used.
#     Fe Fe Fe O -> {Fe1:0 Fe2:1 Fe3:2 O1:3}
#     """
#     try:
#         symbs=symbols.copy().get_chemical_symbols()
#     except Exception:
#         symbs=symbols
#     symdict={}
#     result=OrderedDict()
#     for i,sym in enumerate(symbs):
#         if sym in symdict:
#             symdict[sym]=symdict[sym]+1
#         else:
#             symdict[sym]=1
#         result[sym+str(symdict[sym])]=i
#     return result
# 
# def symnum_to_sym(symbol_number):
#     """
#     symnum-> sym. eg: Fe1-> Fe
#     """
#     try:
#         a=re.search('[A-Za-z]+',symbol_number).group()
#         return a
#     except AttributeError:
#         raise AttributeError('%s is not a good symbol_number'%symbol_number)


# Path: pyDFTutils/perovskite/octahedra.py
from ase.utils.geometry import rotate
from ase.io import read
from ase.geometry.cell import cellpar_to_cell, cell_to_cellpar
from pyDFTutils.ase_utils.symbol import get_symdict,symbol_number,symnum_to_sym
from pyDFTutils.ase_utils.ase_utils import scaled_pos_to_pos,force_near_0,pos_to_scaled_pos
from collections import OrderedDict,Iterable
from ase.calculators.neighborlist import NeighborList
    from scipy.sparse import csr_matrix
    from scipy.sparse.csgraph import dijkstra
import numpy as np
    import argparse



def vec_ang(a,b):
    """angle of two vectors, 0 ~ 180"""
    return np.arccos(np.inner(a,b)/(np.linalg.norm(a)*np.linalg.norm(b)))/np.pi*180

def atom_angle(a1,a2,a3):
    """
    angle a1-a2-a3
    a1 a2 a3 are atom objects
    """
    vec1=a2.position-a1.position
    vec2=a2.position-a3.position
    return vec_ang(vec1,vec2)


def even_or_odd_path(atoms,from_symnum,node_sym_list,to_symnum_list=None,first_neighbor_min=2.5,first_neighbor_max=4.5):
    """
    Find whether the distance of the atoms with symnum in to_list to the atom(from_symnum) is even or odd.
    The distance to the first neighbor is 1. The 1st neighbor's 1st neighbor is 2. etc....
    Args:
      atoms:
      from_symnum
      to_sym_list: The symbol of the atoms, eg:['Fe','Ni' ], Note the from_symnum should be start with the symbol in this list
      to_symnum_list: The symbol_number of the atoms, eg:['Fe1','Fe2','Ni1'].Only one of the to_sym_list and to_symnum_list should should be specified.
      first_neighbor_min/max: The min/max distance to the first neighbor
    Returns:
      a dict.  The values are 1/-1. 1 is odd, -1: even eg {'Fe1':1,'Ni1':-1}
    """
    #1. Get the first neighbor list

    symdict=symbol_number(atoms)