# Path: vasppy/units.py

# 
# Path: vasppy/band.py
# class Band():
# 
#     def __init__( self, index, energy, occupancy, negative_occupancies='warn' ):
#         self.index = index
#         self.energy = energy
#         self.occupancy = handle_occupancy( occupancy, negative_occupancies=negative_occupancies )
# 
#     def __eq__( self, other ):
#         return ( ( self.index == other.index ) &
#                  ( self.energy == other.energy ) &
#                  ( self.occupancy == other.occupancy ) )


import numpy as np  # type: ignore
import re
import math
import warnings
import fortranformat as ff  # type: ignore
from .units import angstrom_to_bohr, ev_to_hartree
from .band import Band
from copy import deepcopy
from functools import reduce
    Returns:
        (float): The effective mass
    """
    assert( cartesian_k_points.shape[0] == 2 )
    assert( eigenvalues.size == 2 )
    dk = cartesian_k_points[ 1 ] - cartesian_k_points[ 0 ]
    mod_dk = np.sqrt( np.dot( dk, dk ) )
    delta_e = ( eigenvalues[ 1 ] - eigenvalues[ 0 ] ) * ev_to_hartree * 2.0
    effective_mass = mod_dk * mod_dk / delta_e
    return effective_mass

def least_squares_effective_mass( cartesian_k_points, eigenvalues ):
    """
    Calculate the effective mass using a least squares quadratic fit.

    Args:
        cartesian_k_points (np.array): Cartesian reciprocal coordinates for the k-points
        eigenvalues (np.array):        Energy eigenvalues at each k-point to be used in the fit.

    Returns:
        (float): The fitted effective mass

    Notes:
        If the k-points do not sit on a straight line a ValueError will be raised.
    """
    if not points_are_in_a_straight_line( cartesian_k_points ):
        raise ValueError( 'k-points are not collinear' )
    dk = cartesian_k_points - cartesian_k_points[0]
    mod_dk = np.linalg.norm( dk, axis = 1 )
    delta_e = eigenvalues - eigenvalues[0]

# Path: vasppy/units.py

# 
# Path: vasppy/band.py
# class Band():
# 
#     def __init__( self, index, energy, occupancy, negative_occupancies='warn' ):
#         self.index = index
#         self.energy = energy
#         self.occupancy = handle_occupancy( occupancy, negative_occupancies=negative_occupancies )
# 
#     def __eq__( self, other ):
#         return ( ( self.index == other.index ) &
#                  ( self.energy == other.energy ) &
#                  ( self.occupancy == other.occupancy ) )


# Path: vasppy/procar.py
import numpy as np  # type: ignore
import re
import math
import warnings
import fortranformat as ff  # type: ignore
from .units import angstrom_to_bohr, ev_to_hartree
from .band import Band
from copy import deepcopy
from functools import reduce

    Returns:
        (float): The effective mass
    """
    assert( cartesian_k_points.shape[0] == 2 )
    assert( eigenvalues.size == 2 )
    dk = cartesian_k_points[ 1 ] - cartesian_k_points[ 0 ]
    mod_dk = np.sqrt( np.dot( dk, dk ) )
    delta_e = ( eigenvalues[ 1 ] - eigenvalues[ 0 ] ) * ev_to_hartree * 2.0
    effective_mass = mod_dk * mod_dk / delta_e
    return effective_mass

def least_squares_effective_mass( cartesian_k_points, eigenvalues ):
    """
    Calculate the effective mass using a least squares quadratic fit.

    Args:
        cartesian_k_points (np.array): Cartesian reciprocal coordinates for the k-points
        eigenvalues (np.array):        Energy eigenvalues at each k-point to be used in the fit.

    Returns:
        (float): The fitted effective mass

    Notes:
        If the k-points do not sit on a straight line a ValueError will be raised.
    """
    if not points_are_in_a_straight_line( cartesian_k_points ):
        raise ValueError( 'k-points are not collinear' )
    dk = cartesian_k_points - cartesian_k_points[0]
    mod_dk = np.linalg.norm( dk, axis = 1 )
    delta_e = eigenvalues - eigenvalues[0]

    effective_mass = 1.0 / ( np.polyfit( mod_dk, eigenvalues, 2 )[0] * ev_to_hartree * 2.0 )