# 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)
# 
# class MissingAttributeError(Exception):
#     pass


import logging
import numpy
from cclib.method.calculationmethod import Method, MissingAttributeError




class Population(Method):
    """An abstract base class for population-type methods."""

    # All of these are typically required for population analyses.
    required_attrs = ('homos', 'mocoeffs', 'nbasis')

    # At least one of these are typically required.
    overlap_attributes = ('aooverlaps', 'fooverlaps')

    def __init__(self, data, progress=None, \
                 loglevel=logging.INFO, logname="Log"):
        super().__init__(data, progress, loglevel, logname)

        self.fragresults = None

    def __str__(self):
        """Return a string representation of the object."""
        return "Population"

    def __repr__(self):
        """Return a representation of the object."""
        return "Population"

    def _check_required_attributes(self):
        super()._check_required_attributes()
        
        if self.overlap_attributes and not any(hasattr(self.data, a) for a in self.overlap_attributes):

# 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)
# 
# class MissingAttributeError(Exception):
#     pass


# Path: cclib/method/population.py
import logging
import numpy
from cclib.method.calculationmethod import Method, MissingAttributeError




class Population(Method):
    """An abstract base class for population-type methods."""

    # All of these are typically required for population analyses.
    required_attrs = ('homos', 'mocoeffs', 'nbasis')

    # At least one of these are typically required.
    overlap_attributes = ('aooverlaps', 'fooverlaps')

    def __init__(self, data, progress=None, \
                 loglevel=logging.INFO, logname="Log"):
        super().__init__(data, progress, loglevel, logname)

        self.fragresults = None

    def __str__(self):
        """Return a string representation of the object."""
        return "Population"

    def __repr__(self):
        """Return a representation of the object."""
        return "Population"

    def _check_required_attributes(self):
        super()._check_required_attributes()
        
        if self.overlap_attributes and not any(hasattr(self.data, a) for a in self.overlap_attributes):

            raise MissingAttributeError(
