# Path: cclib/method/calculationmethod.py
# class Method:
#     """Abstract base class for all cclib method classes.
# 
#     Subclasses defined by cclib:
#         CDA - charde decomposition analysis
#         CSPA - C-squared population analysis
#         Density - density matrix calculation
#         FragmentAnalysis - fragment analysis for ADF output
#         LPA - Löwdin population analysis
#         MBO - Mayer's bond orders
#         Moments - multipole moments calculations
#         MPA - Mulliken population analysis
#         Nuclear - properties of atomic nuclei
#         OPA - overlap population analysis
#         Population - base class for population analyses
#         Volume - volume/grid calculations
# 
#     All the modules containing methods should be importable.
#     """
#     required_attrs = ()
#     def __init__(self, data, progress=None, loglevel=logging.INFO, logname="Log"):
#         """Initialise the Logfile object.
# 
#         This constructor is typically called by the constructor of a subclass.
#         """
# 
#         self.data = data
#         self.progress = progress
#         self.loglevel = loglevel
#         self.logname = logname
#         self._check_required_attributes()
#         self.logger = logging.getLogger('%s %s' % (self.logname, self.data))
#         self.logger.setLevel(self.loglevel)
#         self.logformat = "[%(name)s %(levelname)s] %(message)s"
#         handler = logging.StreamHandler(sys.stdout)
#         handler.setFormatter(logging.Formatter(self.logformat))
#         self.logger.addHandler(handler)
# 
#     def _check_required_attributes(self):
#         """Check if required attributes are present in data."""
#         missing = [x for x in self.required_attrs
#                     if not hasattr(self.data, x)]
#         if missing:
#             missing = ' '.join(missing)
#             raise MissingAttributeError(
#                 'Could not parse required attributes to use method: ' + missing)
# 
# Path: cclib/method/volume.py
# def electrondensity_spin(ccdata, volume, mocoeffslist):
#     """Calculate the magnitude of the electron density at every point in a volume for either up or down spin
# 
#     Inputs:
#         ccdata -- ccData object
#         volume -- Volume object (will not be altered)
#         mocoeffslist -- list of molecular orbital to calculate electron density from;
#                         i.e. [ccdata.mocoeffs[0][1:2]]
# 
#     Output:
#         Volume object with wavefunction at each grid point stored in data attribute
# 
#     Attributes:
#         coords -- the coordinates of the atoms
#         mocoeffs -- mocoeffs for all of the occupied eigenvalues
#         gbasis -- gbasis from a parser object
#         volume -- a template Volume object (will not be altered)
# 
#     Note: mocoeffs is a list of NumPy arrays. The list will be of length 1.
#     """
#     assert (
#         len(mocoeffslist) == 1
#     ), "mocoeffslist input to the function should have length of 1."
#     _check_pyquante()
#     bfs = getbfs(ccdata)
# 
#     density = copy.copy(volume)
#     density.data = numpy.zeros(density.data.shape, "d")
# 
#     x, y, z = getGrid(density)
#     gridpoints = numpy.asanyarray(
#         tuple((xp, yp, zp) for xp in x for yp in y for zp in z)
#     )
# 
#     # For occupied orbitals
#     # `mocoeff` and `gbasis` in ccdata object is ordered in a way `homos` can specify which orbital
#     # is the highest lying occupied orbital in mocoeff and gbasis.
#     for mocoeffs in mocoeffslist:
#         for mocoeff in mocoeffs:
#             wavefn = numpy.zeros(density.data.shape, "d")
#             for bs in range(len(bfs)):
#                 if abs(mocoeff[bs]) > 0.0:
#                     wavefn += numpy.resize(
#                         pyamp(bfs, bs, gridpoints) * mocoeff[bs], density.data.shape
#                     )
#             density.data += wavefn ** 2
#     return density


import copy
import random
import numpy
import logging
import math
from cclib.method.calculationmethod import Method
from cclib.method.volume import electrondensity_spin
from cclib.parser.utils import convertor
                "It looks like pseudopotentials were used to generate this output. Please note that the Bader charges may not be accurate and may report unexpected results. Consult the original paper (doi:10.1016/j.commatsci.2005.04.010) for more information."
            )

    def __str__(self):
        """Return a string representation of the object."""
        return "Bader's QTAIM charges of {}".format(self.data)

    def __repr__(self):
        """Return a representation of the object."""
        return "Bader({})".format(self.data)

    def _check_required_attributes(self):
        super()._check_required_attributes()

    def calculate(self, indices=None, fupdate=0.05):
        """Calculate Bader's QTAIM charges using on-grid algorithm proposed by Henkelman group
           in doi:10.1016/j.commatsci.2005.04.010
           
           Cartesian, uniformly spaced grids are assumed for this function.
           """

        # Obtain charge densities on the grid if it does not contain one.
        if not numpy.any(self.volume.data):
            self.logger.info("Calculating charge densities on the provided empty grid.")
            if len(self.data.mocoeffs) == 1:
                self.chgdensity = electrondensity_spin(
                    self.data, self.volume, [self.data.mocoeffs[0][: self.data.homos[0]]]
                )
                self.chgdensity.data *= 2
            else:

# Path: cclib/method/calculationmethod.py
# class Method:
#     """Abstract base class for all cclib method classes.
# 
#     Subclasses defined by cclib:
#         CDA - charde decomposition analysis
#         CSPA - C-squared population analysis
#         Density - density matrix calculation
#         FragmentAnalysis - fragment analysis for ADF output
#         LPA - Löwdin population analysis
#         MBO - Mayer's bond orders
#         Moments - multipole moments calculations
#         MPA - Mulliken population analysis
#         Nuclear - properties of atomic nuclei
#         OPA - overlap population analysis
#         Population - base class for population analyses
#         Volume - volume/grid calculations
# 
#     All the modules containing methods should be importable.
#     """
#     required_attrs = ()
#     def __init__(self, data, progress=None, loglevel=logging.INFO, logname="Log"):
#         """Initialise the Logfile object.
# 
#         This constructor is typically called by the constructor of a subclass.
#         """
# 
#         self.data = data
#         self.progress = progress
#         self.loglevel = loglevel
#         self.logname = logname
#         self._check_required_attributes()
#         self.logger = logging.getLogger('%s %s' % (self.logname, self.data))
#         self.logger.setLevel(self.loglevel)
#         self.logformat = "[%(name)s %(levelname)s] %(message)s"
#         handler = logging.StreamHandler(sys.stdout)
#         handler.setFormatter(logging.Formatter(self.logformat))
#         self.logger.addHandler(handler)
# 
#     def _check_required_attributes(self):
#         """Check if required attributes are present in data."""
#         missing = [x for x in self.required_attrs
#                     if not hasattr(self.data, x)]
#         if missing:
#             missing = ' '.join(missing)
#             raise MissingAttributeError(
#                 'Could not parse required attributes to use method: ' + missing)
# 
# Path: cclib/method/volume.py
# def electrondensity_spin(ccdata, volume, mocoeffslist):
#     """Calculate the magnitude of the electron density at every point in a volume for either up or down spin
# 
#     Inputs:
#         ccdata -- ccData object
#         volume -- Volume object (will not be altered)
#         mocoeffslist -- list of molecular orbital to calculate electron density from;
#                         i.e. [ccdata.mocoeffs[0][1:2]]
# 
#     Output:
#         Volume object with wavefunction at each grid point stored in data attribute
# 
#     Attributes:
#         coords -- the coordinates of the atoms
#         mocoeffs -- mocoeffs for all of the occupied eigenvalues
#         gbasis -- gbasis from a parser object
#         volume -- a template Volume object (will not be altered)
# 
#     Note: mocoeffs is a list of NumPy arrays. The list will be of length 1.
#     """
#     assert (
#         len(mocoeffslist) == 1
#     ), "mocoeffslist input to the function should have length of 1."
#     _check_pyquante()
#     bfs = getbfs(ccdata)
# 
#     density = copy.copy(volume)
#     density.data = numpy.zeros(density.data.shape, "d")
# 
#     x, y, z = getGrid(density)
#     gridpoints = numpy.asanyarray(
#         tuple((xp, yp, zp) for xp in x for yp in y for zp in z)
#     )
# 
#     # For occupied orbitals
#     # `mocoeff` and `gbasis` in ccdata object is ordered in a way `homos` can specify which orbital
#     # is the highest lying occupied orbital in mocoeff and gbasis.
#     for mocoeffs in mocoeffslist:
#         for mocoeff in mocoeffs:
#             wavefn = numpy.zeros(density.data.shape, "d")
#             for bs in range(len(bfs)):
#                 if abs(mocoeff[bs]) > 0.0:
#                     wavefn += numpy.resize(
#                         pyamp(bfs, bs, gridpoints) * mocoeff[bs], density.data.shape
#                     )
#             density.data += wavefn ** 2
#     return density


# Path: cclib/method/bader.py
import copy
import random
import numpy
import logging
import math
from cclib.method.calculationmethod import Method
from cclib.method.volume import electrondensity_spin
from cclib.parser.utils import convertor

                "It looks like pseudopotentials were used to generate this output. Please note that the Bader charges may not be accurate and may report unexpected results. Consult the original paper (doi:10.1016/j.commatsci.2005.04.010) for more information."
            )

    def __str__(self):
        """Return a string representation of the object."""
        return "Bader's QTAIM charges of {}".format(self.data)

    def __repr__(self):
        """Return a representation of the object."""
        return "Bader({})".format(self.data)

    def _check_required_attributes(self):
        super()._check_required_attributes()

    def calculate(self, indices=None, fupdate=0.05):
        """Calculate Bader's QTAIM charges using on-grid algorithm proposed by Henkelman group
           in doi:10.1016/j.commatsci.2005.04.010
           
           Cartesian, uniformly spaced grids are assumed for this function.
           """

        # Obtain charge densities on the grid if it does not contain one.
        if not numpy.any(self.volume.data):
            self.logger.info("Calculating charge densities on the provided empty grid.")
            if len(self.data.mocoeffs) == 1:
                self.chgdensity = electrondensity_spin(
                    self.data, self.volume, [self.data.mocoeffs[0][: self.data.homos[0]]]
                )
                self.chgdensity.data *= 2
            else:

                self.chgdensity = electrondensity_spin(