# Path: vasppy/configuration.py
# class Configuration:
#     def __init__( self, cell, atoms ):
#     def dr( self, atom1, atom2 ):
#     def minimum_image_dr( self, atom1, atom2, cutoff=None ):
#     def interatomic_distances( self, minimum_image_convention = True ):
#     def interatomic_distances_for_atom( self, atom1, minimum_image_convention = True ):
#     def atoms_with_label( self, label ):
#     def partial_rdf( self, spec_i, spec_j, max_r, number_of_bins ):
#     def per_atom_rdf( self, spec_i, spec_j, max_r, number_of_bins ):
# 
# Path: vasppy/atom.py
# class Atom:
#     def __init__( self, label, r ): # currently assume fractional coordinates
# 
# Path: vasppy/cell.py
# def angle( x, y ):
# def rotation_matrix(axis, theta):
#     def __init__( self, matrix ):
#     def dr( self, r1, r2, cutoff=None ):
#     def nearest_image( self, origin, point ):
#     def minimum_image( self, r1, r2 ):
#     def minimum_image_dr( self, r1, r2, cutoff=None ):
#     def lengths( self ):
#     def angles( self ):
#     def cartesian_to_fractional_coordinates( self, coordinates ):
#     def fractional_to_cartesian_coordinates( self, coordinates ):
#     def inside_cell( self, r ):
#     def volume( self ):
#     def unit_vectors( self ):
#     def rotate( self, axis, theta ):
# class Cell:
# 
# Path: vasppy/units.py



import numpy as np  # type: ignore
import sys
import re
import copy
from vasppy import configuration, atom, cell
from vasppy.units import angstrom_to_bohr
from pymatgen import Lattice as pmg_Lattice  # type: ignore
from pymatgen import Structure as pmg_Structure  # type: ignore
from pymatgen.io.cif import CifWriter  # type: ignore
from collections import Counter
from signal import signal, SIGPIPE, SIG_DFL
 
    def range_by_species( self, species ):
        i = 0
        atom_range = {}
        for a, n in zip( self.atoms, self.atom_numbers ):
            atom_range[ a ] = range(i, i+n)
            i += n
        return atom_range[ species ]

    def atom_number_by_species( self, species ):
        atom_numbers = { a : n for a, n in zip( self.atoms, self.atom_numbers ) }
        return atom_numbers[ species ]

    def sorted( self, species ):
        new_poscar = copy.deepcopy( self )
        new_poscar.atoms = species
        new_poscar.atom_numbers = [ self.atom_number_by_species( s ) for s in species ]
        new_poscar.coordinates = np.concatenate( [ self.coordinates_by_species( s ) for s in species ], axis = 0 )
        return new_poscar 
 
    def read_from( self, filename ):
        with open( filename ) as f:
            lines = f.readlines()
        self.title = lines.pop(0).strip()
        self.scaling = float( lines.pop(0).strip() ) 
        self.cell.matrix = np.array( [ [ float( e ) for e in lines.pop(0).split() ] for i in range( 3 ) ] )
        self.cell.inv_matrix = np.linalg.inv( self.cell.matrix )
        self.atoms = lines.pop(0).split()
        self.atom_numbers = [ int(element) for element in lines.pop(0).split() ]
        self.coordinate_type = lines.pop(0).strip()

# Path: vasppy/configuration.py
# class Configuration:
#     def __init__( self, cell, atoms ):
#     def dr( self, atom1, atom2 ):
#     def minimum_image_dr( self, atom1, atom2, cutoff=None ):
#     def interatomic_distances( self, minimum_image_convention = True ):
#     def interatomic_distances_for_atom( self, atom1, minimum_image_convention = True ):
#     def atoms_with_label( self, label ):
#     def partial_rdf( self, spec_i, spec_j, max_r, number_of_bins ):
#     def per_atom_rdf( self, spec_i, spec_j, max_r, number_of_bins ):
# 
# Path: vasppy/atom.py
# class Atom:
#     def __init__( self, label, r ): # currently assume fractional coordinates
# 
# Path: vasppy/cell.py
# def angle( x, y ):
# def rotation_matrix(axis, theta):
#     def __init__( self, matrix ):
#     def dr( self, r1, r2, cutoff=None ):
#     def nearest_image( self, origin, point ):
#     def minimum_image( self, r1, r2 ):
#     def minimum_image_dr( self, r1, r2, cutoff=None ):
#     def lengths( self ):
#     def angles( self ):
#     def cartesian_to_fractional_coordinates( self, coordinates ):
#     def fractional_to_cartesian_coordinates( self, coordinates ):
#     def inside_cell( self, r ):
#     def volume( self ):
#     def unit_vectors( self ):
#     def rotate( self, axis, theta ):
# class Cell:
# 
# Path: vasppy/units.py



# Path: vasppy/poscar.py
import numpy as np  # type: ignore
import sys
import re
import copy
from vasppy import configuration, atom, cell
from vasppy.units import angstrom_to_bohr
from pymatgen import Lattice as pmg_Lattice  # type: ignore
from pymatgen import Structure as pmg_Structure  # type: ignore
from pymatgen.io.cif import CifWriter  # type: ignore
from collections import Counter
from signal import signal, SIGPIPE, SIG_DFL

 
    def range_by_species( self, species ):
        i = 0
        atom_range = {}
        for a, n in zip( self.atoms, self.atom_numbers ):
            atom_range[ a ] = range(i, i+n)
            i += n
        return atom_range[ species ]

    def atom_number_by_species( self, species ):
        atom_numbers = { a : n for a, n in zip( self.atoms, self.atom_numbers ) }
        return atom_numbers[ species ]

    def sorted( self, species ):
        new_poscar = copy.deepcopy( self )
        new_poscar.atoms = species
        new_poscar.atom_numbers = [ self.atom_number_by_species( s ) for s in species ]
        new_poscar.coordinates = np.concatenate( [ self.coordinates_by_species( s ) for s in species ], axis = 0 )
        return new_poscar 
 
    def read_from( self, filename ):
        with open( filename ) as f:
            lines = f.readlines()
        self.title = lines.pop(0).strip()
        self.scaling = float( lines.pop(0).strip() ) 
        self.cell.matrix = np.array( [ [ float( e ) for e in lines.pop(0).split() ] for i in range( 3 ) ] )
        self.cell.inv_matrix = np.linalg.inv( self.cell.matrix )
        self.atoms = lines.pop(0).split()
        self.atom_numbers = [ int(element) for element in lines.pop(0).split() ]
        self.coordinate_type = lines.pop(0).strip()

        if re.match( r'\A[Ss]', self.coordinate_type ): # test for 'Selective dynamics'