# Path: vasppy/poscar.py
# def parity( list ):
# def swap_axes( matrix, axes ):
#     def __init__( self ):
#     def coordinates_by_species( self, species ):
#     def range_by_species( self, species ):
#     def atom_number_by_species( self, species ):
#     def sorted( self, species ):
#     def read_from( self, filename ):
#     def from_file( cls, filename ):
#     def in_bohr( self ):
#     def coords_are_fractional( self ): 
#     def coords_are_cartesian( self ):
#     def fractional_coordinates( self ):
#     def cartesian_coordinates( self ):
#     def select_coordinates( self, coordinate_type='Direct' ):
#     def output_coordinates_only( self, coordinate_type='Direct', opts=None ):
#     def output( self, coordinate_type='Direct', opts=None ):
#     def output_header( self, coordinate_type='Direct', opts=None ):
#     def write_to( self, filename, coordinate_type='Direct', opts=None ):
#     def output_as_xtl( self ):
#     def output_as_cif( self, symprec = None ):
#     def output_as_pimaim( self, to_bohr = True ):
#     def cell_coordinates( self ):
#     def labels( self ):
#     def replicate( self, h, k, l, group=False ):
#     def cell_lengths( self ):
#     def cell_angles( self ):
#     def to_configuration( self ):
#     def swap_axes( self, axes ):
#     def to_pymatgen_structure( self ):
#     def stoichiometry( self ):
# class Poscar:
# 
# 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:


import numpy as np  # type: ignore
import sys
import math
from vasppy import poscar, cell

    def fractional_coordinate_at_index( self, index ):      
        return( np.multiply( self.spacing, index ) )

    def cartesian_coordinate_at_index( self, index ):
        return( self.fractional_coordinate_at_index( index ).dot( self.poscar.cell.matrix ) )

    def cube_slice( self, x0, y0, z0 ):
        x1 = ( x0 + 1 ) % self.dimensions[0]
        y1 = ( y0 + 1 ) % self.dimensions[1]
        z1 = ( z0 + 1 ) % self.dimensions[2]
        cube = np.array( [ self.grid[ x0, y0, z0 ],
                           self.grid[ x0, y0, z1 ],
                           self.grid[ x0, y1, z0 ],
                           self.grid[ x0, y1, z1 ],
                           self.grid[ x1, y0, z0 ],
                           self.grid[ x1, y0, z1 ],
                           self.grid[ x1, y1, z0 ],
                           self.grid[ x1, y1, z1 ] ] ).reshape( 2, 2, 2 )
        return( cube )

    def interpolated_value_at_fractional_coordinate( self, coord ):
        point = np.multiply( np.array( self.dimensions ), coord ) # point contains the (fractional) index of the coordinate coord.
        origin = [ int( f ) for f in point ]                      # origin contains the 3D index of the lowest-index point in the cube surrounding point (i,j,k)
        delta = [ p - o for p, o in zip( point, origin ) ]        # delta contains the *fractional* offset of "point" from "origin"
        cube = self.cube_slice( *origin )                         # cube contains the data values at the 8 bounding grid points
        return( trilinear_interpolation( cube, delta ) )

    def interpolate_to_orthorhombic_grid( self, dimensions ): # warning. This may need a more robust minimim image function in Cell.py for highly non-orthorhombic cells
        old_grid = self

# Path: vasppy/poscar.py
# def parity( list ):
# def swap_axes( matrix, axes ):
#     def __init__( self ):
#     def coordinates_by_species( self, species ):
#     def range_by_species( self, species ):
#     def atom_number_by_species( self, species ):
#     def sorted( self, species ):
#     def read_from( self, filename ):
#     def from_file( cls, filename ):
#     def in_bohr( self ):
#     def coords_are_fractional( self ): 
#     def coords_are_cartesian( self ):
#     def fractional_coordinates( self ):
#     def cartesian_coordinates( self ):
#     def select_coordinates( self, coordinate_type='Direct' ):
#     def output_coordinates_only( self, coordinate_type='Direct', opts=None ):
#     def output( self, coordinate_type='Direct', opts=None ):
#     def output_header( self, coordinate_type='Direct', opts=None ):
#     def write_to( self, filename, coordinate_type='Direct', opts=None ):
#     def output_as_xtl( self ):
#     def output_as_cif( self, symprec = None ):
#     def output_as_pimaim( self, to_bohr = True ):
#     def cell_coordinates( self ):
#     def labels( self ):
#     def replicate( self, h, k, l, group=False ):
#     def cell_lengths( self ):
#     def cell_angles( self ):
#     def to_configuration( self ):
#     def swap_axes( self, axes ):
#     def to_pymatgen_structure( self ):
#     def stoichiometry( self ):
# class Poscar:
# 
# 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/grid.py
import numpy as np  # type: ignore
import sys
import math
from vasppy import poscar, cell


    def fractional_coordinate_at_index( self, index ):      
        return( np.multiply( self.spacing, index ) )

    def cartesian_coordinate_at_index( self, index ):
        return( self.fractional_coordinate_at_index( index ).dot( self.poscar.cell.matrix ) )

    def cube_slice( self, x0, y0, z0 ):
        x1 = ( x0 + 1 ) % self.dimensions[0]
        y1 = ( y0 + 1 ) % self.dimensions[1]
        z1 = ( z0 + 1 ) % self.dimensions[2]
        cube = np.array( [ self.grid[ x0, y0, z0 ],
                           self.grid[ x0, y0, z1 ],
                           self.grid[ x0, y1, z0 ],
                           self.grid[ x0, y1, z1 ],
                           self.grid[ x1, y0, z0 ],
                           self.grid[ x1, y0, z1 ],
                           self.grid[ x1, y1, z0 ],
                           self.grid[ x1, y1, z1 ] ] ).reshape( 2, 2, 2 )
        return( cube )

    def interpolated_value_at_fractional_coordinate( self, coord ):
        point = np.multiply( np.array( self.dimensions ), coord ) # point contains the (fractional) index of the coordinate coord.
        origin = [ int( f ) for f in point ]                      # origin contains the 3D index of the lowest-index point in the cube surrounding point (i,j,k)
        delta = [ p - o for p, o in zip( point, origin ) ]        # delta contains the *fractional* offset of "point" from "origin"
        cube = self.cube_slice( *origin )                         # cube contains the data values at the 8 bounding grid points
        return( trilinear_interpolation( cube, delta ) )

    def interpolate_to_orthorhombic_grid( self, dimensions ): # warning. This may need a more robust minimim image function in Cell.py for highly non-orthorhombic cells
        old_grid = self

        old_cell = old_grid.poscar.cell