# Path: astroNN/shared/nn_tools.py
# def cpu_fallback(flag=True):
#     """
#     A function to force Tensorflow to use CPU even Nvidia GPU present
# 
#     :param flag: True to fallback to CPU, False to un-manage CPU or GPU
#     :type flag: bool
#     :History:
#         | 2017-Nov-25 - Written - Henry Leung (University of Toronto)
#         | 2020-May-31 - Update for tf 2
#     """
#     gpu_phy_devices = tf.config.list_physical_devices('GPU')
#     cpu_phy_devices = tf.config.list_physical_devices('CPU')
# 
#     general_warning_msg = f"Tensorflow has already been initialized, {inspect.currentframe().f_code.co_name}() needs " \
#                           f"to be called before any Tensorflow operation, as a result this function will have no effect"
# 
#     if flag is True:
#         try:
#             tf.config.set_visible_devices([], 'GPU')
#         except RuntimeError:
#             warnings.warn(general_warning_msg)
#     elif flag is False:
#         try:
#             tf.config.set_visible_devices(gpu_phy_devices, 'GPU')
#         except RuntimeError:
#             warnings.warn(general_warning_msg)
#     else:
#         raise ValueError('Unknown flag, can only be True of False!')
# 
# def gpu_memory_manage(ratio=True, log_device_placement=False):
#     """
#     To manage GPU memory usage, prevent Tensorflow preoccupied all the video RAM
# 
#     :param ratio: Optional, ratio of GPU memory pre-allocating to astroNN
#     :type ratio: Union[NoneType, float]
#     :param log_device_placement: whether or not log the device placement
#     :type log_device_placement: bool
#     :History:
#         | 2017-Nov-25 - Written - Henry Leung (University of Toronto)
#         | 2020-Jun-1 - Updated for tf v2
#     """
#     gpu_phy_devices = tf.config.list_physical_devices('GPU')
# 
#     general_warning_msg = f"Tensorflow has already been initialized, {inspect.currentframe().f_code.co_name}() needs " \
#                           f"to be called before any Tensorflow operation, as a result this function will have no effect"
# 
#     try:
#         if ratio:
#             for gpu in gpu_phy_devices:
#                 tf.config.experimental.set_memory_growth(gpu, True)
#         else:
#             for gpu in gpu_phy_devices:
#                 tf.config.experimental.set_memory_growth(gpu, False)
# 
#         if log_device_placement:
#             tf.debugging.set_log_device_placement(True)
#         else:
#             tf.debugging.set_log_device_placement(False)
#     except RuntimeError:
#         warnings.warn(general_warning_msg)
# 
#     return None


import configparser
import os
import platform
    import astroNN.data
    import tensorflow as tf
    import tensorflow.python as tfpython
from astroNN.shared.nn_tools import cpu_fallback, gpu_memory_manage
    from astroNN.shared.patch_util import Patch
    from tensorflow.python import keras
    from packaging import version
    NAME: cpu_gpu_reader
    PURPOSE: to read cpu gpu setting in config
    INPUT:
    OUTPUT:
        (boolean)
    HISTORY:
        2018-Mar-14 - Written - Henry Leung (University of Toronto)
    """
    cpath = config_path()
    config = configparser.ConfigParser()
    config.read(cpath)

    try:
        cpu_string = config['NeuralNet']['CPUFallback']
        gpu_string = config['NeuralNet']['GPU_Mem_ratio']
        cpu_string = True if cpu_string.upper() == 'TRUE' else False
        gpu_string = True if gpu_string.upper() == 'TRUE' else False
        return cpu_string, gpu_string
    except KeyError:
        config_path(flag=1)
        return cpu_gpu_reader()


def cpu_gpu_check():
    fallback_cpu, limit_gpu_mem = cpu_gpu_reader()
    if fallback_cpu is True:
        cpu_fallback()
    if isinstance(limit_gpu_mem, float) is True:
        gpu_memory_manage(ratio=limit_gpu_mem)
    else:

# Path: astroNN/shared/nn_tools.py
# def cpu_fallback(flag=True):
#     """
#     A function to force Tensorflow to use CPU even Nvidia GPU present
# 
#     :param flag: True to fallback to CPU, False to un-manage CPU or GPU
#     :type flag: bool
#     :History:
#         | 2017-Nov-25 - Written - Henry Leung (University of Toronto)
#         | 2020-May-31 - Update for tf 2
#     """
#     gpu_phy_devices = tf.config.list_physical_devices('GPU')
#     cpu_phy_devices = tf.config.list_physical_devices('CPU')
# 
#     general_warning_msg = f"Tensorflow has already been initialized, {inspect.currentframe().f_code.co_name}() needs " \
#                           f"to be called before any Tensorflow operation, as a result this function will have no effect"
# 
#     if flag is True:
#         try:
#             tf.config.set_visible_devices([], 'GPU')
#         except RuntimeError:
#             warnings.warn(general_warning_msg)
#     elif flag is False:
#         try:
#             tf.config.set_visible_devices(gpu_phy_devices, 'GPU')
#         except RuntimeError:
#             warnings.warn(general_warning_msg)
#     else:
#         raise ValueError('Unknown flag, can only be True of False!')
# 
# def gpu_memory_manage(ratio=True, log_device_placement=False):
#     """
#     To manage GPU memory usage, prevent Tensorflow preoccupied all the video RAM
# 
#     :param ratio: Optional, ratio of GPU memory pre-allocating to astroNN
#     :type ratio: Union[NoneType, float]
#     :param log_device_placement: whether or not log the device placement
#     :type log_device_placement: bool
#     :History:
#         | 2017-Nov-25 - Written - Henry Leung (University of Toronto)
#         | 2020-Jun-1 - Updated for tf v2
#     """
#     gpu_phy_devices = tf.config.list_physical_devices('GPU')
# 
#     general_warning_msg = f"Tensorflow has already been initialized, {inspect.currentframe().f_code.co_name}() needs " \
#                           f"to be called before any Tensorflow operation, as a result this function will have no effect"
# 
#     try:
#         if ratio:
#             for gpu in gpu_phy_devices:
#                 tf.config.experimental.set_memory_growth(gpu, True)
#         else:
#             for gpu in gpu_phy_devices:
#                 tf.config.experimental.set_memory_growth(gpu, False)
# 
#         if log_device_placement:
#             tf.debugging.set_log_device_placement(True)
#         else:
#             tf.debugging.set_log_device_placement(False)
#     except RuntimeError:
#         warnings.warn(general_warning_msg)
# 
#     return None


# Path: astroNN/config.py
import configparser
import os
import platform
    import astroNN.data
    import tensorflow as tf
    import tensorflow.python as tfpython
from astroNN.shared.nn_tools import cpu_fallback, gpu_memory_manage
    from astroNN.shared.patch_util import Patch
    from tensorflow.python import keras
    from packaging import version

    NAME: cpu_gpu_reader
    PURPOSE: to read cpu gpu setting in config
    INPUT:
    OUTPUT:
        (boolean)
    HISTORY:
        2018-Mar-14 - Written - Henry Leung (University of Toronto)
    """
    cpath = config_path()
    config = configparser.ConfigParser()
    config.read(cpath)

    try:
        cpu_string = config['NeuralNet']['CPUFallback']
        gpu_string = config['NeuralNet']['GPU_Mem_ratio']
        cpu_string = True if cpu_string.upper() == 'TRUE' else False
        gpu_string = True if gpu_string.upper() == 'TRUE' else False
        return cpu_string, gpu_string
    except KeyError:
        config_path(flag=1)
        return cpu_gpu_reader()


def cpu_gpu_check():
    fallback_cpu, limit_gpu_mem = cpu_gpu_reader()
    if fallback_cpu is True:
        cpu_fallback()
    if isinstance(limit_gpu_mem, float) is True:
        gpu_memory_manage(ratio=limit_gpu_mem)
    else:

        gpu_memory_manage()