# -*- coding: utf-8 -*-
"""
Provides functions for data transformation (currently only LLS) and
normalization.
"""

import numpy as np


def transform(raw_data, mode, direction='direct', **kwargs):
    """
    Apply mathematical transformations to data.

    Parameters
    ----------
    raw_data : ndarray
        2D numpy array with the shape (N, M) containing N data rows to be
        smoothed. Each data row is represented by row in numpy array and
        contains M values. If only one data row is present, raw_data has the
        shape (1, M).
    mode : str
        Maths used for transformation. Allowed mode is 'log_log_sqrt' only at
        the moment which first takes the square root and then does the
        logarithm twice.
    direction : str, optional
        Gives the direction of the tranformation. If 'direct', the data is
        transformed, if 'inverse', the inverse of the transformation is
        calculated. The default is 'direct'.
    **kwargs for the different modes
        mode is 'log_log_sqrt' and direction is 'inverse':
            min_value : float
                Original minimum value of the data before transformation. Has
                to be known because it is lost upon transformation. Default is
                1.

    Raises
    ------
    ValueError
        If the value passed as mode or direction is not understood.

    Returns
    -------
    raw_data : ndarray
        Transformed data with the same shape as raw_data.

    """
    # list of allowed modes for data transformation
    transform_modes = ['log_log_sqrt']

    if direction == 'direct':
        if mode == transform_modes[0]:
            minimum_value = np.min(raw_data)
            raw_data -= minimum_value
            raw_data = np.log(np.log(np.sqrt(raw_data + 1) + 1) + 1)
        else:
            raise ValueError('No valid transform mode entered. Allowed modes '
                             'are {0}'.format(transform_modes))

    elif direction == 'inverse':
        if mode == transform_modes[0]:
            minimum_value = kwargs.get('min_value', 1)
            raw_data = (np.exp(np.exp(raw_data) - 1) - 1)**2 - 1
            raw_data += minimum_value
        else:
            raise ValueError('No valid transform mode entered. Allowed modes '
                             'are {0}'.format(transform_modes))
    else:
        raise ValueError('No valid transform direction entered. Allowed '
                         'directions are [\'direct\', \'inverse\']')

    return raw_data


def normalize(raw_data, mode, factor=1, **kwargs):
    raw_data = np.asarray(raw_data)

    # list of allowed modes for normalization
    normalize_modes = ['total_intensity']

    if mode == normalize_modes[0]:
        x_data_points = raw_data.shape[1]
        x_data = kwargs.get('x_data', np.arange(x_data_points))
        conversion_factor = 1/np.repeat(np.trapz(raw_data, x=x_data, axis=1),
                                        x_data_points).reshape(
                                            (-1, x_data_points))

        normalized_data = raw_data * conversion_factor * factor
    else:
        raise ValueError('No valid normalization mode entered. Allowed modes '
                         'are {0}'.format(normalize_modes))

    return normalized_data

# -*- coding: utf-8 -*-
"""
Provides functions for data transformation (currently only LLS) and
normalization.
"""

import numpy as np


def transform(raw_data, mode, direction='direct', **kwargs):
    """
    Apply mathematical transformations to data.

    Parameters
    ----------
    raw_data : ndarray
        2D numpy array with the shape (N, M) containing N data rows to be
        smoothed. Each data row is represented by row in numpy array and
        contains M values. If only one data row is present, raw_data has the
        shape (1, M).
    mode : str
        Maths used for transformation. Allowed mode is 'log_log_sqrt' only at
        the moment which first takes the square root and then does the
        logarithm twice.
    direction : str, optional
        Gives the direction of the tranformation. If 'direct', the data is
        transformed, if 'inverse', the inverse of the transformation is
        calculated. The default is 'direct'.
    **kwargs for the different modes
        mode is 'log_log_sqrt' and direction is 'inverse':
            min_value : float
                Original minimum value of the data before transformation. Has
                to be known because it is lost upon transformation. Default is
                1.

    Raises
    ------
    ValueError
        If the value passed as mode or direction is not understood.

    Returns
    -------
    raw_data : ndarray
        Transformed data with the same shape as raw_data.

    """
    # list of allowed modes for data transformation
    transform_modes = ['log_log_sqrt']

    if direction == 'direct':
        if mode == transform_modes[0]:
            minimum_value = np.min(raw_data)
            raw_data -= minimum_value
            raw_data = np.log(np.log(np.sqrt(raw_data + 1) + 1) + 1)
        else:
            raise ValueError('No valid transform mode entered. Allowed modes '
                             'are {0}'.format(transform_modes))

    elif direction == 'inverse':
        if mode == transform_modes[0]:
            minimum_value = kwargs.get('min_value', 1)
            raw_data = (np.exp(np.exp(raw_data) - 1) - 1)**2 - 1
            raw_data += minimum_value
        else:
            raise ValueError('No valid transform mode entered. Allowed modes '
                             'are {0}'.format(transform_modes))
    else:
        raise ValueError('No valid transform direction entered. Allowed '
                         'directions are [\'direct\', \'inverse\']')

    return raw_data


def normalize(raw_data, mode, factor=1, **kwargs):
    raw_data = np.asarray(raw_data)

    # list of allowed modes for normalization
    normalize_modes = ['total_intensity']

    if mode == normalize_modes[0]:
        x_data_points = raw_data.shape[1]
        x_data = kwargs.get('x_data', np.arange(x_data_points))
        conversion_factor = 1/np.repeat(np.trapz(raw_data, x=x_data, axis=1),
                                        x_data_points).reshape(
                                            (-1, x_data_points))

        normalized_data = raw_data * conversion_factor * factor
    else:
        raise ValueError('No valid normalization mode entered. Allowed modes '
                         'are {0}'.format(normalize_modes))

    return normalized_data

# -*- coding: utf-8 -*- Provides functions for data transformation (currently only LLS) and normalization. Apply mathematical transformations to data.      Parameters     ----------     raw_data : ndarray         2D numpy array with the shape (N, M) containing N data rows to be         smoothed. Each data row is represented by row in numpy array and         contains M values. If only one data row is present, raw_data has the         shape (1, M).     mode : str         Maths used for transformation. Allowed mode is 'log_log_sqrt' only at         the moment which first takes the square root and then does the         logarithm twice.     direction : str, optional         Gives the direction of the tranformation. If 'direct', the data is         transformed, if 'inverse', the inverse of the transformation is         calculated. The default is 'direct'.     **kwargs for the different modes         mode is 'log_log_sqrt' and direction is 'inverse':             min_value : float                 Original minimum value of the data before transformation. Has                 to be known because it is lost upon transformation. Default is                 1.      Raises     ------     ValueError         If the value passed as mode or direction is not understood.      Returns     -------     raw_data : ndarray         Transformed data with the same shape as raw_data. # list of allowed modes for data transformation # list of allowed modes for normalization