################
#### MIOPY #####
################

import pandas as pd
import numpy as np
from pandarallel import pandarallel
from sklearn.model_selection import train_test_split, KFold
from sklearn.linear_model import LarsCV, Lasso, LassoCV, ElasticNetCV, ElasticNet, Ridge, RidgeCV
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import RandomizedSearchCV
from statsmodels.stats.multitest import multipletests

from os import path
from .R_utils import tmm_normalization, deg_edger, deg_limma_array, voom_normalization
from .process_data import *
from .immune import ips
from .data import load_gene_ips
from multiprocessing import Pool
import functools

import scipy.stats
import ranky as rk
from .process_data import *

##################
## Miscelaneos ###
##################

def adjust_geneset(table):
    """
    Function to adjust the p-values of the geneset
    Args:
        table   df  Dataframe long table with the pvalues from the geneset
    """

    p = table["Pval"]
    mask = np.isfinite(p)

    #Creating an empty vector
    table["FDR"] = 1
    table.loc[mask,"FDR"] = multipletests(p[mask], method="fdr_bh")[1]
    return table

def adj_pval(df):
    """
    Function to adjust the p-values of the correlation results
    Args:
        df  df  Dataframe with the correlation results
    Returns:
        df  df  Dataframe with the correlation results and the adjusted pvalues
    """

    l_cor = ["Rho","R","Tau","Background"]
    method = "fdr_bh"

    for cor in l_cor:
        col = "%s_%s"  %(cor,method)
        col_raw = "%s_Pval" %(cor)

        #Pval
        try:
            p = df[col_raw]
            mask = np.isfinite(p)

            #Creating an empty vector
            df[col] = 1

            df.loc[mask,col] = multipletests(p[mask], method=method)[1]
        except Exception as e:
            print(e)

    return df

##################
## GeneSetScore ##
##################
def calculate_gene_set_score(expr, conf):
    """
    Function to calculate the GeneSetScore
    Args:
        expr    df  Dataframe with the expression of the genes
        conf    df  Dataframe with the targeting of the genes
    Returns:
        GScore  float   GeneSetScore
    """

    sum_gene_predictor = sum(expr * conf)
    sum_predictor = sum(conf)

    try:
        GScore = sum_gene_predictor/sum_predictor
    except:
        GScore = 0
    #print(GScore)
    return GScore

def gene_set_correlation(exprDf, lGeneSet, GeneSetName="GeneSet", lMirUser=None, n_core=6):
    """
    Calculate the correlation between a GeneSet and the expression of microRNA, considering microRNA/gene targeting.

    Args:
        exprDf (DataFrame): Dataframe with gene expression data.
        lGeneSet (list): List of genes in the GeneSet.
        GeneSetName (str): Name of the GeneSet.
        lMirUser (list): List of microRNA to use.
        n_core (int): Number of CPU cores to use for parallel processing.

    Returns:
        dfCor (DataFrame): Dataframe with correlation values between the GeneSet and microRNA.
        dfPval (DataFrame): Dataframe with p-values of the correlation between the GeneSet and microRNA.
        dfSetScore (DataFrame): Dataframe with the GeneSetScore of the GeneSet.
    """

    # Initialize parallel processing with the specified number of cores
    pandarallel.initialize(verbose=1, nb_workers=int(n_core))

    # Extract the list of microRNA and gene names from the expression dataframe
    lMir, lGene = header_list(exprDF=exprDf)

    # Load a confident dataframe and count "1" occurrences in the expression matrix
    dfConf = get_confident_df(load_matrix_counts().apply(lambda col: col.str.count("1")))
    print("[+] microRNA/Gene confidence target calculated", flush=True)
    # Intersect gene and microRNA lists with the confident dataframe indices and columns
    lGene = intersection(lGene, dfConf.index.tolist())
    lMir = intersection(lMir, dfConf.columns.tolist())

    # Intersect the gene list with the provided GeneSet if it is given
    if lGeneSet is not None:
        lGene = intersection(lGene, lGeneSet)

    # Intersect the microRNA list with the provided list if it is given
    if lMirUser is not None:
        lMir = intersection(lMir, lMirUser)

    # Calculate the GeneSetScore for each microRNA and gene pair using parallel processing
    dfSetScore = dfConf.loc[lGene, lMir].parallel_apply(lambda conf:
                                                        exprDf[lGene].apply(lambda expr:
                                                                           calculate_gene_set_score(expr, conf),
                                                                           axis=1), axis=0)
    print("[+] microRNA/Geneset score calculated", flush=True)
    # Remove columns with NaN values from the GeneSetScore dataframe
    dfSetScore = dfSetScore.apply(lambda col: col.dropna())

    # Calculate the correlation between GeneSetScore and gene expression for each microRNA
    cor = dfSetScore.parallel_apply(lambda col:
                                   col.corr(exprDf[col.name], method=lambda x, y: scipy.stats.pearsonr(x, y)))

    # Remove columns with NaN values from the correlation dataframe
    cor = cor.apply(lambda col: col.dropna())

    # Create dataframes for correlation and p-values
    # Create dataframes for correlation and p-values
    dfPval = pd.DataFrame(cor.iloc[0, :])
    dfCor = pd.DataFrame(cor.iloc[1, :])

    # Rename the columns with the GeneSetName
    dfPval.columns = [GeneSetName]
    dfCor.columns = [GeneSetName]

    return dfCor, dfPval, dfSetScore

###########################
##### Immunephenoscore ####
###########################

def ips_correlation(exprDf, lMirUser = None, n_core = 2):

    pandarallel.initialize(verbose=1, nb_workers=n_core)

    lMir, lGene = header_list(exprDF=exprDf)

    if lMirUser is not None:
        lMir = intersection(lMir,lMirUser)

    gene_ips = load_gene_ips()

    dfIPS = exprDf[lGene].parallel_apply(lambda x: \
                      ips(x, gene_ips), \
                      axis = 1)

    dfExpr = pd.concat((dfIPS,exprDf[lMir]), axis = 1)

    table, dfCor = all_methods(dfExpr, lMirUser = lMir, lGeneUser = ["AZ",], n_core = n_core, hr = False, k = 5, background = False, test = False, add_target = False)

    return table, dfCor, dfIPS

##################
## EdgeR       ###
##################

def differential_expression_edger(fPath, metaFile, bNormal = False, bFilter = False, paired = False, group = "event"):
    """
    Function to obtain the DEG between 2 groups
    with edgeR.

    Args:
        fPath string  Path with the raw counts
        metaFile  string  Path, the first Row is sample names, second is Group
        outPath string  File output
        bNormal Bool    Bool to normalize the data with TMM
        bFilter Bool    Bool to FIlter low expression genes

    Returns:
        df  dataframe   DataFrame with The LogFC, and pvalues for genes
    """
    DEG = deg_edger(fPath = fPath, metaFile = metaFile, bNormal = str(bNormal), \
        bFilter = str(bFilter), bPaired = str(paired), group = group)

    return DEG

def tmm_normal(fPath, bFilter=True):
    """
    Function to obtain the Voom normal Count

    Args:
        fPath string  Path with the raw counts
        outPath string  File output
        bFilter Bool    Bool to FIlter low expression genes

    Returns:
        tmm  dataframe   DataFrame with the log2(TMM) counts
    """
    tmm = tmm_normalization(fPath, str(bFilter))
    return tmm

##################
## Limma Array  ##
##################

def differential_expression_array(fPath, metaFile, bNormal = True, bFilter = True, paired = False):
    """
    Function to obtain the DEG between 2 groups
    with Limma.

    Args:
        fPath string  Path with the raw counts
        metaFile  string  Path, the first Row is sample names, second is Group
        outPath string  File output
        bNormal Bool    Bool to normalize the data with TMM
        bFilter Bool    Bool to FIlter low expression genes

    Returns:
        df  dataframe   DataFrame with The LogFC, and pvalues for genes
    """
    DEG = deg_limma_array(fPath, metaFile, str(bNormal), str(bFilter), str(paired))

    return DEG

def voom_normal(fPath, bFilter=True):
    """
    Function to obtain the Voom normal Count

    Args:
        fPath string  Path with the raw counts
        outPath string  File output
        bFilter Bool    Bool to FIlter low expression genes

    Returns:
        tmm  dataframe   DataFrame with the log2(TMM) counts
    """
    voom = voom_normalization(fPath, str(bFilter))
    return voom

##################
### sklearn ######
##################

def CoefLarsCV(x, y, n_core=4):
    """
    Compute the coefficients using the Least Angle Regression (LARS) Cross-Validation.

    Args:
        x (DataFrame): Features data.
        y (Series): Target variable.
        n_core (int): Number of CPU cores to use for parallel processing.

    Returns:
        coef (Series): Coefficients obtained from LARS CV.
    """

    # Split the data into training and testing sets
    X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=1)

    # Cross-validation with LARS
    larscv = LarsCV(cv=5)
    larscv.fit(X_train, y_train)

    # Get coefficients as a Series
    coef = pd.Series(larscv.coef_, index=x.columns)

    return coef

def CoefLassoCV(X, Y, k=3, n_core=4):
    """
    Compute the coefficients using Lasso with Cross-Validation.

    Args:
        X (DataFrame): Features data.
        Y (Series): Target variable.
        k (int): Number of folds for cross-validation.
        n_core (int): Number of CPU cores to use for parallel processing.

    Returns:
        coef (Series): Mean coefficients obtained from Lasso CV.
    """

    # Split data into k-folds for cross-validation
    skf = KFold(n_splits=k, shuffle=True)
    indexes = [(training, test) for training, test in skf.split(X, Y)]

    dfTopCoefTemp = pd.DataFrame(dtype='float64', index=X.columns).fillna(0)

    for train_index, test_index in indexes:
        X_train, X_test = X.iloc[train_index, :], X.iloc[test_index, :]
        y_train, y_test = Y[train_index], Y[test_index]

        # Cross-validation with Lasso
        lassocv = LassoCV(cv=5)
        lassocv.fit(X_train, y_train)
        lasso = Lasso(max_iter=1e4, alpha=lassocv.alpha_).fit(X_train, y_train)

        dfTopCoefTemp = pd.concat([dfTopCoefTemp, pd.Series(lasso.coef_, index=X.columns).fillna(0)], axis=1)

    # Compute the mean coefficients
    coef = dfTopCoefTemp.apply(lambda row: row.mean(), axis=1)

    return coef

def CoefLasso(x, y):
    """
    Compute the coefficients using Lasso.

    Args:
        x (DataFrame): Features data.
        y (Series): Target variable.

    Returns:
        coef (Series): Coefficients obtained from Lasso.
    """

    alphas = [0.001, 0.02, 0.01, 0.1, 0.5, 1, 5]

    # Lasso regression with a specific alpha
    lasso = Lasso(alpha=1).fit(x, y)

    # Get coefficients as a Series
    coef = pd.Series(lasso.coef_, index=x.columns)

    return coef

def CoefRandomForest(x, y, n_core=4):
    """
    Compute feature importances using Random Forest Regressor.

    Args:
        x (DataFrame): Features data.
        y (Series): Target variable.
        n_core (int): Number of CPU cores to use for parallel processing.

    Returns:
        coef (Series): Feature importances obtained from Random Forest.
    """

    # Split the data into training and testing sets
    X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=1)

    # Hyperparameter tuning with RandomizedSearchCV
    rf = RandomizedSearchCV(RandomForestRegressor(),
                           param_distributions={
                               'n_estimators': np.arange(10, 500, 5)
                           },
                           cv=5, n_iter=20,
                           iid=False, random_state=0, refit=True,
                           scoring="neg_mean_absolute_error", n_jobs=n_core)
    rf.fit(X_train, y_train)
    rf = rf.best_estimator_

    # Calculate feature importances
    importances = rf.feature_importances_

    # Create a Series of feature importances
    coef = pd.Series(importances, index=x.columns)

    return coef

def CoefElasticNetCV(X, Y, k=3, n_core=4):
    """
    Compute the coefficients using Elastic Net with Cross-Validation.

    Args:
        X (DataFrame): Features data.
        Y (Series): Target variable.
        k (int): Number of folds for cross-validation.
        n_core (int): Number of CPU cores to use for parallel processing.

    Returns:
        coef (Series): Mean coefficients obtained from Elastic Net CV.
    """

    alphas = [0.001, 0.02, 0.01, 0.1, 0.5, 1, 5]

    skf = KFold(n_splits=k, shuffle=True)
    indexes = [(training, test) for training, test in skf.split(X, Y)]

    dfTopCoefTemp = pd.DataFrame(dtype='float64', index=X.columns).fillna(0)

    for train_index, test_index in indexes:
        X_train, X_test = X.iloc[train_index, :], X.iloc[test_index, :]
        y_train, y_test = Y[train_index], Y[test_index]

        # Cross-validation with Elastic Net
        elasticcv = ElasticNetCV(alphas=alphas, cv=5)
        elasticcv.fit(X_train, y_train)
        elastic = ElasticNet(alpha=elasticcv.alpha_).fit(X_train, y_train)

        dfTopCoefTemp = pd.concat([dfTopCoefTemp, pd.Series(elastic.coef_, index=X.columns).fillna(0)], axis=1)

    # Compute the mean coefficients
    coef = dfTopCoefTemp.apply(lambda row: row.mean(), axis=1)

    return coef

def CoefRidgeCV(X, Y, k=3):
    """
    Compute the coefficients using Ridge with Cross-Validation.

    Args:
        X (DataFrame): Features data.
        Y (Series): Target variable.
        k (int): Number of folds for cross-validation.

    Returns:
        coef (Series): Mean coefficients obtained from Ridge CV.
    """

    alphas = np.logspace(-10, -2, 10)

    skf = KFold(n_splits=k, shuffle=True)
    indexes = [(training, test) for training, test in skf.split(X, Y)]

    dfTopCoefTemp = pd.DataFrame(dtype='float64', index=X.columns).fillna(0)

    for train_index, test_index in indexes:
        X_train, X_test = X.iloc[train_index, :], X.iloc[test_index, :]
        y_train, y_test = Y[train_index], Y[test_index]

        # Cross-validation with Ridge
        ridgecv = RidgeCV(alphas=alphas, cv=5)
        ridgecv.fit(X_train, y_train)
        ridge = Ridge(alpha=ridgecv.alpha_).fit(X_train, y_train)

        dfTopCoefTemp = pd.concat([dfTopCoefTemp, pd.Series(ridge.coef_, index=X.columns).fillna(0)], axis=1)

    # Compute the mean coefficients
    coef = dfTopCoefTemp.apply(lambda row: row.mean(), axis=1)

    return coef

def CoefRidge(x, y):
    """
    Compute the coefficients using Ridge.

    Args:
        x (DataFrame): Features data.
        y (Series): Target variable.

    Returns:
        coef (Series): Coefficients obtained from Ridge.
    """

    alphas = [0.001, 0.02, 0.01, 0.1, 0.5, 1, 5]

    # Split the data into training and testing sets
    X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=1)

    # Ridge regression with a specific alpha
    ridge6 = Ridge(alpha=0.01)
    ridge6.fit(X_train, y_train)

    # Get coefficients as a Series
    coef = pd.Series(ridge6.coef_, index=x.columns)

    return coef

##################
## Correlation ###
##################

def pearson(exprDF, lMirUser = None, lGeneUser = None, n_core = 2, pval = True):
    """
    Function to calculate the Pearson correlation coefficient, and pval
    of each pair of miRNA-mRNA, return a matrix of correlation coefficients
    with columns are miRNAs and rows are mRNAs.

    Args:
        exprDF  df Concat Dataframe rows are samples and cols are gene/mirs

    Returns:
        Cordf   df  A  matrix that includes the Pearson correlation
                        coefficients. Columns are genes, rows are miRNA.
        Pvaldf   df  A  matrix that includes the Pearson correlation
                        pvalues. Columns are genes, rows are miRNA.
    """
    pandarallel.initialize(verbose=1, nb_workers=n_core)

    lMir, lGene = header_list(exprDF=exprDF)

    if lGeneUser is not None:
        lGene = intersection(lGene,lGeneUser)

    if lMirUser is not None:
        lMir = intersection(lMir,lMirUser)

    Cordf = exprDF[lGene].parallel_apply(lambda gene: exprDF[lMir].corrwith(gene, \
            method = lambda x, y: scipy.stats.pearsonr(x,y)[0]))
    if pval:
        Pvaldf = exprDF[lGene].parallel_apply(lambda gene: exprDF[lMir].corrwith(gene, \
                method = lambda x, y: scipy.stats.pearsonr(x,y)[1]))
    else:
        Pvaldf = pd.DataFrame()

    Cordf = Cordf.apply(lambda col: col.dropna())
    Pvaldf = Pvaldf.apply(lambda col: col.dropna())

    return Cordf, Pvaldf

def spearman(exprDF, lMirUser = None, lGeneUser = None, n_core = 2):
    """
    Function to calculate the Spearman correlation coefficient, and pval
    of each pair of miRNA-mRNA, return a matrix of correlation coefficients
    with columns are miRNAs and rows are mRNAs.

    Args:
        exprDF  df Concat Dataframe rows are samples and cols are gene/mirs

    Returns:
        Cordf   df  A  matrix that includes the Spearman correlation
                        coefficients. Columns are genes, rows are miRNA.
        Pvaldf   df  A  matrix that includes the Spearman correlation
                        pvalues. Columns are genes, rows are miRNA.
    """
    pandarallel.initialize(verbose=1, nb_workers=n_core)

    lMir, lGene = header_list(exprDF=exprDF)

    if lGeneUser is not None:
        lGene = intersection(lGene,lGeneUser)

    if lMirUser is not None:
        lMir = intersection(lMir,lMirUser)

    Cordf = exprDF[lGene].parallel_apply(lambda gene: exprDF[lMir].corrwith(gene, \
            method = lambda x, y: scipy.stats.spearmanr(x,y)[0]))

    Pvaldf = exprDF[lGene].parallel_apply(lambda gene: exprDF[lMir].corrwith(gene, \
            method = lambda x, y: scipy.stats.spearmanr(x,y)[1]))

    Cordf = Cordf.apply(lambda col: col.dropna())
    Pvaldf = Pvaldf.apply(lambda col: col.dropna())

    return Cordf, Pvaldf

def kendall(exprDF, lMirUser = None, lGeneUser = None, n_core = 2):
    """
    Function to calculate the Kendall correlation coefficient, and pval
    of each pair of miRNA-mRNA, return a matrix of correlation coefficients
    with columns are miRNAs and rows are mRNAs.

    Args:
        exprDF  df Concat Dataframe rows are samples and cols are gene/mirs

    Returns:
        Cordf   df  A  matrix that includes the Kendall correlation
                        coefficients. Columns are genes, rows are miRNA.
        Pvaldf   df  A  matrix that includes the Kendall correlation
                        pvalues. Columns are genes, rows are miRNA.
    """

    pandarallel.initialize(verbose=1, nb_workers=n_core)

    lMir, lGene = header_list(exprDF=exprDF)

    if lGeneUser is not None:
        lGene = intersection(lGene,lGeneUser)

    if lMirUser is not None:
        lMir = intersection(lMir,lMirUser)

    Cordf = exprDF[lGene].parallel_apply(lambda gene: exprDF[lMir].corrwith(gene, \
            method = lambda x, y: scipy.stats.kendalltau(x,y)[0]))

    Pvaldf = exprDF[lGene].parallel_apply(lambda gene: exprDF[lMir].corrwith(gene, \
            method = lambda x, y: scipy.stats.kendalltau(x,y)[1]))

    Cordf = Cordf.apply(lambda col: col.dropna())
    Pvaldf = Pvaldf.apply(lambda col: col.dropna())

    return Cordf, Pvaldf

def lasso(exprDF, lMirUser = None, lGeneUser = None, n_core = 2):
    """
    Function to calculate the Lasso correlation coefficient
    of each pair of miRNA-mRNA, return a matrix of correlation coefficients
    with columns are miRNAs and rows are mRNAs.

    Args:
        exprDF  df Concat Dataframe rows are samples and cols are gene/mirs

    Returns:
        Cordf   df  A  matrix that includes the lasso correlation
                        coefficients. Columns are genes, rows are miRNA.
    """

    pandarallel.initialize(verbose=1, nb_workers=n_core)

    lMir, lGene = header_list(exprDF=exprDF)

    if lGeneUser is not None:
        lGene = intersection(lGene,lGeneUser)

    if lMirUser is not None:
        lMir = intersection(lMir,lMirUser)

    Cordf = exprDF[lGene].parallel_apply(lambda gene: \
            CoefLassoCV(exprDF[lMir], gene))

    Cordf = Cordf.apply(lambda col: col.dropna())

    return Cordf

def ridge (exprDF, lMirUser = None, lGeneUser = None, n_core = 2):
    """
    Function to calculate the Ridge correlation coefficient
    of each pair of miRNA-mRNA, return a matrix of correlation coefficients
    with columns are miRNAs and rows are mRNAs.

    Args:
        exprDF  df Concat Dataframe rows are samples and cols are gene/mirs

    Returns:
        Cordf   df  A  matrix that includes the Ridge correlation
                        coefficients. Columns are genes, rows are miRNA.
    """
    pandarallel.initialize(verbose=1, nb_workers=n_core)

    lMir, lGene = header_list(exprDF=exprDF)

    if lGeneUser is not None:
        lGene = intersection(lGene,lGeneUser)

    if lMirUser is not None:
        lMir = intersection(lMir,lMirUser)

    Cordf = exprDF[lGene].parallel_apply(lambda gene: \
            CoefRidgeCV(exprDF[lMir],gene))

    Cordf = Cordf.apply(lambda col: col.dropna())

    return Cordf

def elasticnet(exprDF, lMirUser = None, lGeneUser = None, n_core = 2):
    """
    Function to calculate the ElasticNet correlation coefficient
    of each pair of miRNA-mRNA, return a matrix of correlation coefficients
    with columns are miRNAs and rows are mRNAs.

    Args:
        exprDF  df Concat Dataframe rows are samples and cols are gene/mirs

    Returns:
        Cordf   df  A  matrix that includes the lasso correlation
                        coefficients. Columns are genes, rows are miRNA.
    """

    pandarallel.initialize(verbose=1, nb_workers=n_core)

    lMir, lGene = header_list(exprDF=exprDF)

    if lGeneUser is not None:
        lGene = intersection(lGene,lGeneUser)

    if lMirUser is not None:
        lMir = intersection(lMir,lMirUser)

    Cordf = exprDF[lGene].parallel_apply(lambda gene: \
            CoefElasticNetCV(exprDF[lMir],gene, n_core=n_core))

    Cordf = Cordf.apply(lambda col: col.dropna())

    return Cordf

def randomforest(exprDF, lMirUser = None, lGeneUser = None, n_core = 2):
    """
    Function to calculate the RandomForest Regression coefficient
    of each pair of miRNA-mRNA, return a matrix of correlation coefficients
    with columns are miRNAs and rows are mRNAs.

    Args:
        exprDF  df Concat Dataframe rows are samples and cols are gene/mirs

    Returns:
        Cordf   df  A  matrix that includes the lasso correlation
                        coefficients. Columns are genes, rows are miRNA.
    """

    pandarallel.initialize(verbose=1, nb_workers=n_core)

    lMir, lGene = header_list(exprDF=exprDF)

    if lGeneUser is not None:
        lGene = intersection(lGene,lGeneUser)

    if lMirUser is not None:
        lMir = intersection(lMir,lMirUser)

    Cordf = exprDF[lGene].parallel_apply(lambda gene: \
            CoefRandomForest(exprDF[lMir],gene))

    Cordf = Cordf.apply(lambda col: col.dropna())

    return Cordf

def lars(exprDF, lMirUser = None, lGeneUser = None, n_core = 2):
    """
    Function to calculate the RandomForest Regression coefficient
    of each pair of miRNA-mRNA, return a matrix of correlation coefficients
    with columns are miRNAs and rows are mRNAs.

    Args:
        exprDF  df Concat Dataframe rows are samples and cols are gene/mirs

    Returns:
        Cordf   df  A  matrix that includes the lasso correlation
                        coefficients. Columns are genes, rows are miRNA.
    """

    pandarallel.initialize(verbose=1, nb_workers=n_core)

    lMir, lGene = header_list(exprDF=exprDF)

    if lGeneUser is not None:
        lGene = intersection(lGene,lGeneUser)

    if lMirUser is not None:
        lMir = intersection(lMir,lMirUser)

    Cordf = exprDF[lGene].parallel_apply(lambda gene: \
            CoefLarsCV(exprDF[lMir],gene))

    Cordf = Cordf.apply(lambda col: col.dropna())

    return Cordf

def hoeffding (exprDF, lMirUser = None, lGeneUser = None, n_core = 2):
    """
    Function to calculate the hoeffding correlation coefficient
    of each pair of miRNA-mRNA, return a matrix of correlation coefficients
    with columns are miRNAs and rows are mRNAs.

    Args:
        exprDF  df Concat Dataframe rows are samples and cols are gene/mirs

    Returns:
        Cordf   df  A  matrix that includes the hoeffding correlation
                        coefficients. Columns are genes, rows are miRNA.

    Ref:
        https://github.com/PaulVanDev/HoeffdingD
    """

    from  .metrics import hoeffding

    pandarallel.initialize(verbose=1, nb_workers=n_core)

    lMir, lGene = header_list(exprDF=exprDF)

    if lGeneUser is not None:
        lGene = intersection(lGene,lGeneUser)

    if lMirUser is not None:
        lMir = intersection(lMir,lMirUser)

    Cordf = exprDF[lGene].parallel_apply(lambda gene: exprDF[lMir].corrwith(gene, \
            method = lambda x, y: hoeffding(x,y)))

    Cordf = Cordf.apply(lambda col: col.dropna())

    return Cordf

def rdc (exprDF, lMirUser = None, lGeneUser = None, n_core = 2):
    """
    Function to calculate the Randomized Dependence Coefficient coefficient
    of each pair of miRNA-mRNA, return a matrix of correlation coefficients
    with columns are miRNAs and rows are mRNAs.

    Args:
        exprDF  df Concat Dataframe rows are samples and cols are gene/mirs

    Returns:
        Cordf   df  A  matrix that includes the rdc correlation
                        coefficients. Columns are genes, rows are miRNA.

    Ref:
        https://github.com/garydoranjr/rdc
    """

    from .metrics import rdc

    pandarallel.initialize(verbose=1, nb_workers=n_core)

    lMir, lGene = header_list(exprDF=exprDF)

    if lGeneUser is not None:
        lGene = intersection(lGene,lGeneUser)

    if lMirUser is not None:
        lMir = intersection(lMir,lMirUser)

    Cordf = exprDF[lGene].parallel_apply(lambda gene: exprDF[lMir].corrwith(gene, \
            method = lambda x, y: rdc(x,y)))

    Cordf = Cordf.apply(lambda col: col.dropna())

    return Cordf

def hazard_ratio_mirgen(exprDF, table, lMirUser = None, lGeneUser = None, n_core = 2):
    """
    Function to calculate the Spearman correlation coefficient, and pval
    of each pair of miRNA-mRNA, return a matrix of correlation coefficients
    with columns are miRNAs and rows are mRNAs.

    Args:
        exprDF  df Concat Dataframe rows are samples and cols are gene/mirs

    Returns:
        Cordf   df  A  matrix that includes the Spearman correlation
                        coefficients. Columns are genes, rows are miRNA.
        Pvaldf   df  A  matrix that includes the Spearman correlation
                        pvalues. Columns are genes, rows are miRNA.
    """
    from .survival import hazard_ratio

    pandarallel.initialize(verbose=1, nb_workers=n_core)

    lMir, lGene = header_list(exprDF=exprDF)

    if lGeneUser is not None:
        lGene = intersection(lGene,lGeneUser)

    if lMirUser is not None:
        lMir = intersection(lMir,lMirUser)

    hr = hazard_ratio(exprDF=exprDF, lMirUser=lMir, lGeneUser=lGene, n_core = n_core)
    hr.index = hr.target

    table["HR_GENE"] = table.apply(lambda x: hr.loc[x["Gene"],"log(hr)"], axis = 1)
    table["HR_MIR"] = table.apply(lambda x: hr.loc[x["Mir"],"log(hr)"], axis = 1)

    return table

def filter_low_express_feature(exprDF, treshold = 5, sample_percentage = 0.4):
    """
    Function to filter the low expressed miRNA and mRNA.
    Args:
        exprDF  df Concat Dataframe rows are samples and cols are gene/mirs
        treshold int treshold of min number of reads
        sample_percentage float percentage of samples that have more than treshold reads
    Returns:
        dfExprs_filtered   df  A  matrix that includes the filtered expression matrix
    """
    # Set expression threshold and sample percentage for filtering
    threshold = np.log2(treshold)

    # Filter features with low expression in more than 90% of samples
    dfExprs_filtered = exprDF.loc[:, (exprDF > threshold).sum(axis=0) / exprDF.shape[0] >= sample_percentage]
    return dfExprs_filtered

def all_methods(exprDF, lMirUser = None, lGeneUser = None, n_core = 2, hr = False, k = 10, background = True, \
                test = False, add_target = True, filter_low_express = True):
    """
    Function to calculate all coefficient
    of each pair of miRNA-mRNA, return a matrix of correlation coefficients
    with columns are miRNAs and rows are mRNAs.

    Args:
        exprDF  df Concat Dataframe rows are samples and cols are gene/mirs

    Returns:

    """
    import copy

    if filter_low_express:
        exprDF = filter_low_express_feature(exprDF)

    lMir, lGene = header_list(exprDF=exprDF)

    if lGeneUser is not None:
        lGene = intersection(lGene,lGeneUser)

    if lMirUser is not None:
        lMir = intersection(lMir,lMirUser)

    print("Obtain Concat Gene and MIR")
    print("Number of genes: " + str(len(lGene)),flush=True)
    print("Number of miRNAs: " + str(len(lMir)),flush=True)
    print("Number of samples: " + str(exprDF.shape[0]),flush=True)
    print("Number of features: " + str(exprDF.shape[1]),flush=True)
    print(lMirUser,flush=True)
    print(exprDF.head(),flush=True)

    if test:
        modelList = [[spearman,"Rho"],
                    [pearson,"R"],
                    [kendall,"Tau"],
                    ]
    else:
        modelList = [[spearman,"Rho"],
                    [pearson,"R"],
                    [kendall,"Tau"],
                    [rdc, "RDC"],
                    [hoeffding,"Hoeffding"],
                    [ridge,"Ridge"],
                    [lasso,"Lasso"],
                    [elasticnet,"ElasticNet"],
                    # [hazard_ratio_mirgen, "Log(HR)" ]
                    ]

    print("Loading dataset...")

    lTuple = []
    for model, name in modelList :
        print("\nClassifier " + name)
        classifier = copy.deepcopy(model)
        try:
            if name in ["Rho", "R","Tau"]:
                dfCor, pval = classifier(exprDF, lGeneUser=lGene, lMirUser=lMir, n_core=n_core)
                lTuple.append((pval,"%s_Pval"%name))

            else:
                dfCor = classifier(exprDF, lGeneUser=lGene, lMirUser=lMir,n_core=n_core)
        except Exception as error:
            print(error)
            pass
        else:
            #dfCor.to_csv("~/%s.csv"%name)
            lTuple.append((dfCor,name))

    table = process_matrix_list(lTuple, add_target=add_target)

    table = table.loc[~table.duplicated(), :]

    if hr:
        print("\nHazard Ratio")
        table = hazard_ratio_mirgen(exprDF, table, lGeneUser=lGene, lMirUser=lMir, n_core=n_core)

    if background:
        print("\nBackground")
        table = background_estimation(exprDF, table, n_gene=3000, n_core=n_core, pval=False)

    table = adj_pval(table)

    return table, lTuple[1][0]

#################
### Background ##
#################
def process_zscore(lMir, table_random):
    lMean = []
    lStd = []
    for mir in lMir:
        x = table_random.loc[table_random.Mir == mir,:].R.tolist()
        try:
            mean = np.mean(x)
            standard_deviation = np.std(x)
        except:
            mean = np.nan
            standard_deviation = np.nan
        finally:
            lMean.append(mean)
            lStd.append(standard_deviation)

    df = pd.DataFrame({"Mir":lMir,"Mean":lMean,"Standard Deviation":lStd})

    return df

def get_mean_deviation(table_random, n_core = 4):
    import functools
    from multiprocessing import Pool

    ### Intersect with Gene and Mir from table##
    lMir = table_random.Mir.unique().tolist()

    ##Split List
    np_list_split = np.array_split(lMir, n_core)
    split_list = [i.tolist() for i in np_list_split]
    #split_list = same_length(split_list)

    #Fix Exprs Variable
    partial_func = functools.partial(process_zscore, table_random=table_random)

    #Generating Pool
    pool = Pool(n_core)
    lres = pool.map(partial_func, split_list)
    res = pd.concat(lres)
    pool.close()
    pool.join()
    return res

def z_score(value, mean, std):
    return (value - mean) / std

def background_estimation(exprDF, table, n_gene = 3000, method = "R", n_core = 6, pval = False):
    """
    Function to calculate the Pearson correlation coefficient, and pval
    of each pair of miRNA-mRNA, return a matrix of correlation coefficients
    with columns are miRNAs and rows are mRNAs.

    Args:
        exprDF  df Concat Dataframe rows are samples and cols are gene/mirs

    Returns:
        Cordf   df  A  matrix that includes the Pearson correlation
                        coefficients. Columns are genes, rows are miRNA.
        Pvaldf   df  A  matrix that includes the Pearson correlation
                        pvalues. Columns are genes, rows are miRNA.
    """
    import random
    from pandarallel import pandarallel
    pandarallel.initialize(verbose=1, nb_workers=n_core)

    lMir, lGene = header_list(exprDF=exprDF)

    #Select Random Genes for correlation
    random.seed(10)
    lGene = random.sample(lGene, n_gene)

    dfCor, dfPval = pearson(exprDF, lGeneUser = lGene, n_core = n_core, pval = pval)

    ## Get table with number
    table_random = process_matrix_list([(dfCor,"R")], add_target=True)
    table_random["Number"] = table_random["Prediction Tools"].str.count("1")
    table_filter = table_random.loc[table_random["Number"] <= 1,:]

    #Get Mean and Std
    res = get_mean_deviation(table_filter)
    res.index = res.Mir

    #Get Z-score, and P-value
    res_z_p = table.parallel_apply(lambda row: \
                              z_score_value(row.R, res, row.Mir), axis = 1)
    #print(res_z_p)
    #res_z_p = res_z_p.apply(lambda col: col.dropna())
    table["Background Z-Score"] = res_z_p.apply(lambda x: x[0])
    table["Background_Pval"] = res_z_p.apply(lambda x: x[1])

    return table

def z_score_value(x, res, mir):
    from scipy.stats import norm

    try:
        z = z_score(x, res.loc[mir,"Mean"], res.loc[mir,"Standard Deviation"])
        p_value = norm.cdf(x=x,loc=res.loc[mir,"Mean"],scale=res.loc[mir,"Standard Deviation"])
    except:
        z, p_value = 0, 1
    return z, p_value

#################
### Reshaping ###
#################

def matrix2table(Cordf, value_name = "Value"):
    """
    Function to reshaping a correlation matrix where Columns are genes,
    rows are miRNA to Table.

    Args:
        Cordf   df  A  matrix that includes the correlation
                        coefficients. Columns are genes, rows are miRNA.

    Returns:
        Table   df  A  matrix that includes 3 col: gene, mir and value

    Ref:
        https://pandas.pydata.org/docs/user_guide/reshaping.html
    """

    table = Cordf.melt(ignore_index=False)
    #table["Mir"] = table.index.tolist()
    #table = table.loc[["Mir", "Gene", "Value"],:]
    table = table.reset_index()
    table.columns = ["Mir","Gene", value_name]

    return table

def merge_tables(lDf, method = "inner"):
    """
    Function to concat the correlations Tables.

    Args:
        lDf   list  List of DFs with the correlation data

    Returns:
        df   df  A concat df

    Ref:
        https://stackoverflow.com/questions/23668427/pandas-three-way-joining-multiple-dataframes-on-columns
    """
    from functools import reduce

    df = reduce(lambda left, right: pd.merge(left,right,on=['Gene','Mir'], how = method), lDf)

    return df

def process_matrix_list(lTuple, add_target=True, method = "outer"):
    """
    Function to reshape a list of correlation matrix
    in the correlations Tables.

    Args:
        lTuple   list  List of tuples with the correlation matrix, an the
                        name of the analysis (df,"value_name")

    Returns:
        table   df  A table with al the values merged
    """
    lDf = []
    if add_target:
        df = lTuple[0][0]
        target = load_matrix_counts()

        lGen = intersection(df.columns.tolist(), target.index.tolist() )
        lMir = intersection(df.index.tolist(), target.columns.tolist() )

        target = target.loc[lGen,lMir].transpose()
        lTuple.append((target, "Prediction Tools"))

    for tuple in lTuple:
        df = matrix2table(tuple[0], tuple[1])
        lDf.append(df)

    table = merge_tables(lDf, method = method)

    return table

def filter_table(table, low_coef = -0.2, high_coef = 0.2, nDB = 3, pval = 0.05):
    query_string = f"""
                ((R <= {low_coef} | R >= {high_coef} ) | \
                 (Rho <= {low_coef} | Rho >= {high_coef} ) | \
                 (Tau <= {low_coef} | Tau >= {high_coef} ))  \
                & (Tool Number >= {nDB}) & \
                ((Spear_fdr_bh <= {pval}) | \
                 (Pear_fdr_bh <= {pval}) | \
                 (Kendall_fdr_bh <= {pval}))
                 """
    table = table.query(query_string)
    return table

def _mir_gene_ratio(mir, gene, df):
        name = "%s/%s"%(mir.name,gene.name)
        df[name] = pd.Series(mir/gene)
        return None

def get_mir_gene_ratio(exprDF, lMirUser = None, lGeneUser = None,  filter_pair = False, low_coef = -0.5, min_db = 20):
    """
    Function to calculate all coefficient
    of each pair of miRNA-mRNA, return a matrix of correlation coefficients
    with columns are miRNAs and rows are mRNAs.

    Args:
        exprDF  df Concat Dataframe rows are samples and cols are gene/mirs

    Returns:

    """

    lMir, lGene = header_list(exprDF=exprDF)

    if lGeneUser is not None:
        lGene = intersection(lGene,lGeneUser)

    if lMirUser is not None:
        lMir = intersection(lMir,lMirUser)

    df = pd.DataFrame()

    if filter_pair:
        dfCor, pval = pearson(exprDF, lGeneUser=lGene, lMirUser=lMir, n_core=6)
        table = process_matrix_list([(dfCor,"R")], add_target=True)
        table = table.loc[table["R"] <= low_coef, :]
        table = table.loc[table["Prediction Tools"].str.count("1") > min_db,:]

    exprDF[lGene].apply(lambda gene:
                            exprDF[lMir].apply(lambda mir:
                                 _mir_gene_ratio(mir, gene, df)))

    lKeep = table.apply(lambda row: "%s/%s"%(row["Mir"],row["Gene"]), axis = 1)
    df = df[lKeep]
    return df

#################
### Sorting   ###
#################

def obtain_top_matrix(Cordf, topk=100, value_name = "Value"):
    """
    Function to obtain the top X miRNAs-mRNA interactions
    from corr matrix.

    Args:

    Returns:

    """

    table = matrix2table(Cordf, value_name)
    top = obtain_top_table(table, topk, value_name)

    return top

def obtain_top_table(table, topk=100, value_name=None):
    """
    Function to obtain the top X miRNAs-mRNA interactions
    from corr matrix.

    Args:

    Returns:

    """
    table = table.dropna()

    if value_name is None:
        table = table.reindex(table[table.columns.tolist()[2]].abs().sort_values(ascending=False).index)

    else:

        table = table.reindex(table[value_name].abs().sort_values(ascending=False).index)

    toprank = table.head(topk)

    return toprank

def borda_table(table, lMethod = None):
    """
    Function to use the Borda count election
    to integrate the rankings from different miRNA
    coefficients.

    Args:
        table   df  A table with al the values merged
        lMethod     list    List of the columns to rank

    Returns:
        TableRank   df  A table with al the values merged and ranking
    """

    TableRank = table

    if lMethod == None:
        lMethod = GetMethodList(table.columns.tolist())

    TableRank.loc[:,"Ranking"] = rk.borda(TableRank[lMethod].abs(), reverse=False)
    TableRank.loc[:,"Ranking"] = TableRank["Ranking"].round(0)
    return TableRank.sort_values("Ranking", ignore_index = True).round(3)

def borda_matrix(lTuple):
    """
    Function to use the Borda count election
    to integrate the rankings from different miRNA
    coefficients.

    Args:
        lTuple   list  List of tuples with the correlation matrix, an the
                        name of the analysis (df,"value_name")

    Returns:
        TableRank   df  A table with al the values merged and ranking
    """

    lDf = []

    for tuple in lTuple:
        df = matrix2table(tuple[0], tuple[1])
        lDf.append(df)

    TableRank = merge_tables(lDf)

    TableRank = borda_table(TableRank)

    return TableRank

def borda_top_matrix(lTuple, topk=100):
    """
    Function to obtain the the consensus ranking from the TopK
    pair miRNA-mRNA for each correlation method. We only keep
    the pairs present in all the top

    Args:
        table   df  A table with al the values merged
        lMethod     list    List of the columns to rank

    Returns:
        TableRank   df  A table with al the values merged and ranking

    """

    lDf = []

    for tuple in lTuple:
        df = obtain_top_matrix(tuple[0], value_name = tuple[1], topk = topk)
        lDf.append(df)

    TableRank = merge_tables(lDf, method = "outer")

    TableRank = borda_table(TableRank)

    return TableRank

def borda_top_table(table, topk=100, only_negative = False, method = "outer"):
    """
    Function to obtain the the consensus ranking from the TopK
    pair miRNA-mRNA for each correlation method. We only keep
    the pairs present in all the top

    Args:
        lTuple   list  List of tuples with the correlation matrix, an the
                        name of the analysis (df,"value_name")

    Returns:
        TableRank   df  A table with al the values merged and ranking

    """
    lMethod = GetMethodList(table.columns.tolist())

    lDf = []

    if only_negative:
        for m in lMethod:
            if m != "RDC" and m != "Hoeffding":
                table = table[table[m] <= 0]

        #Table = Table[Table["DB"]!="00000000000000000000000"]

    for m in lMethod:
        df = obtain_top_table(table[["Mir","Gene",m]], topk=topk, value_name=m)
        lDf.append(df)

    TableRank = merge_tables(lDf,  method = method)

    TableRank = borda_table(TableRank)
    TableRank = merge_tables([TableRank, table[["Mir","Gene","Prediction Tools"]]], method="inner")

    return TableRank.sort_values("Ranking", ignore_index = True)

def opposite_correlation(Table1, Table2, method="R"):

    keepCol = ["Gene","Mir",method]
    mergeTable = merge_tables([Table1[keepCol],Table2[keepCol]])
    mergeTable["Anti"] = mergeTable["%s_x"%method] * mergeTable["%s_y"%method]

    mergeTable = mergeTable[(mergeTable["Anti"] < 0)].sort_values("Anti",ignore_index=True)

    return mergeTable

def predict_lethality(gene, table, topk=100, method = "outer"):
    ##Get Methods##
    lMethod = GetMethodList(table.columns.tolist())
    slDF = load_synthetic()

    gene_list = slDF[(slDF["GeneA"]== gene)]["GeneB"].tolist()

    match = table[table["Gene"].str.contains("|".join(gene_list))]

    topmatch = borda_top_table(match, topk=topk, method = method )

    #topmatch = merge_tables([topmatch, table[["Mir","Gene","DB"]]], method="inner")

    return topmatch

def FilterDF(table = None, matrix = None, join = "or", lTool = [], low_coef = -0.5, high_coef = 0.5, pval = 0.05, analysis = "Correlation", min_db = 1, method = "R"):

    dbQ = get_target_query(join, lTool)
    #print(dbQ)

    #Filter DF
    if analysis == "Correlation":
        if method in ["R","Rho","Tau"]:
            query_string = f"""
                    (({method} <= {low_coef} | {method} >= {high_coef} )) \
                    & \
                    (({method}_fdr_bh <= {pval}))
            """
        else:
            query_string = f"""
                    (({method} <= {low_coef} | {method} >= {high_coef} ))
                    """

        table = table[table["Prediction Tools"].str.match(dbQ)==True]
        table["Number Prediction Tools"] = table["Prediction Tools"].str.count("1")
        table = table[table["Number Prediction Tools"] >= min_db]

    elif analysis == "GeneSetScore":
        query_string = f"""
                ((R <= {low_coef} | R >= {high_coef} ) \
                &  (FDR <= {pval}))
        """
    else:
        if method in ["R","Rho","Tau"]:
            query_string = f"""
                    (({method} < {low_coef} | {method} > {high_coef} )) \
                    & \
                    (({method}_fdr_bh < {pval}))
            """
        else:
            query_string = f"""
                    (({method} < {low_coef} | {method} > {high_coef} ))
                    """

    table = table.query(query_string)#Query the Correlation Table
    table = borda_table(table)
    #print("Filtrado")
    #print(table.head())

    gene = table["Gene"].unique().tolist()#Obtain Unique Gene after filter the table
    mir = table["Mir"].unique().tolist()#Obtain Unique mir after filter the table

    if matrix is not None:
        try:
            matrix = matrix.loc[mir,gene]#Subset the Correlation matrix to the heatmap
        except:
            try:
                matrix = matrix.loc[gene,mir]#Subset the Correlation matrix to the heatmap
            except:
                matrix = None

        return table, matrix
    else:
        matrix = None
        return table, matrix

def predict_target(table = None, matrix = None, lTarget = None, lTools = None, method = "or", min_db = 10, low_coef = -0.5, high_coef = 0.5, pval = 0.05):

    lTools = lTools if lTools != None else load_matrix_header()

    if len(lTarget) > 0:
        if table is not None:
            #print("Holi")
            if matrix is not None:
                table, matrix = FilterDF(table = table, matrix = matrix, join = method, lTool = lTools, \
                    low_coef = low_coef, high_coef = high_coef, pval = pval)
            else:
                table = FilterDF(table = table, matrix = matrix, join = method, lTool = lTools, \
                    low_coef = low_coef, high_coef = high_coef, pval = pval)
        else:
            table = load_table_counts()
            dbQ = get_target_query(method, lTools)
            table = table[table["Prediction Tools"].str.match(dbQ)==True]
                #Read DF

        #Obtain Target Table
        target = table[table["Gene"].isin(lTarget)|table["Mir"].isin(lTarget)]
        del table
        #Filter by number
        target["Number Prediction Tools"] = target["Prediction Tools"].str.count("1")
        target = target[target["Number Prediction Tools"] >= min_db]

        if not target.empty and matrix is not None:
            gene = target["Gene"].unique().tolist()#Obtain Unique Gene after filter the table
            mir = target["Mir"].unique().tolist()#Obtain Unique mir after filter the table

            try:
                matrix = matrix.loc[mir,gene]#Subset the Correlation matrix to the heatmap
            except:
                matrix = matrix.loc[gene,mir]#Subset the Correlation matrix to the heatmap
        else:
            matrix = None

    else:
        target, matrix = None, None
    return target, matrix

def ora_mir(lGene, matrix, mir_name, q):
    from scipy.stats import fisher_exact

    total_number_gene_universe = len(set(matrix.index.tolist()))
    total_number_gene_list = len(set(lGene))
    target_gene_list = matrix.loc[matrix[mir_name].str.count("1") >= q, mir_name].index.tolist()
    target_number_universe = len(set(target_gene_list))
    target_number_list = len(set(lGene).intersection(set(target_gene_list)))

    in_list, not_list = target_number_list, total_number_gene_list - target_number_list
    in_universe, not_universe = target_number_universe, total_number_gene_universe - target_number_universe

    data = {"List":[in_list, not_list], "Universe": [in_universe, not_universe]}
    res = pd.DataFrame.from_dict(data)

    odd, pval = fisher_exact(res)

    expected = (in_universe / total_number_gene_universe) * total_number_gene_list

    return pd.Series([mir_name, target_number_list, expected, odd, pval], \
                     index = ["microRNA","Target Number","Expected Number", "Fold Enrichment", "Raw P-value"], name = mir_name)

def ora_mir_list(lMir, lGene, matrix, minDB):
    df = pd.DataFrame()
    for mir in lMir:
        res = ora_mir(lGene, matrix, mir, minDB)
        df = pd.concat([df,res], axis = 1)
    return df

def ora_mir_parallel(lGene, matrix, lMir, minDB, n_core = 2):

    ##Split List
    np_list_split = np.array_split(lMir, n_core)
    split_list = [i.tolist() for i in np_list_split]
    #split_list = same_length(split_list)

    #Fix Exprs Variable
    partial_func = functools.partial(ora_mir_list, matrix = matrix, lGene = lGene,  minDB=minDB)

    #Generating Pool
    pool = Pool(n_core)
    lres = pool.map(partial_func, split_list)
    res = pd.concat(lres, axis = 1)
    res = res.transpose()
    pool.close()
    pool.join()

    res["FDR"] = multipletests(res["Raw P-value"], method = "fdr_bh")[1]
    return res

def predict_lethality2(table = None, matrix = None, lQuery = None, lTools = None, method = "or", min_db = 10, low_coef = -0.5, high_coef = 0.5, pval = 0.05):
    ##Get Methods##
    import pandas as pd

    slDF = load_synthetic()

    qA = slDF.loc[slDF["GeneA"].isin(lQuery),:]
    qA.columns = ["Query", "Synthetic Lethal"]
    qB = slDF.loc[slDF["GeneB"].isin(lQuery),:]
    qB.columns = ["Synthetic Lethal","Query"]

    qSl = pd.concat([qA,qB])
    lTarget = qSl["Synthetic Lethal"].tolist()

    if len(lTarget) > 0:
        target,matrix = predict_target(table = table, matrix = matrix, lTarget = lTarget, lTools = lTools, method = method, min_db = min_db, low_coef = low_coef, high_coef = high_coef, pval = pval)
        target = pd.merge(qSl,target, left_on="Synthetic Lethal", right_on="Gene")

        res = ora_mir_parallel(lTarget, load_matrix_counts(), target["Mir"].unique().tolist(), min_db)
    else:
        target = None

    return target, matrix, res


#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Created on Thu Jan 18 15:52:21 2018

@author: imad
"""
import xml.etree.ElementTree as ET
import ConfigParser

###############################################################################

def init():

    config = ConfigParser.RawConfigParser()
    config.read('general_config.cfg')

    tasks_indices = [int(x) for x in config.get('Mapping', 'tasks_indices').split(',')]
    x = [int(x) for x in config.get('Mesh', 'x').split(',')]
    y = [int(y) for y in config.get('Mesh', 'y').split(',')]

    num_resources = 0
    for i in range(0, len(x)):
        num_resources += x[i] * y[i]

    return num_resources, tasks_indices

###############################################################################

num_resources, tasks_indices = init()                                               # Initialize the script

data = ET.Element('mapping')                                                        # Create the file structure
data.set('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance')
data.set('xsi:noNamespaceSchemaLocation', 'ApplicationMapping.xsd')

for i in range(0, num_resources):

    resource = ET.SubElement(data, 'resource')
    resource.set('id', str(i))

    if(i in tasks_indices):                                                         # Adding the task as a child to the resources
        task = ET.SubElement(resource, 'Task')
        task.set('id', str(tasks_indices.index(i)))

mydata = ET.tostring(data)                                                          # Create a new XML file with the results
mapping_file = open(str(num_resources) + "_Mapping.xml", "w")
mapping_file.write(mydata)
mapping_file.close()


def suma_submatrice(matrice, coordonate_matrice):
    """
    determina suma submatricii matricii matrice determinata de coordonatele din lista coordonate
    :param matrice: matricea pe care se opereaza
    :param coordonate_matrice: lista cu perechi de perechi de numere intregi ce reprezinta coordonatele submatricelor
    :return: lista de intregi ce reprezinta sumele cautate
    """
    rows = len(matrice) + 1
    columns = len(matrice[0]) + 1
    matrice_aux = []
    for i in range(0, columns):
        matrice_aux.append([0] * rows)
    for i in range(1, rows):
        for j in range(1, columns):
            matrice_aux[i][j] = matrice_aux[i - 1][j] + matrice_aux[i][j - 1] - matrice_aux[i - 1][j - 1] + \
                                matrice[i - 1][j - 1]
    to_return = []
    for coordonate in coordonate_matrice:
        ax = coordonate[0][0]
        ay = coordonate[0][1]
        bx = coordonate[1][0] + 1
        by = coordonate[1][1] + 1
        suma = matrice_aux[bx][by] - matrice_aux[bx][ay] - matrice_aux[ax][by] + matrice_aux[ax][ay]
        to_return.append(suma)
    return to_return

def testing():
    mat = [[0, 2, 5, 4, 1], [4, 8, 2, 3, 7], [6, 3, 4, 6, 2], [7, 3, 1, 8, 3], [1, 5, 7, 9, 4]]
    rez = suma_submatrice(mat, [((1, 1), (3, 3)), ((2, 2), (4, 4))])
    assert rez[0] == 38
    assert rez[1] == 44
    rez = suma_submatrice(mat, [((1, 1), (3, 3)), ((0, 1), (0, 1)), ((2, 2), (4, 4))])
    assert rez[0] == 38
    assert rez[1] == 2
    assert rez[2] == 44
    rez = suma_submatrice(mat, [((0, 0), (3, 3)), ((0, 1), (0, 2)), ((2, 3), (3, 4))])
    assert rez[0] == 66
    assert rez[1] == 7
    assert rez[2] == 19

def main():
    testing()

main()


from tkinter import *
from tkinter import filedialog
from pathlib import Path
from os.path import join
from PIL import Image, ImageTk

# root = Tk()
# root.geometry("+0+0")

def open_img():
    global img_tk # to ensure that img can be shown and not be thrown to garbage collector.

    init_dir = join(Path.home(), "Pictures")
    file_type_tups = (
        ("jpg image files", "*.jpg"),
        ("jpeg image files", "*.jpeg"),
        ("png image files", "*.png"),
        ("all files", "*.*")
    )

    top = Toplevel()
    top.withdraw() # hide the window
    top.geometry("+0+0")
    top.title("Image")

    top.filename = filedialog.askopenfilename(
        initialdir=init_dir,
        title="Select A Image File",
        filetypes=file_type_tups
    )

    img = Image.open(top.filename)
    img.thumbnail((1280, 720))
    img_tk = ImageTk.PhotoImage(img)
    img_label = Label(
        top,
        image=img_tk
    )
    img_label.pack()

    top.deiconify() # unhide/show again the window
    top.attributes('-topmost',True) # to stay the window on top of other windows

# btn = Button(
#     root,
#     text="Open Image",
#     command=open_img
# )
# btn.pack()

# root.mainloop()


#from django.contrib.gis.db import models
from django.db import models
from django.db.models import Q
from django.template.defaultfilters import slugify

from bios.models import Bio
from organizations.models import Confederation

from collections import defaultdict

"""
class WorldBorder(models.Model):
    # Regular Django fields corresponding to the attributes in the
    # world borders shapefile.
    name = models.CharField(max_length=50)
    area = models.IntegerField()
    pop2005 = models.IntegerField('Population 2005')
    fips = models.CharField('FIPS Code', max_length=2)
    iso2 = models.CharField('2 Digit ISO', max_length=2)
    iso3 = models.CharField('3 Digit ISO', max_length=3)
    un = models.IntegerField('United Nations Code')
    region = models.IntegerField('Region Code')
    subregion = models.IntegerField('Sub-Region Code')
    lon = models.FloatField()
    lat = models.FloatField()

    # GeoDjango-specific: a geometry field (MultiPolygonField), and
    # overriding the default manager with a GeoManager instance.
    mpoly = models.MultiPolygonField()
    objects = models.GeoManager()

    # Returns the string representation of the model.
    def __str__(self):
        return self.name

"""

class CountryManager(models.Manager):

    def find(self, s):

        try:
            return Country.objects.get(name=s)
        except:
            return Country.objects.create(name=s)

    def country_dict(self):
        """
        A dict mapping a team's name and short name to an id.
        """
        d = {}
        for e in self.get_queryset():
            d[e.name] = e.id
        return d

    def id_dict(self):
        """
        A dict mapping a team's name and short name to an id.
        """
        d = {}
        for e in self.get_queryset():
            d[e.id] = e.name
        return d

class Country(models.Model):
    name = models.CharField(max_length=255)
    slug = models.SlugField()

    #population = models.IntegerField(null=True)
    code = models.CharField(max_length=15)

    #confederation = models.CharField(max_length=15)
    confederation = models.ForeignKey(Confederation)

    subconfederation = models.CharField(max_length=15)

    objects = CountryManager()

    def __str__(self):
        return self.name

    def games(self):
        from games.models import Game
        query = Q(city__country=self) | Q(country=self)
        return Game.objects.filter(query)

    class Meta:
        ordering = ('name',)

class StateManager(models.Manager):

    def find(self, state, country):
        try:
            return State.objects.get(name=state, country=country)
        except:
            return State.objects.create(name=state, country=country)

class State(models.Model):
    name = models.CharField(max_length=255)
    slug = models.SlugField()
    abbreviation = models.CharField(max_length=5)
    country = models.ForeignKey(Country, null=True, blank=True)
    joined = models.DateField(null=True)

    objects = StateManager()

    def __str__(self):
        return self.name
        #return "%s, %s" % (self.name, self.country)

    class Meta:
        ordering = ('name',)

class StatePopulation(models.Model):

    state = models.ForeignKey(State)
    year = models.IntegerField()
    population = models.IntegerField(null=True)

class CityManager(models.Manager):

    def duplicate_slugs(self):
        """
        Returns all teams with duplicate slugs.
        """
        # Used to find problem teams.
        d = defaultdict(list)
        for e in self.get_queryset():
            d[e.slug].append(e.name)
        return [(k, v) for (k, v) in d.items() if len(v) > 1]

class City(models.Model):
    name = models.CharField(max_length=255)
    state = models.ForeignKey(State, null=True, blank=True)
    country = models.ForeignKey(Country, null=True, blank=True)
    slug = models.SlugField(max_length=100)

    #geometry = models.PointField(srid=4326)

    objects = CityManager()

    def __str__(self):
        if self.state:
            return "%s, %s" % (self.name, self.state.abbreviation)
        elif self.country:
            return "%s, %s" % (self.name, self.country.name)
        else:
            return self.name

    class Meta:
        ordering = ('name',)

class StadiumManager(models.Manager):

    def as_dict(self):
        """
        Dict mapping names to stadium id's.
        """
        d = {}
        for e in self.get_queryset():
            d[e.name] = e.id
        return d

    def find(self, name, create=True):
        """
        Given a team name, determine the actual team.
        """
        # Not here?
        if name == '':
            import pdb; pdb.set_trace()

        stadiums = Stadium.objects.filter(name=name)
        if stadiums:
            return stadiums[0]
        else:
            slug = slugify(name)
            return Stadium.objects.create(name=name, slug=slug)

class Stadium(models.Model):
    name = models.CharField(max_length=255)
    slug = models.SlugField(unique=False, max_length=100)

    short_name = models.CharField(max_length=255)

    address = models.CharField(max_length=255)
    location = models.CharField(max_length=255)

    city = models.ForeignKey(City, null=True, blank=True)
    #location = models.PointField()

    opened = models.DateField(null=True)
    year_opened = models.IntegerField(null=True)

    closed = models.DateField(null=True)
    year_closed = models.IntegerField(null=True)

    architect = models.ForeignKey(Bio, null=True)

    capacity = models.IntegerField(null=True)

    width = models.CharField(max_length=255)
    length = models.CharField(max_length=255)
    measure = models.CharField(max_length=255)

    cost = models.DecimalField(max_digits=31, decimal_places=2, null=True)
    denomination = models.CharField(max_length=255)

    notes = models.CharField(max_length=255)

    objects = StadiumManager()

    def __str__(self):
        return self.name

    def open_string(self):
        if self.opened:
            return self.opened

        elif self.year_opened:
            return self.year_opened

        else:
            return None

    def goal_count(self):
        scores = self.game_set.values_list('team1_score', 'team2_score')
        game_score_totals = [sum([a or 0, b or 0]) for (a, b) in scores]
        return sum(game_score_totals)

    def close_string(self):
        if self.closed:
            return self.closed

        elif self.year_closed:
            return self.year_closed

        else:
            return None

    class Meta:
        ordering = ('name',)

class StadiumMap(models.Model):

    stadium = models.ForeignKey('places.Stadium')
    team = models.ForeignKey('teams.Team')

    start = models.DateField()
    end = models.DateField()


#!/usr/bin/env/python3
import setuptools

with open("README.md", encoding="utf-8") as fh:
    long_description = fh.read()

setuptools.setup(
    name="Amazon DenseClus",
    version="0.0.19",
    author="Charles Frenzel",
    description="Dense Clustering for Mixed Data Types",
    long_description=long_description,
    long_description_content_type="text/markdown",
    url="https://github.com/awslabs/amazon-denseclus",
    packages=setuptools.find_packages(),
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    python_requires=">=3.7",
    license_files=("LICENSE",),
    install_requires=[
        "umap_learn>=0.5.1",
        "numpy>=1.20.2",
        "hdbscan>=0.8.27",
        "numba>=0.51.2",
        "pandas>=1.2.4",
        "scikit_learn>=0.24.2",
    ],
)


import gpu
import bgl

from gpu_extras.batch import batch_for_shader

class BL_UI_Widget:

    def __init__(self, x, y, width, height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.bg_color = (0.8, 0.8, 0.8, 1.0)
        self.update(x, y)

    def set_bg_color(self, color):
        self.bg_color = color

    def draw(self):
        self.shader.bind()
        self.shader.uniform_float("color", self.bg_color)

        bgl.glEnable(bgl.GL_BLEND)
        self.batch_panel.draw(self.shader)
        bgl.glDisable(bgl.GL_BLEND)

    def update(self, x, y):

        self.x_screen = x
        self.y_screen = y

        indices = ((0, 1, 2), (0, 2, 3))

        # bottom left, top left, top right, bottom right
        vertices = (
                    (self.x_screen, self.y_screen),
                    (self.x_screen, self.y_screen + self.height),
                    (self.x_screen + self.width, self.y_screen + self.height),
                    (self.x_screen + self.width, self.y_screen))

        self.shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR')
        self.batch_panel = batch_for_shader(self.shader, 'TRIS', {"pos" : vertices}, indices=indices)

    def handle_event(self, event):
        if(event.type == 'LEFTMOUSE'):
            if(event.value == 'PRESS'):
                return self.mouse_down(event.mouse_region_x, event.mouse_region_y)
            else:
                self.mouse_up(event.mouse_region_x, event.mouse_region_y)

        elif(event.type == 'MOUSEMOVE'):
            self.mouse_move(event.mouse_region_x, event.mouse_region_y)
            return False

        return False

    def is_in_rect(self, x, y):

        if (
            (self.x_screen <= x <= (self.x_screen + self.width)) and
            (self.y_screen <= y <= (self.y_screen + self.height))
            ):
            return True

        return False

    def mouse_down(self, x, y):
        return self.is_in_rect(x,y)

    def mouse_move(self, x, y):
        pass

    def mouse_up(self, x, y):
        pass


import os, sys
import numpy as np

import torch
import torchvision.transforms as transforms
from torchvision.utils import save_image
from torch.autograd import Variable

from args import args
from dataset import AnimeDataset
from torch.utils.data import DataLoader

from network import LCMFTNGenerator, EI, VGGDiscriminator
from utils import weights_init_normal
from utils import LambdaLR

from tqdm import tqdm

import wandb
wandb.init(project="LCMFTN")

DEVICE = 0

generator = LCMFTNGenerator(args).to(DEVICE)
feature_extractor = EI(nc_in=1).to(DEVICE)
discriminator = VGGDiscriminator().to(DEVICE)

feature_extractor.eval()
discriminator.eval()

generator.apply(weights_init_normal)

criterion_color = torch.nn.L1Loss()
criterion_MSE = torch.nn.MSELoss()

optimizer_G = torch.optim.Adam(generator.parameters(), lr=args.lr, betas=(0.5, 0.9))
lr_scheduler_G = torch.optim.lr_scheduler.LambdaLR(optimizer_G, lr_lambda=LambdaLR(args.end_epoch, args.start_epoch, args.decay_epoch).step)

Tensor = torch.cuda.FloatTensor
Input_C = Tensor(args.batch_size, args.c_channel, args.input_height, args.input_width)
Input_S = Tensor(args.batch_size, args.s_channel, args.input_height, args.input_width)

trans = [transforms.ToPILImage(),
         transforms.Resize(size=(args.input_height, args.input_width), interpolation=transforms.InterpolationMode.BICUBIC),
         transforms.ToTensor()]
train_dataset = AnimeDataset(args, trans=trans)
train_loader = DataLoader(train_dataset, batch_size=args.batch_size, shuffle=True, num_workers=args.n_cpu)
print("Data Loaded====================>")

###### Training ######
for epoch in tqdm(range(args.start_epoch, args.end_epoch + 1)):
    for i, batch in enumerate(train_loader):

        Sn = Variable(Input_S.copy_(batch['Sn'])).to(DEVICE)
        Sp = Variable(Input_S.copy_(batch['Sp'])).to(DEVICE)
        Cn = Variable(Input_C.copy_(batch['Cn'])).to(DEVICE)
        Cp = Variable(Input_C.copy_(batch['Cp'])).to(DEVICE)

        optimizer_G.zero_grad()

        EIp = feature_extractor(Sp)
        EIn = feature_extractor(Sn)

        pred_Cn = generator(Sn, Sp, Cp, EIp.detach(), EIn.detach())
        # if torch.isnan(pred_Cn[0, 0, 0, 0]):
        #     raise Exception("Nan encountered in prediction of Cn.")

        color_loss = criterion_color(Cn, pred_Cn)

        fms_real = discriminator(Cn)
        fms_fake = discriminator(pred_Cn)

        perceptual_loss = criterion_MSE(fms_real[0], fms_fake[0])
        for i in range(1, len(fms_real)):
            perceptual_loss += criterion_MSE(fms_real[i], fms_fake[i])

        lambda1, lambda2 = 10, 2e-2
        loss = color_loss * lambda1 + perceptual_loss * lambda1

        wandb.log({"color_loss": color_loss.item(), "perceptual_loss": loss.item()})

        loss.backward()
        optimizer_G.step()

    lr_scheduler_G.step()

    if epoch % 1 == 0:
        save_image(Sn, os.path.join('./results/train', str(epoch) + '_Sn.jpg'))
        save_image(Sp, os.path.join('./results/train', str(epoch) + '_Sp.jpg'))
        save_image(Cn, os.path.join('./results/train', str(epoch) + '_Cn.jpg'))
        save_image(Cp, os.path.join('./results/train', str(epoch) + '_Cp.jpg'))
        save_image(pred_Cn, os.path.join('./results/train', str(epoch) + '_pred_Cn.jpg'))

    if epoch % 10 == 0:
        torch.save(generator.state_dict(), args.models_root + '/' + str(epoch) + '_generator.pth')


input = open('cowtip.in', 'r').readline
print = lambda x : open('cowtip.out', 'w').write(str(x)+'\n')

def flip(arr, r, c):
    for r0 in range(r, -1, -1):
        for c0 in range(c, -1, -1):
            if arr[r0][c0] == "1":
                arr[r0][c0] = "0"
            else:
                arr[r0][c0] = "1"

n = int(input())
arr = []
for i in range(n):
    arr.append(list(input().strip()))

count = 0
for r in range(n-1, -1, -1):
    for c in range(n-1, -1, -1):
        if arr[r][c] == "1":
            flip(arr, r, c)
            count += 1

# print(arr)
print(count)


import csv
import json

csvfile = open('sales_data.txt', 'r')
jsonfile = open('json_output.json', 'w')

columns = ("sales_id", "sale_date", "sale_customer_name", "sale_customer_email", "sale_item")
reader = csv.DictReader( csvfile, columns)
row_num = 0
for row in reader:
    if row_num == 0:
        row_num += 1
    else:
        json.dump(row, jsonfile)
        jsonfile.write('\n')


'''import cv2
import numpy as np
import matplotlib.pyplot as plt
from math import sqrt,exp
def main():
    img = cv2.imread('image.jpg')
    img_color = cv2.cvtColor(img, cv2.COLOR_YCrCb2RGB)
    # View image
    cv2.imshow('YCBCR',img)
    cv2.imshow('RGB',img_color)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
main()
'''
'''import cv2
import numpy as np
from matplotlib import pyplot as plt

##### Gray Histogram ###
def gray_hst():
     image = cv2.imread('image.jpg')
     gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
     histogram = cv2.calcHist([gray_image], [0], None, [256], [0, 256])
     plt.plot(histogram, color='k')
     cv2.imshow("Original", image)
     plt.show()
     cv2.waitKey(0)
     cv2.destroyAllWindows()

#### RGB Histogram ####
def rgb_hst():
    image = cv2.imread('image.jpg', -1)
    b, g, r = cv2.split(image)
    cv2.imshow("Original", image)
    cv2.imshow("Blue", b),
    cv2.imshow("Green", g)
    cv2.imshow("Red", r)
    plt.hist(b.ravel(), 256, [0, 256])
    plt.hist(g.ravel(), 256, [0, 256])
    plt.hist(r.ravel(), 256, [0, 256])
    hist = cv2.calcHist([image], [0], None, [256], [0, 256])
    plt.plot(hist)
    plt.show()
    cv2.waitKey(0)
    cv2.destroyAllWindows()

#### Equalization ####
def equ():
    img = cv2.imread('image.jpg',0)
    equ = cv2.equalizeHist(img)
    res = np.hstack((img,equ))
    plt.plot(res)
    cv2.imshow("Equalization", res)
    plt.show()
    cv2.imwrite('res.png',res)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

#### Stretching ####
def stret():
    img = cv2.imread('image.jpg')
    original = img.copy()
    xp = [0, 64, 128, 192, 255]
    fp = [0, 16, 128, 240, 255]
    x = np.arange(256)
    table = np.interp(x, xp, fp).astype('uint8')
    img = cv2.LUT(img, table)
    cv2.imshow("Original", original)
    cv2.imshow("Output", img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

while 1:
    print("Choose your option : ")
    print("1. Gray Histogram")
    print("2. RGB Histogram")
    print("3. Histogram Equalization")
    print("4. Histogram Stretching")

    ch = int(input())
    if ch == 1:
        gray_hst()
    elif ch == 2:
        rgb_hst()
    elif ch == 3:
        equ()
    elif ch == 4:
        stret()
    else:
        print("Invalid Option !!!") '''
'''
import cv2
import numpy as np
from matplotlib import pyplot as plt

def median():
    img = cv2.imread('image.png')
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    blur = cv2.medianBlur(img,3)
    plt.subplot(121),plt.imshow(img),plt.title('Original')
    plt.xticks([]), plt.yticks([])
    plt.subplot(122),plt.imshow(blur),plt.title('Median')
    plt.xticks([]), plt.yticks([])
    plt.show()

def gauss():
    img = cv2.imread('image.png')
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    blur = cv2.GaussianBlur(img,(5,5),0)
    plt.subplot(121),plt.imshow(img),plt.title('Original')
    plt.xticks([]), plt.yticks([])
    plt.subplot(122),plt.imshow(blur),plt.title('Gausian')
    plt.xticks([]), plt.yticks([])
    plt.show()

def mean():
    img = cv2.imread('image.png')
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    blur = cv2.blur(img,(7,7))
    plt.subplot(121),plt.imshow(img),plt.title('Original')
    plt.xticks([]), plt.yticks([])
    plt.subplot(122),plt.imshow(blur),plt.title('Mean')
    plt.xticks([]), plt.yticks([])
    plt.show()

while 1:
    print("#------List------#")
    print("1. Median Filter")
    print("2. Gaussian Filter")
    print("3. Mean Filter")
    ch = int(input("Choose your opinion : "))
    if ch == 1:
        median()
    elif ch == 2:
        gauss()
    elif ch == 3:
        mean()
    else:
        print("Invalid Option !!!")
'''
'''
import cv2
import numpy as np
import matplotlib.pyplot as plt

#Global Variable
img = cv2.imread("image.png")
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
out = None

def twoDfilter(src, kernel):
    try:
        m, n = kernel.shape
    except ValueError:
        m = kernel.shape[0]
    d = int((m-1)/2)
    h, w = src.shape[0], src.shape[1]
    dst = np.zeros((h, w))
    for y in range(d, h - d):
        for x in range(d, w - d):
            dst[y][x] = np.sum(src[y-d:y+d+1, x-d:x+d+1]*kernel)
    return dst

def edge_gradient():
    #Manual Gradient Edge Detector Calculation
    kernel_x = np.array([-1, 0, 1])
    kernel_y = np.array([[-1],[0],[1]])
    #Library Gradient Edge Detector Calculation
    lib_x = cv2.filter2D(gray,-1,kernel_x)
    lib_y = cv2.filter2D(gray,-1,kernel_y)
    return lib_x,lib_y,kernel_x,kernel_y

def edge_sobel():
    #Manual Sobel Edge Detector Calculation
    kernel_x = np.array([[-1, 0, 1], [-2, 0, 2],[-1, 0, 1]])
    kernel_y = np.array([[-1, -2, -1],[0, 0, 0],[1, 2, 1]])
    #Library Sobel Edge Detector Calculation
    lib_x = cv2.Sobel(gray,cv2.CV_64F,1,0,ksize=5)
    lib_y = cv2.Sobel(gray,cv2.CV_64F,0,1,ksize=5)
    return lib_x,lib_y,kernel_x,kernel_y

def main():
    grad_lx, grad_ly, grad_kx, grad_ky = edge_gradient()
    sob_lx, sob_ly, sob_kx, sob_ky = edge_sobel()

    gray_grad_x = twoDfilter(gray, grad_kx)
    gray_grad_y = twoDfilter(gray, grad_ky)
    gray_sob_x = twoDfilter(gray, sob_kx)
    gray_sob_y = twoDfilter(gray, sob_ky)

    grad_out = np.sqrt(gray_grad_x ** 2 + gray_grad_y ** 2)
    sob_out = np.sqrt(gray_sob_x ** 2 + gray_sob_y ** 2)

    grad_outlib = grad_lx + grad_ly
    sob_outlib = np.sqrt(sob_lx ** 2 + sob_ly ** 2)

    plt.figure(figsize=(8*5, 8*5), constrained_layout=False)

    plt.subplot(241), plt.imshow(gray, cmap = 'gray'),
    plt.title("Grey Image", fontsize=9), plt.xticks([]), plt.yticks([])
    plt.subplot(242), plt.imshow(gray_grad_x, cmap = 'gray'),
    plt.title("Horizontal No-lib", fontsize=9), plt.xticks([]), plt.yticks([])
    plt.subplot(243), plt.imshow(gray_grad_y, cmap = 'gray'),
    plt.title("Vertical No-lib", fontsize=9), plt.xticks([]), plt.yticks([])
    plt.subplot(244), plt.imshow(grad_out, cmap = 'gray'),
    plt.title("Gradient Edge No-lib", fontsize=9), plt.xticks([]), plt.yticks([])
    plt.subplot(246), plt.imshow(grad_lx, cmap = 'gray'),
    plt.title("Horizontal Lib", fontsize=9), plt.xticks([]), plt.yticks([])
    plt.subplot(247), plt.imshow(grad_ly, cmap = 'gray'),
    plt.title("Vertical Lib", fontsize=9), plt.xticks([]), plt.yticks([])
    plt.subplot(248), plt.imshow(grad_outlib, cmap = 'gray'),
    plt.title("Gradient Edge Lib", fontsize=9), plt.xticks([]), plt.yticks([])

    plt.figure(figsize=(8*5, 8*5), constrained_layout=False)

    plt.subplot(241), plt.imshow(gray, cmap = 'gray'),
    plt.title("Grey Image", fontsize=9), plt.xticks([]), plt.yticks([])
    plt.subplot(242), plt.imshow(gray_sob_x, cmap = 'gray'),
    plt.title("Horizontal No-lib", fontsize=9), plt.xticks([]), plt.yticks([])
    plt.subplot(243), plt.imshow(gray_sob_y, cmap = 'gray'),
    plt.title("Vertical No-lib", fontsize=9), plt.xticks([]), plt.yticks([])
    plt.subplot(244), plt.imshow(sob_out, cmap = 'gray'),
    plt.title("Sobel Edge No-lib", fontsize=9), plt.xticks([]), plt.yticks([])
    plt.subplot(246), plt.imshow(sob_lx, cmap = 'gray'),
    plt.title("Horizontal Lib", fontsize=9), plt.xticks([]), plt.yticks([])
    plt.subplot(247), plt.imshow(sob_ly, cmap = 'gray'),
    plt.title("Vertical Lib", fontsize=9), plt.xticks([]), plt.yticks([])
    plt.subplot(248), plt.imshow(sob_outlib, cmap = 'gray'),
    plt.title("Sobel Edge Lib", fontsize=9), plt.xticks([]), plt.yticks([])

    plt.show()

# Run
main()'''
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

#Fuction harris detection
def harris_det():
    filename = 'image.jpg'
    img = cv.imread(filename)
    original = cv.cvtColor(img, cv.COLOR_BGR2RGB)
    gray = cv.cvtColor(img,cv.COLOR_RGB2GRAY)

    # Find corners
    gray = np.float32(gray)
    dst = cv.cornerHarris(gray,2,3,0.04)
    plt.subplot(231), plt.imshow(original), plt.title("Original")
    plt.xticks([]), plt.yticks([])
    plt.subplot(232), plt.imshow(dst), plt.title("Corner")
    plt.xticks([]), plt.yticks([])

    # Harris Corners
    corner = cv.dilate(dst,None, iterations=3)
    img[corner>0.01*corner.max()]=[0,0,255]
    harris = cv.cvtColor(img, cv.COLOR_BGR2RGB)
    plt.subplot(233), plt.imshow(harris), plt.title("Harris Detection")
    plt.xticks([]), plt.yticks([])
    plt.show()

# Run
harris_det()


# Licensed under a 3-clause BSD style license - see LICENSE.rst

import numba as nb
import numpy as np

nb.config.THREADING_LAYER = 'threadsafe'

__all__ = ['get_drift_corrections']

@nb.njit(cache=True, nogil=False, parallel=False, fastmath=False)
def get_drift_corrections(frame_utc, frame_valid, drift_utc_ranges,
                          drift_deltas):  # pragma: no cover
    """
    Get the drift corrections by linear interpolation between drifts.

    The drift correction will be given as:

    delta_i * (frame_time - start_i) / (end_i - start_i)

    where the start and end are the UTC start and end times for a given drift
    where start < frame_time <= end.  If the frame_time is greater than the
    maximum available drift end time, then extrapolation will be used.

    Parameters
    ----------
    frame_utc : numpy.ndarray (float)
        An array of shape (n_frames,) containing the frame UTC times.
    frame_valid : numpy.ndarray (bool)
        A boolean mask of shape (n_frames,) where `False` skips the correction
        calculation for that frame.
    drift_utc_ranges : numpy.ndarray (float)
        The start and end times for the drifts of shape (n_drifts, 2) where
        index [0, 0] gives the start time of the first drift, and index [0, 1]
        gives the end time of the first drift.
    drift_deltas : numpy.ndarray (float)
        The drift offset deltas of shape (n_drifts, 2) where index [0, 0] gives
        the delta of the first drift in the x-direction, and index [0, 1] gives
        the delta of the first drift in the y-direction.

    Returns
    -------
    drift_correction, extrapolation_frame : numpy.ndarray (float), int
        The drift correction is an array of shape (n_frames, 2) where index
        [0, 0] gives the correction for frame 0 in the x-direction and
        index [0, 1] gives the correction for frame 0 in the y-direction.
        The extrapolation frame will be set to a positive number indicating the
        frame from which extrapolation was required.  If no extrapolation
        occurred, this value is -1.
    """
    extrapolate_index = -1
    drift_index = 0
    n_frames = frame_utc.size
    n_drifts = drift_utc_ranges.shape[0]
    drift_correction = np.empty((n_frames, 2), dtype=nb.float64)
    if n_drifts == 0:
        for frame in range(n_frames):
            drift_correction[frame, 0] = 0.0
            drift_correction[frame, 1] = 0.0
        return drift_correction, extrapolate_index

    min_utc = drift_utc_ranges[0, 0]
    max_utc = drift_utc_ranges[0, 1]
    utc_span = max_utc - min_utc
    dx = drift_deltas[0, 0]
    dy = drift_deltas[0, 1]

    for frame in range(frame_utc.size):
        if not frame_valid[frame]:
            drift_correction[frame, 0] = 0.0
            drift_correction[frame, 1] = 0.0
            continue
        utc = frame_utc[frame]

        if extrapolate_index < 0 and (utc < min_utc or utc > max_utc):
            drift_index += 1
            if drift_index >= n_drifts:
                extrapolate_index = frame
                drift_index = -1

            min_utc = drift_utc_ranges[drift_index, 0]
            max_utc = drift_utc_ranges[drift_index, 1]
            utc_span = max_utc - min_utc
            dx = drift_deltas[drift_index, 0]
            dy = drift_deltas[drift_index, 1]

        dt = (utc - min_utc) / utc_span
        drift_correction[frame, 0] = dx * dt
        drift_correction[frame, 1] = dy * dt

    return drift_correction, extrapolate_index


# Defining the Order class, that handles the different orders we have

class Order:

    # Both SELL and BUY are treated as elements of type Order. They have a type, quantity, price and identifier
    def __init__(self, typeTransac, quantity, price, ide):

        if (typeTransac == "BUY" or typeTransac == "SELL"):

            self.typeTransac = typeTransac
            self.id = ide
            self.price = price
            self.quantity = quantity
        else:

            print("Error : unrecognizeg transaction type ...")

    # Overriding the str function so that we can easily print orders whenever we want

    def __str__(self):
        return str(self.typeTransac) + " " + str(self.quantity) + "@" + str(self.price) + " id=" + str(self.id)

# Defining the Book class

class Book:

    # A book is defined by its name. At the creation, we give the id of the very first transaction (id=1) and an empty history of transactions
    def __init__(self, name="book"):

        self.id = 1
        self.history = []

        if(type(name) == str):

            self.name = name

        else:
            self.name = "book"

    # This function is called to add a purchase
    def insert_buy(self, quantity, unitaryPrice):

        # We create an Order with the given attributes
        newBuy = Order("BUY", quantity, unitaryPrice, self.id)
        self.id += 1

        # We add the new Order to the history
        self.history.append(newBuy)

        # We print what happened to let the user know the current state of the history
        print("--- Insert ", end = "")
        print(newBuy, end = "")
        print(" on ", self.name, end = "\n")

        # We sort the history according to the price before displaying it
        self.order()
        print(self)

    # This function is called to add a sale
    def insert_sell(self, quantity, unitaryPrice):

        # We create an Order with the given attributes
        newSell = Order("SELL", quantity, unitaryPrice, self.id)
        self.id += 1

        # We print what happened to let the user know the current type of the history
        print("--- Insert ", end = "")
        print(newSell, end = "")
        print(" on", self.name, end = "\n")

        # We check if any execution(s) should be made
        self.execute(newSell)

        # We sort the history according to the price before displaying it
        self.order()
        print(self)

    # This functions sorts the history according to the price
    def order(self):

        self.history = sorted(self.history, key = lambda order : order.price, reverse = True)

    # This function is called during sales.
    def execute(self, order):

        # buyList contains the list of bought items. totalQuantitiesBuy is the sum of the quantities of buyList
        buyList = [buy for buy in self.history if buy.typeTransac == "BUY"]
        totalQuantitiesBuy = sum(buy.quantity for buy in buyList)

        # We initialize an index that will go over buyList
        index = 0
        quantity = order.quantity

        # if quantity is lower than totalQuantitiesBuy, we must make an execute
        if quantity < totalQuantitiesBuy:

            # while we still have quantities to remove
            while quantity > 0 and index < len(buyList):

                print("Execute", end = " ")

                tempList = [i for i in self.history if i.id == buyList[index].id]

                # element is the indexth item of buyList. ind is its index in the self.history.
                element = tempList[0]
                ind = self.history.index(element)

                # if we can remove it all:
                if quantity < buyList[index].quantity:

                    self.history[ind].quantity -= quantity
                    quantity = 0

                    print(order.quantity - quantity, "at", element.price, end = " ")

                # else, it means we must remove element from self.history and re-loop because we still have some items in excess in the SELL
                else:
                    x = element
                    self.history.remove(element)
                    quantity -= x.quantity

                    print(x.quantity, "at", x.price, end = " ")

                index += 1

                print("on", self.name)

        # else, we simply add the order to the history
        else:

            self.history.append(order)

    # Overriding the str function so that we can easily print orders whenever we want
    def __str__(self):

        s = "Book on " + self.name + "\n"

        for transaction in self.history:
            s += "\t" + str(transaction) + "\n"

        s += "------------------------"

        return s


from django.shortcuts import render
from Hotel.models import hotel
from django.http import HttpResponse
from .addHotelForm import HotelForm
from django.shortcuts import render
from Location.models import location
# Create your views here.

def addHotel(request):

    if request.method == 'POST':
        data = HotelForm(request.POST , request.FILES)
        if data.is_valid():
            dummy = hotel()
            dummy.name = data.cleaned_data['name']
            dummy.stars = data.cleaned_data['stars']
            dummy.image = data.cleaned_data['image']

            getLocationID = location.objects.filter(country=data.cleaned_data['country'],city=data.cleaned_data['city'])
            # insert a new location
            if not getLocationID:
                newLocation = location()
                newLocation.country=data.cleaned_data['country']
                newLocation.city=data.cleaned_data['city']
                newLocation.save()
             #get thisn location id
            getLocationID = location.objects.get(country=data.cleaned_data['country'], city=data.cleaned_data['city'])
            dummy.location_id = getLocationID
            dummy.save()
            return HttpResponse("Added Successfully!")
        else:
            return HttpResponse("error")

    form = HotelForm()
    return render(request,'Hotel/addHotel.html',{'form' : form})

def showHotels(request):
    all = hotel.objects.all()
    return render(request,'Hotel/showHotels.html',{'hotels':all})


# 문자열 재정렬
"""
입력예시: K1KA5CB7
출력예시: ACBKK13

문자만 따로 붙이기 join으로 나머지는 정렬
*isalpha() -> 일파벳 판별
"""

data = input()
result = []
value = 0

for x in data:
    if x.isalpha():
        result.append(x)
    else:
        value += int(x)

result.sort()

if value != 0:
    result.append(str(value))

print("".join(result))


from torch.utils.data import Dataset

class CustomDataset(Dataset):
    def __init__(self, dataset, tokenizer):
        self.dataset = dataset
        self.tokenizer = tokenizer
        self.tokenized_sentence = self.tokenizer(
            dataset,
            return_tensors="pt",
            padding="max_length",
            truncation=True,
            max_length=256,
            add_special_tokens=True,
            return_token_type_ids=False,
        )

    def __getitem__(self, idx):
        encoded = {key: val[idx] for key, val in self.tokenized_sentence.items()}
        encoded["labels"] = encoded["input_ids"].clone()
        return encoded

    def __len__(self):
        return len(self.dataset)


import meraki
import os

# Instructions:
# Set APIKEY in environment variable MERAKI_DASHBOARD_API_KEY.

def select_org(dashboard):
    # Fetch and select the organization
    print('\n\nFetching organizations...\n')
    organizations = dashboard.organizations.getOrganizations()
    organizations.sort(key=lambda x: x['name'])
    counter = 0
    print('Select org to query:')
    for organization in organizations:
        orgName = organization['name']
        print(f'{counter} - {orgName}')
        counter+=1
    isDone = False
    while isDone == False:
        selected = input('\nSelect the organization ID you would like to query: ')
        try:
            if int(selected) in range(0,counter):
                isDone = True
            else:
                print('\tInvalid Organization Number\n')
        except:
            print('\tInvalid Organization Number\n')
    return(organizations[int(selected)]['id'], organizations[int(selected)]['name'])

# ---- Begin Variables ----
debugLog = False
csvOutSuffix = '_DeviceStatus.csv'

# ---- Begin Script ----

# Connect to dashboard, select org
dashboard = meraki.DashboardAPI(output_log=debugLog, log_path="./logs/", log_file_prefix=os.path.basename(__file__), print_console=False)
selected_org, orgName = select_org(dashboard)
print(f"[+] Organization ID: {selected_org}")

print("[+] Grabbing Network Device List")
devices = dashboard.organizations.getOrganizationDevicesAvailabilities(organizationId=selected_org)

outPath = orgName + csvOutSuffix
with open(outPath, 'w') as file:
    export_string = 'Status,MAC,DeviceName,NetId'
    file.write(export_string + '\n')
    for a in devices:
        if (a['status'] == 'alerting' or a['status'] == 'dormant' or a['status'] == 'offline'):
            print("Status: %s MAC: %s Name: %s Network ID: %s" % (a['status'], a['mac'], a['name'], a['network']['id']))
            export_string = a['status'] +','+ a['mac'] +','+ a['name'] +','+ a['network']['id']
            file.write(export_string + '\n')


import numpy as np
import matplotlib.pyplot as pyplt

P_values = np.linspace(1,10,30)

A_values = (P_values + np.log(10))/np.log(10)

pyplt.plot(P_values,A_values)
pyplt.title("PLOT")
pyplt.xlabel('p')
pyplt.ylabel('A')
pyplt.grid(True)
pyplt.show()


import tensorflow as tf
from tensorflow.keras.applications.vgg19 import preprocess_input
from tensorflow.keras.losses import BinaryCrossentropy
from tensorflow.keras.losses import MeanAbsoluteError
from tensorflow.keras.losses import MeanSquaredError
from tensorflow.keras.metrics import Mean
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.optimizers.schedules import PiecewiseConstantDecay

tf.keras.backend.set_image_data_format('channels_last')

## For distributed training
from tensorflow.python.keras.utils import losses_utils

GLOBAL_BATCH_SIZE = None

def compute_avg_loss_gpu(per_replica_loss_tensor , GLOBAL_BATCH_SIZE_IN = GLOBAL_BATCH_SIZE):
    return tf.nn.compute_average_loss(per_replica_loss_tensor, global_batch_size = GLOBAL_BATCH_SIZE_IN )

def vgg_model():
  # Load our model. Load pretrained VGG, trained on imagenet data
  with tf.name_scope("VGG_MODEL_LOADED_BLOCK"):
    vgg = tf.keras.applications.VGG19(input_shape = [None, None, 3] , include_top=False, weights='imagenet')
    vgg.trainable = False

    outputs = [vgg.get_layer(name).output for name in ['block5_conv4']]

    model = tf.keras.models.Model(vgg.input, outputs)
    model.trainable = False
  return model

content_layers = ['block5_conv4']

def vgg_layers(input_tensor):
  """ Creates a vgg model that returns a list of intermediate output values."""
  # Load our model. Load pretrained VGG, trained on imagenet data

  with tf.name_scope("GAN_TO_VGG_BLOCK"):
    vgg_model_loaded = vgg_model()

    output_features = vgg_model_loaded(input_tensor)

  return tf.convert_to_tensor(output_features, dtype = tf.float32)

def content_loss(hr, sr):
    with tf.name_scope("Content_Loss_Block"):
          # sr_preprocessed = preprocess_input(sr)
          # hr_preprocessed = preprocess_input(hr)
          sr_features = vgg_layers(sr) / 12.75
          hr_features = vgg_layers(hr) / 12.75
          meansquarederror_obj = MeanSquaredError(reduction=losses_utils.ReductionV2.NONE)
          per_replica_loss = meansquarederror_obj(hr_features, sr_features)
          meansquarederror_loss = compute_avg_loss_gpu(per_replica_loss )
          return meansquarederror_loss

def generator_loss(sr_out):
    with tf.name_scope("Generator_Loss_Block"):
        binaryCrossentropy_obj = BinaryCrossentropy(from_logits=False, reduction = losses_utils.ReductionV2.NONE )

        binaryCrossentropy_loss_per_replica = binaryCrossentropy_obj(tf.ones_like(sr_out), sr_out)

        binaryCrossentropy_loss = compute_avg_loss_gpu(binaryCrossentropy_loss_per_replica )

        return binaryCrossentropy_loss

def discriminator_loss(gan_model):
    with tf.name_scope("Discriminator_Loss_Block"):
        hr_out = tf.cast(gan_model.discriminator_real_outputs, tf.float32)
        sr_out = tf.cast(gan_model.discriminator_gen_outputs, tf.float32)

        def get_loss_over_batch(x , y ):
            binaryCrossentropy_obj_disc = BinaryCrossentropy(from_logits=False, reduction = losses_utils.ReductionV2.NONE)
            binaryCrossentropy_per_replica = binaryCrossentropy_obj_disc(x, y)
            return compute_avg_loss_gpu(binaryCrossentropy_per_replica )

        hr_loss = get_loss_over_batch(tf.ones_like(hr_out), hr_out)

        sr_loss = get_loss_over_batch(tf.zeros_like(sr_out), sr_out)

        return hr_loss + sr_loss

def srgan_loss(gan_model):
  with tf.name_scope("SRGAN_Loss_Block"):
    # Define non-adversarial loss - for example "VGG loss" and "MSE loss"

    non_adversarial_loss = content_loss(gan_model.real_data, gan_model.generated_data )

    # non_adversarial_loss_MSE = tf.keras.losses.mean_squared_error(gan_model.real_data, gan_model.generated_data)

    # Define generator loss
    generator_loss_value =  0.001 * generator_loss(gan_model.discriminator_gen_outputs )
    # generator_loss = tfgan.losses.modified_generator_loss(gan_model)

    # Combine these losses - you can specify more parameters
    # Exactly one of weight_factor and gradient_ratio must be non-None

    combined_loss = non_adversarial_loss + generator_loss_value

    return combined_loss

def perpix_loss(gan_model):

    # Define non-adversarial loss - for example "VGG loss" and "MSE loss"

    non_adversarial_loss = content_loss(gan_model.real_data, gan_model.generated_data)

    non_adversarial_loss_MSE = tf.keras.losses.mean_squared_error(gan_model.real_data, gan_model.generated_data)

    # Define generator loss
    generator_loss_value =  0.001 * generator_loss(gan_model.discriminator_gen_outputs )
    # generator_loss = tfgan.losses.modified_generator_loss(gan_model)

    # Combine these losses - you can specify more parameters
    # Exactly one of weight_factor and gradient_ratio must be non-None

    combined_loss = non_adversarial_loss + non_adversarial_loss_MSE + generator_loss_value

    return combined_loss

def MSE_loss(gan_model):
    with tf.name_scope("MSE_Loss_Block"):
        # Define non-adversarial loss - for example "VGG loss" and "MSE loss"

        meansquarederror_obj2 = MeanSquaredError(reduction=losses_utils.ReductionV2.NONE)
        per_replica_loss2 = meansquarederror_obj2(gan_model.real_data, gan_model.generated_data)
        non_adversarial_loss_MSE = compute_avg_loss_gpu(per_replica_loss2 )

        # Define generator loss
        generator_loss_value =  1e-3 * generator_loss(gan_model.discriminator_gen_outputs )
        # generator_loss = tfgan.losses.modified_generator_loss(gan_model)

        # Combine these losses - you can specify more parameters
        # Exactly one of weight_factor and gradient_ratio must be non-None

        combined_loss = non_adversarial_loss_MSE + generator_loss_value
    return combined_loss


from flask import Flask
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager
from elasticsearch import Elasticsearch
import logging
from logging.handlers import RotatingFileHandler
import os

app = Flask(__name__)
app.config.from_object(Config)
app.elasticsearch = Elasticsearch([app.config['ELASTICSEARCH_URL']]) \
    if app.config['ELASTICSEARCH_URL'] else None

from sqlalchemy import MetaData

naming_convention = {
    "ix": 'ix_%(column_0_label)s',
    "uq": "uq_%(table_name)s_%(column_0_name)s",
    "ck": "ck_%(table_name)s_%(column_0_name)s",
    "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
    "pk": "pk_%(table_name)s"
}
db = SQLAlchemy(app, metadata=MetaData(naming_convention=naming_convention))
# db = SQLAlchemy(app)
migrate = Migrate(app, db)
login = LoginManager(app)
# let flak-login knows what is the view function that handles logins
login.login_view = 'login'

from app import routes, models

if app.config['LOG_TO_STDOUT']:
    stream_handler = logging.StreamHandler()
    stream_handler.setLevel(logging.INFO)
    app.logger.addHandler(stream_handler)
else:
    if not os.path.exists('logs'):
        os.mkdir('logs')
    file_handler = RotatingFileHandler('logs/project.log',
                                       maxBytes=10240, backupCount=10)
    file_handler.setFormatter(logging.Formatter(
        '%(asctime)s %(levelname)s: %(message)s '
        '[in %(pathname)s:%(lineno)d]'))
    file_handler.setLevel(logging.INFO)
    app.logger.addHandler(file_handler)