# 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/rdf.py
# RDF = TypeVar('RDF', bound='RadialDistributionFunction')
# VHA = TypeVar('VHA', bound='VanHoveAnalysis')
# class RadialDistributionFunction(object):
# class VanHoveAnalysis(object):
#     def __init__(self,
#                  structures: List[Structure],
#                  indices_i: List[int],
#                  indices_j: Optional[List[int]] = None,
#                  nbins: int = 500,
#                  r_min: float = 0.0,
#                  r_max: float = 10.0,
#                  weights: Optional[List[float]] = None) -> None:
#     def smeared_rdf(self, 
#                     sigma: float = 0.1) -> np.ndarray:
#     def from_species_strings(cls: Type[RDF], 
#                              structures: List[Structure], 
#                              species_i: str, 
#                              species_j: Optional[str] = None, 
#                              **kwargs) -> RDF:
#     def __dr_ij(self, 
#                 structure: Structure) -> np.ndarray:
#     def __init__(self,
#                  structures: List[Structure],
#                  indices: List[int],
#                  d_steps: int,
#                  nbins: int = 500,
#                  r_min: float = 0.0,
#                  r_max: float = 10.0):
#     def self(self, 
#              sigma: Optional[float] = None) -> np.ndarray:
#     def distinct(self,
#                  sigma: Optional[float] = None) -> np.ndarray:
#     def smeared_gsrt(self, 
#                      sigma: float = 0.1) -> np.ndarray:
#     def smeared_gdrt(self,
#                      sigma: float = 0.1) -> np.ndarray:
# def shell_volumes(intervals: np.ndarray) -> np.ndarray:


from vasppy import atom, cell, rdf
import numpy as np  # type: ignore
    def minimum_image_dr( self, atom1, atom2, cutoff=None ):
        return self.cell.minimum_image_dr( atom1.r, atom2.r, cutoff=cutoff )

    def interatomic_distances( self, minimum_image_convention = True ):
        return np.array( [ [ self.minimum_image_dr( atom_i, atom_j ) for atom_j in self.atoms ] for atom_i in self.atoms ] )

    def interatomic_distances_for_atom( self, atom1, minimum_image_convention = True ):
        return np.array( [ self.minimum_image_dr( atom1, atom2 ) for atom2 in self.atoms ] )

    def atoms_with_label( self, label ):
        return filter( lambda atom: atom.label == label, self.atoms )        

    def partial_rdf( self, spec_i, spec_j, max_r, number_of_bins ):
        this_rdf = rdf.Rdf( max_r, number_of_bins )
        atoms_i = list( self.atoms_with_label( spec_i ) )
        atoms_j = list( self.atoms_with_label( spec_j ) )
        for atom_i in atoms_i:
            for atom_j in atoms_j:
                if atom_i is atom_j:
                    continue
                dr = self.minimum_image_dr( atom_i, atom_j )
                if dr <= max_r:
                    this_rdf.add_dr( dr )
        return this_rdf 

    def per_atom_rdf( self, spec_i, spec_j, max_r, number_of_bins ):
        rdfs = []
        atoms_i = list( self.atoms_with_label( spec_i ) )
        atoms_j = list( self.atoms_with_label( spec_j ) )
        for atom_i in atoms_i:

# 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/rdf.py
# RDF = TypeVar('RDF', bound='RadialDistributionFunction')
# VHA = TypeVar('VHA', bound='VanHoveAnalysis')
# class RadialDistributionFunction(object):
# class VanHoveAnalysis(object):
#     def __init__(self,
#                  structures: List[Structure],
#                  indices_i: List[int],
#                  indices_j: Optional[List[int]] = None,
#                  nbins: int = 500,
#                  r_min: float = 0.0,
#                  r_max: float = 10.0,
#                  weights: Optional[List[float]] = None) -> None:
#     def smeared_rdf(self, 
#                     sigma: float = 0.1) -> np.ndarray:
#     def from_species_strings(cls: Type[RDF], 
#                              structures: List[Structure], 
#                              species_i: str, 
#                              species_j: Optional[str] = None, 
#                              **kwargs) -> RDF:
#     def __dr_ij(self, 
#                 structure: Structure) -> np.ndarray:
#     def __init__(self,
#                  structures: List[Structure],
#                  indices: List[int],
#                  d_steps: int,
#                  nbins: int = 500,
#                  r_min: float = 0.0,
#                  r_max: float = 10.0):
#     def self(self, 
#              sigma: Optional[float] = None) -> np.ndarray:
#     def distinct(self,
#                  sigma: Optional[float] = None) -> np.ndarray:
#     def smeared_gsrt(self, 
#                      sigma: float = 0.1) -> np.ndarray:
#     def smeared_gdrt(self,
#                      sigma: float = 0.1) -> np.ndarray:
# def shell_volumes(intervals: np.ndarray) -> np.ndarray:


# Path: vasppy/configuration.py
from vasppy import atom, cell, rdf
import numpy as np  # type: ignore

    def minimum_image_dr( self, atom1, atom2, cutoff=None ):
        return self.cell.minimum_image_dr( atom1.r, atom2.r, cutoff=cutoff )

    def interatomic_distances( self, minimum_image_convention = True ):
        return np.array( [ [ self.minimum_image_dr( atom_i, atom_j ) for atom_j in self.atoms ] for atom_i in self.atoms ] )

    def interatomic_distances_for_atom( self, atom1, minimum_image_convention = True ):
        return np.array( [ self.minimum_image_dr( atom1, atom2 ) for atom2 in self.atoms ] )

    def atoms_with_label( self, label ):
        return filter( lambda atom: atom.label == label, self.atoms )        

    def partial_rdf( self, spec_i, spec_j, max_r, number_of_bins ):
        this_rdf = rdf.Rdf( max_r, number_of_bins )
        atoms_i = list( self.atoms_with_label( spec_i ) )
        atoms_j = list( self.atoms_with_label( spec_j ) )
        for atom_i in atoms_i:
            for atom_j in atoms_j:
                if atom_i is atom_j:
                    continue
                dr = self.minimum_image_dr( atom_i, atom_j )
                if dr <= max_r:
                    this_rdf.add_dr( dr )
        return this_rdf 

    def per_atom_rdf( self, spec_i, spec_j, max_r, number_of_bins ):
        rdfs = []
        atoms_i = list( self.atoms_with_label( spec_i ) )
        atoms_j = list( self.atoms_with_label( spec_j ) )
        for atom_i in atoms_i:

            this_rdf = rdf.Rdf( max_r, number_of_bins )