<reponame>harmsm/gpgraph
__description__ = \
"""
Functions for checking the sanity of various variable types. Used throughout
the library.
"""
__author__ = "<NAME>"
__date__ = "2021-08-31"

import numpy as np
from gpmap import GenotypePhenotypeMap

def gpm_sanity(gpm):
    """
    Check sanity of a genotype phenotype map.
    """

    try:
        if not type(gpm) is GenotypePhenotypeMap:
            raise ValueError

    except ValueError:
        err = "gpm must be a GenotypePhenotypeMap instance"
        raise ValueError(err)

def node_list_sanity(node_list,G):
    """
    Check sanity of a node list.

    Parameters
    ----------
    node_list : list-like
        list of nodes to use for networkx calculations/graphing
    G : GenotypePhenotypeGraph instance
    """

    try:
        G_nodes = list(G.nodes)
    except (AttributeError,TypeError):
        err = "G chould be a GenotypePhenotypeGraph instance with a gpmap\n"
        err += "loaded."
        raise ValueError(err)

    # Check node_list sanity
    try:
        len(node_list)

        # Are all nodes in node list found in G?
        if not set(node_list).issubset(set(G_nodes)):
            raise TypeError

        # Are all entries unique?
        if len(set(node_list)) != len(node_list):
            raise TypeError

    except TypeError:
        err = "node_list must be a list that contains only indexes found in\n"
        err += "G.nodes. All elements must be unique.\n"
        raise ValueError(err)


def int_sanity(possible_int):
    """
    Enforce sanity check on possible integer, throwing ValueError if not
    interpretable as integer.

    Parameters
    ----------
    possible_int : ?
        possible integer to evaluate.
    """

    try:
        # Try to cast as int
        int(possible_int)

        # If this is a float, see if it has zero after decimal
        if type(possible_int) is float or isinstance(possible_int, np.floating):
            if round(possible_int) != possible_int:
                raise ValueError
    except (ValueError,TypeError):
        err = f"Could not safely coerce '{possible_int}' into an integer\n"
        raise ValueError(err)

def float_sanity(possible_float,min_allowed=-np.inf,max_allowed=np.inf):
    """
    Enforce sanity check on possible float, throwing ValueError if not
    interpretable as float.

    Parameters
    ----------
    possible_float: ?
        possible float to evaluate.
    min_allowed : float
        minimium allowed value for the variable
    max_allowed : float
        maximum allowed value for the variable
    """

    try:
        # Try to cast as int
        float(possible_float)

    except (ValueError,TypeError):
        err = f"Could not safely coerce '{possible_float}' into a float\n"
        raise ValueError(err)

    if float(possible_float) <= min_allowed:
        err = f"'{possible_float}' < minimum allowed value ({min_allowed})\n"
        raise ValueError(err)

    if float(possible_float) >= max_allowed:
        err = f"'{possible_float}' > maximum allowed value ({max_allowed})\n"
        raise ValueError(err)

__description__ = \
"""
Functions for checking the sanity of various variable types. Used throughout
the library.
"""
__author__ = "<NAME>"
__date__ = "2021-08-31"

import numpy as np
from gpmap import GenotypePhenotypeMap

def gpm_sanity(gpm):
    """
    Check sanity of a genotype phenotype map.
    """

    try:
        if not type(gpm) is GenotypePhenotypeMap:
            raise ValueError

    except ValueError:
        err = "gpm must be a GenotypePhenotypeMap instance"
        raise ValueError(err)

def node_list_sanity(node_list,G):
    """
    Check sanity of a node list.

    Parameters
    ----------
    node_list : list-like
        list of nodes to use for networkx calculations/graphing
    G : GenotypePhenotypeGraph instance
    """

    try:
        G_nodes = list(G.nodes)
    except (AttributeError,TypeError):
        err = "G chould be a GenotypePhenotypeGraph instance with a gpmap\n"
        err += "loaded."
        raise ValueError(err)

    # Check node_list sanity
    try:
        len(node_list)

        # Are all nodes in node list found in G?
        if not set(node_list).issubset(set(G_nodes)):
            raise TypeError

        # Are all entries unique?
        if len(set(node_list)) != len(node_list):
            raise TypeError

    except TypeError:
        err = "node_list must be a list that contains only indexes found in\n"
        err += "G.nodes. All elements must be unique.\n"
        raise ValueError(err)


def int_sanity(possible_int):
    """
    Enforce sanity check on possible integer, throwing ValueError if not
    interpretable as integer.

    Parameters
    ----------
    possible_int : ?
        possible integer to evaluate.
    """

    try:
        # Try to cast as int
        int(possible_int)

        # If this is a float, see if it has zero after decimal
        if type(possible_int) is float or isinstance(possible_int, np.floating):
            if round(possible_int) != possible_int:
                raise ValueError
    except (ValueError,TypeError):
        err = f"Could not safely coerce '{possible_int}' into an integer\n"
        raise ValueError(err)

def float_sanity(possible_float,min_allowed=-np.inf,max_allowed=np.inf):
    """
    Enforce sanity check on possible float, throwing ValueError if not
    interpretable as float.

    Parameters
    ----------
    possible_float: ?
        possible float to evaluate.
    min_allowed : float
        minimium allowed value for the variable
    max_allowed : float
        maximum allowed value for the variable
    """

    try:
        # Try to cast as int
        float(possible_float)

    except (ValueError,TypeError):
        err = f"Could not safely coerce '{possible_float}' into a float\n"
        raise ValueError(err)

    if float(possible_float) <= min_allowed:
        err = f"'{possible_float}' < minimum allowed value ({min_allowed})\n"
        raise ValueError(err)

    if float(possible_float) >= max_allowed:
        err = f"'{possible_float}' > maximum allowed value ({max_allowed})\n"
        raise ValueError(err)
Functions for checking the sanity of various variable types. Used throughout the library. Check sanity of a genotype phenotype map. Check sanity of a node list.      Parameters     ----------     node_list : list-like         list of nodes to use for networkx calculations/graphing     G : GenotypePhenotypeGraph instance # Check node_list sanity # Are all nodes in node list found in G? # Are all entries unique? Enforce sanity check on possible integer, throwing ValueError if not     interpretable as integer.      Parameters     ----------     possible_int : ?         possible integer to evaluate. # Try to cast as int # If this is a float, see if it has zero after decimal Enforce sanity check on possible float, throwing ValueError if not     interpretable as float.      Parameters     ----------     possible_float: ?         possible float to evaluate.     min_allowed : float         minimium allowed value for the variable     max_allowed : float         maximum allowed value for the variable # Try to cast as int