import cv2
import numpy as np
import math

def zeroPadding(img):
    zeroImg = np.zeros((img.shape[0]+3,img.shape[1]+3))
    for i in range(1,img.shape[0]+1):
        for j in range(1, img.shape[1]+1):
            zeroImg[i][j] = img[i-1][j-1]
    return zeroImg

def convolution(kernel, data):
    n,m = data.shape

    convolution_img = []
    for i in range(0,n-3):
        line = []
        for j in range(0,m-3):
            a = data[i:i+3,j:j+3]
            temp = np.sum(np.multiply(kernel, a))
            line.append(temp)
        convolution_img.append(line)
    return np.array(convolution_img)

def gaussianBlur(img):

    x, y = np.mgrid[-1:2, -1:2]
    gaussian_kernel = np.exp(-(x ** 2 + y ** 2))

    # Normalization
    gaussian_kernel = gaussian_kernel / gaussian_kernel.sum()

    # print(gaussian_kernel)
    colized = convolution(gaussian_kernel,img)

    return colized

def gradientCal(gx,gy):
    G = np.hypot(gx,gy)
    G = G / G.max() * 255
    theta = np.arctan2(gy,gx)
    return (G,theta)

def nonmaxSuppression(img,D):
    m,n = img.shape
    copyed = np.zeros((m, n), dtype=np.int32)
    angle = D * 180 / np.pi
    angle[ angle<0 ] += 180

    for i in range(1,m-1):
        for j in range(1,n-1):
            try:
                q = 255
                r = 255

                if(0 <= angle[i,j] < 22.5) or (157.5 <= angle[i,j] <= 180):
                    q = img[i,j+1]
                    r = img[i,j-1]
                elif(22.5 <= angle[i,j] < 67.5):
                    q = img[i + 1, j - 1]
                    r = img[i - 1, j + 1]
                elif (67.5 <= angle[i, j] < 112.5):
                    q = img[i + 1, j]
                    r = img[i - 1, j]
                # angle 135
                elif (112.5 <= angle[i, j] < 157.5):
                    q = img[i - 1, j - 1]
                    r = img[i + 1, j + 1]

                if (img[i, j] >= q) and (img[i, j] >= r):
                    copyed[i, j] = img[i, j]
                else:
                    copyed[i, j] = 0

            except IndexError as e:
                pass

    return copyed

def threshold(img, lowthresholdRatio,highthresholdRatio):
    highRatio = img.max() * highthresholdRatio
    lowRatio = highRatio * lowthresholdRatio

    m,n = img.shape
    res = np.zeros((m,n),dtype=np.int32)

    weak = np.int32(25)
    strong = np.int32(255)

    strong_i, strong_j = np.where(img >= highRatio)

    weak_i, weak_j = np.where((img <= highRatio) & (img >= lowRatio))

    res[strong_i, strong_j] = strong
    res[weak_i, weak_j] = weak

    return res

def EdgeLinking(img, weak=25, strong=255):
    m, n = img.shape
    for i in range(1, m-1):
        for j in range(1, n-1):
            if (img[i,j] == weak):
                try:
                    if ((img[i+1, j-1] == strong) or
                        (img[i+1, j] == strong) or
                        (img[i+1, j+1] == strong) or
                        (img[i, j-1] == strong) or
                        (img[i, j+1] == strong) or
                        (img[i-1, j-1] == strong) or
                        (img[i-1, j] == strong) or
                        (img[i-1, j+1] == strong)):

                        img[i, j] = strong
                    else:
                        img[i, j] = 0
                except IndexError as e:
                    pass
    return img

def CannyEdgeDetect(img):
    Gx = np.array([[-1, 0, 1],
                   [-2, 0, 2],
                   [-1, 0, 1]])
    Gy = np.array([[-1, -2, -1],
                   [0, 0, 0],
                   [1, 2, 1]])
    img_gx = convolution(Gx,img)
    img_gy = convolution(Gy,img)

    mag = np.hypot(img_gx,img_gy)
    mag *=255.0 / np.max(mag)

    gradMat , theta = gradientCal(img_gx,img_gy)

    non = nonmaxSuppression(mag,theta)

# 1
#     thresholdImg = threshold(non,lowthresholdRatio=0.09,highthresholdRatio=0.5)
# 2
#     thresholdImg = threshold(non,lowthresholdRatio=0.03,highthresholdRatio=0.8)
# 3
#     thresholdImg = threshold(non,lowthresholdRatio=0.01,highthresholdRatio=0.1)
# 4
    thresholdImg = threshold(non,lowthresholdRatio=0.01,highthresholdRatio=0.8)

    imgEdgeLinking = EdgeLinking(thresholdImg)

    cv2.imwrite('result_img2.jpg', imgEdgeLinking)

    return imgEdgeLinking

def hough_line(img, angle_step=1, value_threshold=120):

    thetas = np.deg2rad(np.arange(-90.0, 90.0, angle_step))
    m, n = img.shape
    diagLen = int(round(math.sqrt(m * m + n * n)))
    rhos = np.linspace(-diagLen, diagLen, diagLen * 2)

    cos_t = np.cos(thetas)
    sin_t = np.sin(thetas)
    num_thetas = len(thetas)

    accumulator = np.zeros((2 * diagLen, num_thetas), dtype=np.uint8)

    edges = img > value_threshold if 1 else img < value_threshold

    y_idxs, x_idxs = np.nonzero(edges)

    for i in range(len(x_idxs)):
        x = x_idxs[i]
        y = y_idxs[i]

        for t_idx in range(num_thetas):
            rho = diagLen + int(round(x * cos_t[t_idx] + y * sin_t[t_idx]))
            accumulator[rho, t_idx] += 1

    m = accumulator.shape[0]
    n = accumulator.shape[1]
    accumulator = accumulator.reshape((m * n))

    def peak_vote(acc,thetas,rhos):
        idx = np.argmax(acc)
        rho = rhos[int(idx / n)]
        theta = thetas[idx % n]

        return idx,theta,rho

    for i in range(5):
        idx , theta , rho = peak_vote(accumulator,thetas,rhos)

        y1 = int((rho) / math.sin(theta))
        x2 = img.shape[1]
        y2 = int((rho - (x2 * math.cos(theta))) / math.sin(theta))

        point1 , point2 = (0,y1) , (x2,y2)

        cv2.line(img2,point1,point2, (255, 0, 0), 1, cv2.LINE_AA)

        np.delete(accumulator, [0])
        accumulator = np.delete(accumulator, np.where(accumulator == accumulator[idx]))

    cv2.imwrite('result_img3.jpg', img2)

src = "./test_images/1.jpg"

img = cv2.imread(src)
img2 = img.copy()

img_gray = cv2.imread(src , cv2.IMREAD_GRAYSCALE)
img_padding_grad = zeroPadding(img_gray)
img_col = gaussianBlur(img_padding_grad)

cv2.imwrite('result_img1.jpg', img_col)

img_cos = cv2.imread('./result_img1.jpg' , cv2.IMREAD_GRAYSCALE)

img_Canny = CannyEdgeDetect(img_cos)

hough_line(img_Canny)

cv2.imshow("Original",img)
cv2.imshow("Processed", img2)
cv2.waitKey()
cv2.destroyAllWindows()


import os
import sys
import logging
import multiprocessing
import progressbar
import threading

from PanACoTA import utils

main_logger = logging.getLogger("align.alignment")

def align_all_families(prefix, all_fams, ngenomes, dname, quiet, threads):
    """
    For each family:

    - align all its proteins with mafft
    - back-translate to nucleotides
    - add missing genomes

    Parameters
    ----------
    prefix :  str
        path to ``aldir/<name of dataset>`` (used to get extraction, alignment and btr files
        easily)
    all_fams : []
        list of all family numbers
    ngenomes : int
        total number of genomes in dataset
    dname : str
        name of dataset (used to name concat and grouped files, as well as tree folder)
    quiet : bool
        True if nothing must be written in stdout/stderr, False otherwise
    threads : int
        max number of threads that can be used by mafft

    Returns
    -------
    bool
        True if everything went well, False if there was a problem in at least 1 family.
    """
    main_logger.info(("Starting alignment of all families: protein alignment, "
                      "back-translation to nucleotides, and add missing genomes in the family"))
    nbfam = len(all_fams)
    bar = None
    if not quiet:
        # Create progressbar
        widgets = ['Alignment: ', progressbar.Bar(marker='█', left='', right='', fill=' '),
                   ' ', progressbar.Counter(), "/{}".format(nbfam), ' (',
                   progressbar.Percentage(), ') - ', progressbar.Timer(), ' - '
                   ]
        bar = progressbar.ProgressBar(widgets=widgets, max_value=nbfam,
                                      term_width=79).start()
    final = []
    if threads == 1:
        update_bar = 1
        for num_fam in all_fams:
            f = handle_family_1thread((prefix, num_fam, ngenomes))
            final.append(f)
            bar.update(update_bar)
            update_bar+=1

    else:
        pool = multiprocessing.Pool(threads)

        # Create a Queue to put logs from processes, and handle them after from a single thread
        m = multiprocessing.Manager()
        q = m.Queue()
        # arguments : (gpath, cores_prokka, name, force, nbcont, q) for each genome
        arguments = [(prefix, num_fam, ngenomes, q) for num_fam in all_fams]
        try:
            final = pool.map_async(handle_family, arguments, chunksize=1)
            pool.close()
            # Listen for logs in processes
            lp = threading.Thread(target=utils.logger_thread, args=(q,))
            lp.start()
            if not quiet:
                while True:
                    if final.ready():
                        break
                    remaining = final._number_left
                    bar.update(nbfam - remaining)
                bar.finish()
            pool.join()
            q.put(None)
            lp.join()
            final = final.get()
        # If an error occurs (or user kills with keybord), terminate pool and exit
        except Exception as excp:  # pragma: no cover
            pool.terminate()
            main_logger.error(excp)
            sys.exit(1)
    # We re-aligned (or added missing genomes) at least one family
    # -> remove concatenated files and groupby files (if they exist)
    if set(final) != {"OK"}:
        aldir = os.path.split(prefix)[0]
        concat_nucl = os.path.join(aldir, f"{dname}-complete.nucl.cat.aln")
        concat_aa = os.path.join(aldir, f"{dname}-complete.aa.cat.aln")
        outdir = os.path.split(aldir)[0]
        treedir = os.path.join(outdir, "Phylo-" + dname)
        grpfile_nucl = os.path.join(treedir, dname + ".nucl.grp.aln")
        grpfile_aa = os.path.join(treedir, dname + ".aa.grp.aln")
        utils.remove(concat_nucl)
        utils.remove(concat_aa)
        utils.remove(grpfile_nucl)
        utils.remove(grpfile_aa)
    return False not in final

def handle_family_1thread(args):
    """
    For the given family:

    - align its proteins with mafft
    - back-translate to nucleotides
    - add missing genomes

    Parameters
    ----------
    args : ()
         (prefix, num_fam, ngenomes, q) with:

         - prefix: path to ``aldir/<name of dataset>``
         - num_fam: the current family number
         - ngenomes: the total number of genomes in dataset

    Returns
    -------
    bool
        - "OK" if the files were not re-created, and have the expected format. This is used by
          ``align_all_families`` function, to know if something was regenerated, or if everything
          already existed with the expected format. If something was redone and concat/group files
          exist, it removes them.
        - False if any problem (extractions, alignment, btr, add missing genomes...)
        - True if just generated all files, and everything is ok
    """
    prefix, num_fam, ngenomes = args
    logger = logging.getLogger('align.align_family')
    # Get file names
    prt_file = f"{prefix}-current.{num_fam}.prt"
    gen_file = f"{prefix}-current.{num_fam}.gen"
    miss_file = f"{prefix}-current.{num_fam}.miss.lst"
    mafft_file = f"{prefix}-mafft-align.{num_fam}.aln"
    btr_file = f"{prefix}-mafft-prt2nuc.{num_fam}.aln"
    # Align all sequences for given family
    status1 = family_alignment(prt_file, gen_file, miss_file, mafft_file, btr_file,
                               num_fam, ngenomes, logger)
    #  status1 is:
    # - False if problem with extractions, alignment or backtranslation -> return False
    # - 'nb_seqs' = number of sequences aligned if everything went well (extractions and
    # alignment ok, btr created without problem)
    # - "OK" if extractions and alignments went well, and btr already exists and is ok
    # If it returned true or the , Add missing genomes
    # If 'OK' or nb_seq, add missing genomes
    if status1:
        added_aa = add_missing_genomes(mafft_file, "protein", miss_file, num_fam, ngenomes, status1, logger)
        added_nucl = add_missing_genomes(btr_file, "back-translated", miss_file, num_fam, ngenomes, status1, logger)
        # 1 of them false: return false
        # both are "OK": return OK (no need to remove concatenated and grouped files)
        # 1 of them true (not "OK"): return true
        if not added_nucl or not added_aa:
            return False
        elif added_aa == "OK" and added_nucl == "OK":
            return "OK"
        else:
            return True
    # Else, return False (there was a problem while trying to align, in any step)
    return False

def handle_family(args):
    """
    For the given family:

    - align its proteins with mafft
    - back-translate to nucleotides
    - add missing genomes

    Parameters
    ----------
    args : ()
         (prefix, num_fam, ngenomes, q) with:

         - prefix: path to ``aldir/<name of dataset>``
         - num_fam: the current family number
         - ngenomes: the total number of genomes in dataset
         - q: a queue, which will be used by logger to put logs while in other process

    Returns
    -------
    bool
        - "OK" if the files were not re-created, and have the expected format. This is used by
          ``align_all_families`` function, to know if something was regenerated, or if everything
          already existed with the expected format. If something was redone and concat/group files
          exist, it removes them.
        - False if any problem (extractions, alignment, btr, add missing genomes...)
        - True if just generated all files, and everything is ok
    """
    prefix, num_fam, ngenomes, q = args
    qh = logging.handlers.QueueHandler(q)
    root = logging.getLogger()
    root.setLevel(logging.DEBUG)
    root.handlers = []
    logging.addLevelName(utils.detail_lvl(), "DETAIL")
    root.addHandler(qh)
    logger = logging.getLogger('align.align_family')
    return handle_family_1thread((prefix, num_fam, ngenomes))

def add_missing_genomes(align_file, ali_type, miss_file, num_fam, ngenomes, status1, logger):
    """
    Once all family proteins are aligned, and back-translated to nucleotides,
    add missing genomes for the family to the alignment with '-'.
    (Add missing genomes to both mafft alignment and back-translated alignment)

    Parameters
    ----------
    align_file : str
        path to file containing alignments (proteins if from mafft output,
        or nucleic sequences if after backtranslating them)
    ali_type : str
        protein or backtranslated
    miss_file : str
        path to file containing the list of missing genomes in this family
    num_fam : int
        family number
    ngenomes : int
        total number of genomes in dataset
    status1 : bool or str
        - "OK" if we did not redo the alignments as they already were as expected. In that case,
          if missing genomes are already present, just add a warning message saying that we
          used the already existing btr file.
        - True if we just did the alignments and backtranslate. So no warning message needed.
        - False if problem with extraction, alignment or backtranslation (will never happen as
          this function is not called if status1 == False)
    logger : logging.Logger
        the logger, having a queue Handler, to give logs to the main logger

    Returns
    -------
    bool or str
        - "OK" if btr file was not recreated, and already has the right number of sequences,
          and all with the same length.
        - False if problem in btr file alignment, so missing genomes not added
        - True if alignment + adding missing genomes is ok. Can happen if there is no missing
          genome for this family (in that case, btr generated already has the right number of
          sequences), or if we just added the missing genomes.

    """
    # btr_file should always exist.
    # Sometimes it comes from previous step ('missing genomes' are missing)
    # Sometimes it comes from a previous run (all genomes should be here)
    status = check_add_missing(align_file, num_fam, ngenomes, logger, prev=True)
    # If btr_file has the correct number of sequences, all the same length, return True
    if status is True:
        if status1 == "OK":
            logger.warning(f"{ali_type} alignment already done for family {num_fam}. The program will use "
                            "it for next steps")
            return "OK"
        else:
            return True
    # If btr_files has problem in alignment (not all sequences with same size)
    elif status is False:
        return False
    # All sequences have same length but some genomes are missing -> Add missing genomes
    # status is length of sequence (if it was True or False, it already ended this function)
    logger.log(utils.detail_lvl(), f"Adding missing genomes for family {num_fam} in {ali_type} alignment.")
    len_aln = status
    with open(miss_file, "r") as missf, open(align_file, "a") as alif:
        for genome in missf:
            genome = genome.strip()
            toadd = ">" + genome + "\n" + "-" * len_aln + "\n"
            alif.write(toadd)
    # check_add_missing called with prev=False :
    # output is True if all ok, or False if problems. Cannot be sequence length (as it can be with prev=True)
    ret = check_add_missing(align_file, num_fam, ngenomes, logger, prev=False)
    return ret

def check_add_missing(btr_file, num_fam, ngenomes, logger, prev):
    """
    Check back-translated alignment while missing genomes have been added

    Parameters
    ----------
    btr_file : str
        path to file containing back-translated alignment
    num_fam : int
        current family number
    ngenomes : int
        total number of genomes in dataset
    logger : logging.Logger
        logger with queueHandler to give logs to main logger
    prev : bool
        True if we are checking alignments before adding missing genomes (in case it comes
        from a previous run and is already done, or in case there are no missing genomes for
        this family, so nothing to do to btr file). In that case, do not write error message
        if the number of sequences does not correspond to the total number of genomes.
        False if we just added missing genomes. In that case, nb sequences should be equal to
        the total number of genomes. If not, write error message.

    Returns
    -------
    bool or int
        - True if right number of sequences in btr file and all the same length (everything is ok)
        - False if problem in alignment (sequences do not all have the same size), or same size but not all
          genomes while not being from previous run (prev=False)
        - alignment length if sequences aligned all have the same length, but missing
          genomes are not added yet (so, will have to add lines with this number of '-')
    """
    res = check_lens(btr_file, num_fam, logger)
    # If all sequences have the same length, res = (length of a sequence, number of sequences in btr file)
    if res:
        len_aln, nb = res
    # otherwise, return False: problem while aligning or back-translating
    else:
        return False
    # If number of sequences in btr file is not the same as the total number of genomes, either:
    #   - btr comes from a previous run, but was not complete (prev)
    #   - we just created btr file, and there are missing genomes in this family.
    # return sequence length, so that we add missing genomes
    if nb != ngenomes:
        # prev = true: this function was called at the beggining of 'add_missing_genomes',
        # so it's ok if there are not all sequences, they will be added just after. We
        # just checked in case this is a file already complete from a previous run, or
        # in case there is no missing genome in this family.
        # prev = false: called after adding missing genomes. So, error message, as it should
        # contain all expected genomes.
        if not prev:
            logger.error((f"ERROR: family {num_fam} contains {nb} genomes in total "
                          f"instead of the {ngenomes} genomes in input.\n"))
            return False
        # If not already has all sequences, return sequence length to add the missing ones
        return len_aln
    # Everything ok (nb genomes ok and all same length)
    return True

def family_alignment(prt_file, gen_file, miss_file, mafft_file, btr_file,
                     num_fam, ngenomes, logger):
    """
    From a given family, align all its proteins with mafft, back-translate
    to nucleotides, and add missing genomes in this family.

    Parameters
    ----------
    prt_file : str
        path to file containing proteins extracted
    gen_file : str
        path to file containing genes extracted
    miss_file : str
        path to file containing list of genomes missing
    mafft_file : str
        path to file which will contain the protein alignment
    btr_file : str
        path to file which will contain the nucleotide alignment back-translated from protein
        alignment
    num_fam : int
        current family number
    ngenomes : int
        total number of genomes in dataset
    logger : logging.Logger
        logger with queueHandler to give logs to main logger

    Returns
    -------
    bool or str
        - False if problem with extractions or with alignment or with backtranslation
        - 'nb_seqs' = number of sequences aligned if everything went well (extractions and
          alignment ok, btr created without problem)
        - "OK" if extractions and alignments went well, and btr already exists and is ok
    """
    # Check number of proteins extracted
    # =check that nb_prt (or nb_gen, which should be the same) + nb_miss = nb_genomes
    # returns number of genomes extracted (so, excludes missing genomes for the family)
    nbfprt = check_extractions(num_fam, miss_file, prt_file, gen_file, ngenomes, logger)
    nbfal = None
    # If problem with extractions (0 proteins extracted), remove mafft and btr files if they exist, so that they will
    # be regenerated
    if not nbfprt:
        utils.remove(mafft_file)
        utils.remove(btr_file)
        return False
    # If mafft file already exists, check the number of proteins aligned corresponds to number of
    #  proteins extracted. If not, remove mafft and btr files.
    if os.path.isfile(mafft_file):
        # There can be nbfprt (number of proteins extracted)
        # or nb_genomes (proteins extracted + missing added with '-')
        nbfal1 = check_nb_seqs(mafft_file, nbfprt, logger, "")
        nbfal2 = check_nb_seqs(mafft_file, ngenomes, logger, "")
        # if nbfal1: missing genomes have not been added yet. Save this value for later
        if nbfal1:
            nbfal = nbfal1
        # if nbfal2: missing genomes already there, save for later
        elif nbfal2:
            nbfal = nbfal2
        # If not any of those 2 numbers: error
        else:
            message = (f"fam {num_fam}: Will redo alignment, because found a different number of proteins "
                       f"extracted in {prt_file} ({nbfprt}) and proteins aligned in "
                       f"existing {mafft_file}")
            logger.error(message)
            os.remove(mafft_file)
            utils.remove(btr_file)
    # If mafft file does not exist (removed because problem in its alignment, or just not generated
    # yet), remove btr (will be regenerated), and do alignment with mafft
    if not os.path.isfile(mafft_file):
        utils.remove(btr_file)  # remove if exists...
        nbfal = mafft_align(num_fam, prt_file, mafft_file, nbfprt, logger)
    # If problem with alignment, return False
    if not nbfal:
        return False
    # If btr file already exists, means that it was already done before, and not removed because
    # extractions and mafft files are ok. So, return True, saying that btr file is done,
    # next step will be to check it, add missing genomes etc.
    if os.path.isfile(btr_file):
        message = (f"fam {num_fam}: Will redo back-translation, because found a different number of "
                   f"proteins aligned in {mafft_file} ({nbfal}) and genes back-translated in "
                   f"existing {btr_file}")
        # btr file contains either nbfal entries (number of proteins extracted) if it was not completed
        # with missing genomes, or ngenomes if it was completed. If it is not the case, remove it
        # (will be regenerated)
        res = check_nb_seqs(btr_file, [nbfal, ngenomes], logger, message)
        if not res:
            utils.remove(btr_file)
        else:
            return "OK"
    # If btr file does not exist (removed because problem with mafft generated before,
    # or just not generated yet), do back-translation, and return:
    # - number of sequences back-translated if it went well,
    # - False otherwise
    return back_translate(num_fam, mafft_file, gen_file, btr_file, nbfal, logger)

def check_extractions(num_fam, miss_file, prt_file, gen_file, ngenomes, logger):
    """
    Check that extractions went well for the given family:

    - check number of proteins and genes extracted compared to the
      number of genomes

    Parameters
    ----------
    num_fam : int
        current family number
    miss_file : str
        path to file containing the list of genomes missing for the current family
    prt_file : str
        path to file containing all proteins extracted
    gen_file : str
        path to file containing all genes extracted
    ngenomes : int
        total number of genomes in dataset
    logger : logging.Logger
        logger with queueHandler to give logs to main logger

    Returns
    -------
    bool or int
        False if any problem (nbmiss+prt != nbgenomes or nbmiss+gen != nbgenomes). If no
        problem, returns the number of proteins/genes extracted
    """
    logger.log(utils.detail_lvl(), f"Checking extractions for family {num_fam}")

    # Check that extractions went well
    nbmiss = utils.count(miss_file)
    # If files with proteins extracted do not even exist, close with error
    # (they should have been created at the previous step)
    if not os.path.isfile(gen_file):
        logger.error(f"fam {num_fam}: no file with genes extracted "
                     f"('{gen_file}'). Cannot align.")
        sys.exit(1)
    if not os.path.isfile(prt_file):
        logger.error(f"fam {num_fam}: no file with proteins extracted "
                     f"('{prt_file}'). Cannot align.")
        sys.exit(1)
    nbfprt = utils.grep(prt_file, "^>", counts=True)
    nbfgen = utils.grep(gen_file, "^>", counts=True)
    if nbmiss + nbfprt != ngenomes:
        logger.error(("fam {}: wrong sum of missing genomes ({}) and prt extracted ({}) for {} "
                      "genomes in the dataset.").format(num_fam, nbmiss, nbfprt, ngenomes))
        return False
    if nbmiss + nbfgen != ngenomes:
        logger.error(("fam {}: wrong sum of missing genomes ({}) and gen extracted ({}) for {} "
                      "genomes in the dataset.").format(num_fam, nbmiss, nbfgen, ngenomes))
        return False
    return nbfprt

def mafft_align(num_fam, prt_file, mafft_file, nbfprt, logger):
    """
    Align all proteins of the given family with mafft

    Parameters
    ----------
    num_fam : int
        current family number
    prt_file : str
        path to file containing all proteins extracted
    mafft_file : str
        path to file which will contain proteins alignment
    nbfprt : int
        number of proteins extracted in prt file
    logger : logging.Logger
        logger with queueHandler to give logs to main logger

    Returns
    -------
    bool
        True if no problem (alignment ok, same number of proteins extracted and aligned),
        False otherwise
    """
    logger.log(utils.detail_lvl(), f"Aligning family {num_fam}")
    cmd = f"mafft --auto {prt_file}"
    error = f"Problem while trying to align fam {num_fam}"
    stdout = open(mafft_file, "w")
    stderr = open(mafft_file + ".log", "w")
    logger.log(utils.detail_lvl(), f"Mafft command: {cmd}")
    ret = utils.run_cmd(cmd, error, stdout=stdout, stderr=stderr, logger=logger)
    stdout.close()
    if not isinstance(ret, int):
        ret = ret.returncode
    if ret != 0:
        os.remove(mafft_file)
        return False
    message = (f"fam {num_fam}: different number of proteins extracted in {prt_file} ({nbfprt}) and proteins "
               f"aligned in {mafft_file}")
    return check_nb_seqs(mafft_file, nbfprt, logger, message)

def back_translate(num_fam, mafft_file, gen_file, btr_file, nbfal, logger):
    """
    Backtranslate protein alignment to nucleotides

    Parameters
    ----------
    num_fam : int
        current family number. Used for log messages
    mafft_file : str
        path to file containing protein alignments by mafft
    gen_file : str
        path to file containing all sequences, not aligned, in nucleotides. It is used to
        convert the alignment in proteins into a nucleotide alignment
    btr_file : str
        path to the file that will contain the nucleotide alignment
    nbfal : int
        number of sequences aligned for the family by mafft
    logger : logging.Logger
        logger with queueHandler to give logs to main logger

    Returns
    -------
    bool
        - False if problem (back-translation, different number of families...)
        - number of sequences in btr file if everything went well
    """
    logger.log(utils.detail_lvl(), f"Back-translating family {num_fam}")
    curpath = os.path.dirname(os.path.abspath(__file__))
    awk_script = os.path.join(curpath, "prt2codon.awk")
    cmd = f"awk -f {awk_script} {mafft_file} {gen_file}"
    stdout = open(btr_file, "w")
    error = f"Problem while trying to backtranslate {mafft_file} to a nucleotide alignment"
    ret = utils.run_cmd(cmd, error, stdout=stdout, logger=logger)
    stdout.close()
    if not isinstance(ret, int):
        ret = ret.returncode
    if ret != 0:
        os.remove(btr_file)
        return False
    message = (f"fam {num_fam}: different number of proteins aligned in {mafft_file} ({nbfal}) and genes "
               f"back-translated in {btr_file}")
    # Check number of sequences in btr file, and return True/False according to it
    # It should contain the same number of sequences as the mafft file.
    return check_nb_seqs(mafft_file, nbfal, logger, message)

def check_nb_seqs(alnfile, nbfal, logger, message=""):
    """
    Check the number of sequences in the given alignment file

    Parameters
    ----------
    alnfile : str
        path to alignment file
    nbfal : int or []
        expected number of sequences, or list of expected numbers of sequences
    logger : logging.Logger
        logger with queueHandler to give logs to main logger
    message : str
        message to write when sequence numbers do not match

    Returns
    -------
    bool or int
        - False if not same number of sequences
        - nbseqs in align file if found among values in 'nbfal'
    """
    nbseqs = utils.grep(alnfile, "^>", counts=True)
    if isinstance(nbfal, int):
        nbfal = [nbfal]
    for num in nbfal:
        if nbseqs == num:
            return nbseqs
    if message:
        logger.error(f"{message} ({nbseqs})")
    return False

def check_lens(aln_file, num_fam, logger):
    """
    In the given alignment file, check that all sequences have the same length.
    If there is no problem, it returns the length of alignment, and the number
    of sequences aligned.

    Parameters
    ----------
    aln_file : str
        path to the alignment file to check
    num_fam : int
        current family number. Used for log message if problem
    logger : logging.Logger
        logger having a queue Handler to give logs to the main logger in the main process

    Returns
    -------
    bool or tuple
        False if there is a problem in the alignment (sequences do not all have the
        same length).
        If they all have the same length, returns this length and the number of sequences
    """
    nb_gen = 0
    all_sums = set()
    with open(aln_file, "r") as btrf:
        cur_sum = 0
        start = True
        for line in btrf:
            if line.startswith(">"):
                nb_gen += 1
                if not start:
                    all_sums.add(cur_sum)
                    cur_sum = 0
            else:
                start = False
                cur_sum += len(line.strip())
        all_sums.add(cur_sum)
    if len(all_sums) > 1:
        logger.error(f"Nucleic alignments for family {num_fam} (in {aln_file}) do not all have the same "
                     f"length. Lengths found are: {all_sums}\n")
        return False
    # Return sequence length and number of sequences in alignment file
    return list(all_sums)[0], nb_gen


from utils import read_input_as_one_line_ints
from collections import Counter

def update_fish(fish):
    new_fish = fish.get(0, 0)
    for k in range(1, 9):
        fish[k - 1] = fish.get(k, 0)

    fish[8] = new_fish
    fish[6] += new_fish

    return fish

def evolve(days):
    fish = dict(Counter(data))
    for i in range(days):
        fish = update_fish(fish)

    return sum(fish.values())

data = read_input_as_one_line_ints('inputs/day6.txt')
print('Part 1: ', evolve(80))
print('Part 2: ', evolve(256))


import os
import sys
from torch.optim import Adam
from graph_dataset import create_dataset, DataSet
from pathlib import Path
sys.path.append(str((Path(__file__).parent)))
sys.path.append(str((Path(__file__).parent.parent.parent)))
import os
cur_dir = os.getcwd()
pkg_rootdir = os.path.dirname(os.path.dirname(cur_dir))
print(pkg_rootdir)
if pkg_rootdir not in sys.path:
    sys.path.append(pkg_rootdir)

from models.reveal.model import MetricLearningModel
from trainer import train, show_representation
from utils import debug, get_run_id, processed_dir,cache_dir, set_seed, result_dir, get_dir
import numpy as np
import random
import torch
import warnings

warnings.filterwarnings('ignore')
import argparse
from tsne import plot_embedding

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '--base_dir', help='Base Dir',
        default='/data1/username/ReVeal/data/full_experiment_real_data_processed/bigvul/full_graph/balanced/all_balanced'
    )
    parser.add_argument('--dataset', required=True, type=str)
    args = parser.parse_args()
    print(args)
    seed = 12345
    np.random.seed(seed)
    torch.manual_seed(seed)
    torch.cuda.manual_seed(seed)
    random.seed(seed)
    base_dir = args.base_dir

    # ggnn_output = torch.load(f'/data1/username/CLVD/storage/cache/ggnn_output/{args.dataset}/ggnn_output.bin')
    ggnn_bin_path_balanced = cache_dir()/f"ggnn_output/{args.dataset}/ggnn_output.bin"
    ggnn_bin_path = cache_dir()/f"ggnn_output/{args.dataset}/not_balance/ggnn_output.bin"
    ggnn_output = torch.load(ggnn_bin_path)

    # train_entries ；valid_entries；test_entries
    dataset = create_dataset(
        ggnn_output=ggnn_output,
        batch_size=128,
        output_buffer=sys.stderr
    )
    num_epochs = 200
    dataset.initialize_dataset(balance=False) # train entries

    # dataset.initialize_dataset(balance=False) # train entries

    ## train_features, train_targets,_ = dataset.prepare_data(
    #     dataset.train_entries, list(range(len(dataset.train_entries)))
    # )
    # plot_embedding(train_features, train_targets, args.name + '-before-training')
    # plot_embedding(train_features, train_targets, args.dataset + '-before-training')

    print(dataset.hdim, end='\t')
    model = MetricLearningModel(input_dim=dataset.hdim, hidden_dim=256)
    model.cuda()
    optimizer = Adam(model.parameters(), lr=0.001)
    print(model)
    train(model, dataset, optimizer, num_epochs, dataset_name=args.dataset, cuda_device=0, max_patience=10,
          output_buffer=sys.stderr)

    ## show_representation(model, dataset.get_next_test_batch, dataset.initialize_test_batches(), 0,
    #                     args.dataset + '-after-training-triplet')
    #
    # model = MetricLearningModel(input_dim=dataset.hdim, hidden_dim=256, lambda1=0, lambda2=0)
    # model.cuda()
    # optimizer = Adam(model.parameters(), lr=0.001)
    # train(model, dataset, optimizer, num_epochs, cuda_device=0, max_patience=10, output_buffer=sys.stderr)
    # show_representation(model, dataset.get_next_test_batch, dataset.initialize_test_batches(), 0,
    #                     args.dataset + '-after-training-no-triplet')
    pass


import torch.nn.functional as F
import pruning.function.prune as prune

class PruneLeNet5(prune.PruneModule):
    def __init__(self):
        super(PruneLeNet5, self).__init__()
        self.conv1 = prune.MaskConv2Module(1, 20, 5, 1) # in_channels/out_channels/kernel_size/stride
        self.conv2 = prune.MaskConv2Module(20, 50, 5, 1)
        self.fc1 = prune.MaskLinearModule(4 * 4 * 50, 500)
        self.fc2 = prune.MaskLinearModule(500, 10)

    def forward(self, x):
        x = F.relu(self.conv1(x))
        x = F.max_pool2d(x, 2, 2)
        x = F.relu(self.conv2(x))
        x = F.max_pool2d(x, 2, 2)
        x = x.view(-1, 4 * 4 * 50)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x

    # 返回输入值x的第零维外维度乘积。例如x[m,n,q,w]，返回n*q*w
    def num_flat_features(self, x):
        size = x.size()[1:]
        num_features = 1
        for s in size:
            num_features *= s
        return num_features


from tensorflow.keras.datasets import mnist
from sklearn.decomposition import PCA
import numpy as np
from sklearn.svm import SVC

def reshaping(x:np.ndarray):
    return x.reshape(x.shape[0],-1)

(x_train,y_train),(x_test,y_test)=mnist.load_data()
x=reshaping(np.concatenate((x_train,x_test),axis=0))
pca=PCA(n_components=x.shape[1])
pca.fit(x)
evr=np.cumsum(pca.explained_variance_ratio_)
print(f'0.95:{len(np.argwhere(evr>=0.95))}')
print(f'0.99:{len(np.argwhere(evr>=0.99))}')
print(f'0.999:{len(np.argwhere(evr>=0.999))}')
print(f'1.0:{len(np.argwhere(evr>=1.0))}')


# pip install pygame

import pygame
import sys

FPS = 60
MAX_WIDTH = 600
MAX_HEIGHT = 400

pygame.init()       # pygame 초기화
clock = pygame.time.Clock()     # clock 설정
screen = pygame.display.set_mode((MAX_WIDTH, MAX_HEIGHT))       # 스크린 설정 600*400

class Player():     # Player Class 생성
    def __init__(self, x, y) :      # 객체 생성 시 초기화
        self.x = x
        self.y = y
        self.isJump = False
        self.jumpCount = 10

    def draw(self) :        # 파란색 네모 40*40 사이즈 생성
        return pygame.draw.rect(screen, (0, 0, 255), (self.x, self.y, 40, 40))

    def jump(self) :        # Player 점프 구현
        if self.isJump:
            if self.jumpCount >= -10 :
                neg = 1
                if self.jumpCount < 0 :
                    neg = -1
                self.y -= self.jumpCount**2 * 0.7 * neg
                self.jumpCount -= 1
            else :
                self.isJump = False
                self.jumpCount = 10

player = Player(50, MAX_HEIGHT - 40)        # player로 객체 생성

def main():
    while True:
        for event in pygame.event.get():        # pygame의 event 불러오기
            if event.type == pygame.QUIT:       # X 버튼을 누르면 종료
                pygame.quit()
                sys.exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    player.isJump = True        # spacebar를 누르면 player 점프

        clock.tick(FPS)     # 위에 설정된 FPS로 동작
        screen.fill((255, 255, 255))

        player_rect = player.draw()
        player.jump()

        print(player_rect)

        pygame.display.update()     # 적용된 함수들 업데이트

if __name__ == "__main__" :
    main()


"""
API Router
"""
from fastapi import APIRouter

from app.apis.api_v1.book import create_book_router
from app.services.book_service import BookService

def v1_router(book_service: BookService) -> APIRouter:
    api_router = APIRouter()
    api_router.include_router(
        create_book_router(book_service),
        prefix="/books",
        tags=["books"],
    )
    return api_router


from django.db import models
from decouple import config

# Create your models here.

MEMBER_TYPE = (
        ('DIR', 'Director, NIT Raipur'),
        ('HCD', 'Head of Career development'),
        ('FCT','Faculty Incharge'),
        ('MNG', 'Manager'),
        ('HCO', 'Head Co-ordinator'),
        ('OCO', 'Overall Co-ordinator'),
        ('EXC', 'Executive'),
    )

class Member(models.Model):
    domain_choices = [
        ['tech']*2,
        ['spons']*2,
        ['pr']*2,
        ['doc']*2,
        ['design']*2,
        ['none']*2
    ]

    name = models.CharField(max_length=100)
    profile_url = models.URLField(blank=True, null=True)
    image = models.ImageField(upload_to='static/uploads/team', null=True, blank = True)
    member_type = models.CharField(max_length=3, choices= MEMBER_TYPE, default='EXEC')
    year = models.IntegerField(default=2019)
    domain = models.CharField(max_length=100, choices=domain_choices, default='pr')
    linkedin = models.URLField(blank=True, null=True)
    facebook = models.URLField(blank=True, null=True)

    @property
    def image_url(self):
        return config('HOST')+self.image.url

    def __str__(self):
        return self.member_type + '-' + self.name


import multiprocessing

from queue import Queue
from threading import Thread
from validations import validate_column, validate_line, validate_region
from concurrent.futures import ThreadPoolExecutor, Future
from SudokuThread import SudokuThread, Semaphore
from typing import Callable

"""
This is a file with multiple Game validations functions,
create threads and print results functions.

"""

def create_threads(n: int) -> list[SudokuThread]:
    """ Creates the threads

    Parameters
    ----------
    n : int
        The number of threads to be created

    Return
    ------
    list[SudokuThread]
        The list of threads created (SudokuThread's elements)

    """

    threads = []
    for _ in range(n):
        finished_lock = Semaphore(0)
        main_thread_lock = Semaphore(0)

        thread = SudokuThread(
            lock=main_thread_lock,
            finished_lock=finished_lock,
            id=_
        )

        thread.start()
        threads.append(thread)

    return threads

def print_results(results: dict[int, list[str]], process_number: int, n_threads: int = None) -> None:
    """ Print the results of the validation of a puzzle

    Parameters
    ----------
    results : dict
        The dictionary containing one result string for each validated puzzle
    process_number : int
        The number of the process that is being executed
    n_threads : int
        The number of threads that the program is using

    Return
    ------
    None

    """
    if len(results.keys()) == 0:
        print(f"Processo {process_number}: 0 erros encontrados")
        return

    errors = []
    n_erros = 0

    for thread_num in results.keys():
        n_erros += len(results[thread_num])
        error = f"T{thread_num+1}: "
        lines = []
        columns = []
        regions = []
        results[thread_num] = sorted(results[thread_num])
        for res in results[thread_num]:
            if "L" in res:
                lines.append(res)
            elif "C" in res:
                columns.append(res)
            else:
                regions.append(res)

        error += ', '.join(lines + columns + regions)
        errors.append(error)

    errors = '; '.join(errors)
    print(f"Processo {process_number}: {n_erros} erros encontrados ({errors})")

def validate_game_creating_threads_once(solutions: list[list[list[int]]], solution_number, n_threads) -> None:
    """ Validates the game creating threads once and dividing
    the validations for the number of threads in each process

    Parameters
    ----------
    solution : list[list[list[int]]]
        The solution that one process is going to validate
    solution_number : int
        The number of the puzzle that is being validated
    n_threads : int
        The number of threads that the program is using

    Return
    ------
    None

    """
    process_number = multiprocessing.current_process().name[8:]
    functions_list = [validate_line, validate_column, validate_region]
    threads = create_threads(n_threads)
    for i in range(len(solutions)):
        print(f"Processo {process_number}: resolvendo quebra-cabeças {solution_number+i}")
        results = {}
        n_funcition = 0

        while n_funcition != 27:
            for thread in threads:
                if n_funcition == 27:
                    thread.reset(target=None, args=None) # a thread não executa em tal iteração
                    thread.lock.release()
                    continue

                thread.reset(target=functions_list[n_funcition % 3], args=(n_funcition//3, solutions[i], ))
                thread.lock.release() # indica que a thread já pode começar a executar a função destinada a ela

                n_funcition +=1

            for thread in threads:
                thread.finished_lock.acquire() # espera até que a thread termine de executar a função

                if thread.result is None:
                    continue

                result, thread_num = thread.result
                if thread_num in results.keys():
                    results[thread_num].add(result)
                else:
                    results[thread_num] = set([result])

        print_results(results, process_number, n_threads)

    for thread in threads:
        thread.stop()

def validate_game_creating_threads_once_and_using_thread_pool(solutions: list[list[list[int]]], solution_number: int, n_threads: int) -> None:
    """ Validates the game using the creating threads once
    and thread pool executor method

    Parameters
    ----------
    solution : list[list[list[int]]]
        The solutions that one process is going to validate
    solution_number : int
        The number of the puzzle that is being validated
    n_threads : int
        The number of threads that the program is using

    Return
    ------
    None

    """
    process_number = multiprocessing.current_process().name[8:]
    with ThreadPoolExecutor(max_workers=n_threads, thread_name_prefix="Thread") as pool:
        functions_list = [validate_line, validate_column, validate_region]

        for i,solution in enumerate(solutions):
            print(f"Processo {process_number}: resolvendo quebra-cabeças {solution_number+i}")
            results = {}

            futures = []
            for j in range(27):
                futures.append(pool.submit(functions_list[j % 3], j//3, solution))

            for future in futures:
                result = future.result()

                if result is None:
                    continue

                error, thread_num = result
                if thread_num in results.keys():
                    results[thread_num].add(error)
                else:
                    results[thread_num] = set([error])

            print_results(results, process_number, n_threads)

def validate_game_thread_pool_executor(solutions: list[list[list[int]]], solution_number: int, n_threads: int) -> None:
    """ Validates the game using the thread pool executor
    method

    Parameters
    ----------
    solution : list[list[list[int]]]
        The solutions that one process is going to validate
    solution_number : int
        The number of the puzzle that is being validated
    n_threads : int
        The number of threads that the program is using

    Return
    ------
    None

    """
    process_number = multiprocessing.current_process().name[8:]

    for i, solution in enumerate(solutions):
        with ThreadPoolExecutor(max_workers=n_threads, thread_name_prefix="Thread") as pool:
            functions_list = [validate_line, validate_column, validate_region]

            print(f"Processo {process_number}: resolvendo quebra-cabeças {solution_number+i}")
            results = {}

            futures = []
            for j in range(27):
                futures.append(pool.submit(functions_list[j % 3], j//3, solution))

            for future in futures:
                result = future.result()

                if result is None:
                    continue

                error, thread_num = result
                if thread_num in results.keys():
                    results[thread_num].add(error)
                else:
                    results[thread_num] = set([error])

            print_results(results, process_number, n_threads)

def validate_game_sequentially(solutions: list[list[list[int]]], solution_number: int, n_threads: int) -> None:
    """ Validates the game sequentially

    Parameters
    ----------
    solution : list[list[list[int]]]
        The solutions that one process is going to validate
    solution_number : int
        The number of the puzzle that is being validated
    n_threads : int
        The number of threads that the program is using

    Return
    ------
    None

    """
    process_number = multiprocessing.current_process().name[8:]

    for i, solution in enumerate(solutions):
        functions_list = [validate_line, validate_column, validate_region]

        print(f"Processo {process_number}: resolvendo quebra-cabeças {solution_number+i}")

        results = {}
        for j in range(27):
            func = functions_list[j % 3]
            result = func(j//3, solution)

            if result is None:
                continue

            error, thread_num = result
            if thread_num in results.keys():
                results[thread_num].add(error)
            else:
                results[thread_num] = set([error])

        print_results(results, process_number, n_threads)

def handle_results(queue: Queue, n_solutions: int, process_number: int) -> None:
    """
    - Recebe um Future enviado pela `queue` representando o resultado de uma validação de uma solução
    - Uma solução validada é printada qunado o seu número de validações for igual a 27 e
      todos as soluções anteriores a ela já terem sido printadas
    """

    # cada dicionário da lista representa uma solução validada pelo processo
    # As chaves do dicionários são os identificadores das threads que realizaram a validação.
    # O svalores são os erros encontrados pelas threads
    validated_solutions: list[dict[int, list[str] | None]] = [dict() for _ in range(n_solutions)]

    # Lista com contadores indicando a quantidade de validações concluídas de cada resultado.
    # Uma solução validada só é printada qunado o seu número de validações for igual a 27 e todos as soluções anteriores a ela já terem sido printadas
    validation_counters: list[int] = [0 for _ in range(n_solutions)]

    # Indica o número da solução que será printada a seguir
    solution_to_print = 0

    """
        - Enquanto ainda haver soluções a serem printadas, recebe uma validação de alguma solução e atualiza os dados referentes a ela.
        - Caso todas as validações da solução atual tenham sido realizadas, printa os erros encontrados
    """
    while solution_to_print < n_solutions:
        # - A queue inicialmente retorna um future. Quando o resultado de tal future for obtido, ele retornaŕa uma tupla contendo tais elementos:
        #   - número da solução validada
        #   - outra tupla contendo: O erro encontrado durante a validação e athread que encontrou tal erro.
        #     Caso nenhum erro seja encontrado, esse elemento será None

        future: Future = queue.get()

        # Cada resultado retorna uma lista contendo uma tupla que representa uma validação específica.
        # Cada valiadção é composta pelo número da solução a qual ela está relacionada e outra tupla contento
        # o erro encontrado e a thread que o encontrou. Caso nenhum erro tenha sido encontrado, a última tupla será None
        results: list[tuple[int, tuple[str, int] | None]] = future.result()
        for solution_number, error_info in results:
            validation_counters[solution_number] += 1

            # se algum erro foi encontrado
            if error_info is not None:
                error_msg, thread_number = error_info

                if  thread_number in validated_solutions[solution_number].keys():
                    validated_solutions[solution_number][thread_number].append(error_msg)
                else:
                    validated_solutions[solution_number][thread_number] = [error_msg]

            # se a validação da solução atual já pode ser printada
            if validation_counters[solution_to_print] == 27:
                print_results(validated_solutions[solution_number], process_number)
                solution_to_print +=1

def execute_validations(validations_to_execute: list[Callable[[], tuple[int, tuple[str, int]]]]) -> None:
    results = []
    for validation in validations_to_execute:
        results.append(validation())
    return results

def validate_many_games_at_once(solutions: list[list[list[int]]], solution_number: int, n_threads: int) -> None:
    """ Validates the game using the creating threads once
    and thread pool executor method

    Parameters
    ----------
    solution : list[list[list[int]]]
        The solutions that one process is going to validate
    solution_number : int
        The number of the puzzle that is being validated
    n_threads : int
        The number of threads that the program is using

    Return
    ------
    None

    """
    with ThreadPoolExecutor(max_workers=n_threads, thread_name_prefix="Thread") as pool:
        process_number = multiprocessing.current_process().name[8:]
        functions_list = [validate_line, validate_column, validate_region]
        queue = Queue()

        result_handler = Thread(target=handle_results, args=(queue, len(solutions), process_number))
        result_handler.start()

        validation_batch = [] # lista contendo validações que serão realizadas por uma única thread
        for i,solution in enumerate(solutions):
            print(f"Processo {process_number}: resolvendo quebra-cabeças {solution_number+i}")
            for j in range(27):
                def validation(
                        solution_number = i,
                        func = functions_list[j % 3],
                        index = j//3,
                        solution = solution
                ):
                    return solution_number, func(index, solution)

                validation_batch.append(validation)

                if len(validation_batch) == 10 or (i == len(solutions) - 1 and j == 26):
                    future = pool.submit(execute_validations, validation_batch)
                    validation_batch = []

                    queue.put(future)

        result_handler.join()


from dataclasses import dataclass
from datetime import datetime

def to_cypher_value(value) -> str:
    """Converts value to a valid openCypher type"""
    value_type = type(value)

    if value_type == str and value.lower() == "null":
        return value

    if value_type in [int, float, bool]:
        return str(value)

    if value_type in [list, set, tuple]:
        return f"[{', '.join(map(to_cypher_value, value))}]"

    if value_type == dict:
        lines = ", ".join(f"{k}: {to_cypher_value(v)}" for k, v in value.items())
        return f"{{{lines}}}"

    if value is None:
        return "null"

    if value.lower() in ["true", "false"]:
        return value

    return f"'{value}'"

@dataclass
class Track:
    LABEL = "Track"
    artist_name: str
    track_uri: str
    artist_uri: str
    track_name: str
    album_uri: str
    duration_ms: int
    album_name: str

    @staticmethod
    def create_from_data(data):
        return Track(
            data.properties["artist_name"],
            data.properties["track_uri"],
            data.properties["artist_uri"],
            data.properties["track_name"],
            data.properties["album_uri"],
            data.properties["duration_ms"],
            data.properties["album_name"],
        )

    def to_cypher(self):
        return (
            f"artist_name: {self.artist_name}, track_uri: {self.track_uri}, artist_uri:"
            f" {self.artist_uri}, track_name: {self.track_name}, album_uri: {self.album_uri},"
            f" duration_ms: {to_cypher_value(self.duration_ms)}, album_name: {self.album_name}"
        )

    @staticmethod
    def create_from_dict(data):
        return Track(
            data["artist_name"],
            data["track_uri"],
            data["artist_uri"],
            data["track_name"],
            data["album_uri"],
            data["duration_ms"],
            data["album_name"],
        )

@dataclass
class Playlist:
    LABEL = "Playlist"

    name: str
    collaborative: bool = False
    pid: int = 0
    modified_at: datetime = ""
    num_albums: int = 0
    num_tracks: int = 0
    num_followers: int = 0
    num_edits: int = 0
    duration_ms: int = 0
    num_artists: int = 0

    @staticmethod
    def create_from_data(data):
        return Playlist(
            data.properties["name"],
            data.properties["collaborative"],
            data.properties["pid"],
            data.properties["modified_at"],
            data.properties["num_albums"],
            data.properties["num_tracks"],
            data.properties["num_followers"],
            data.properties["num_edits"],
            data.properties["duration_ms"],
            data.properties["num_artists"],
        )

    @staticmethod
    def create_from_dict(data):
        return Playlist(
            data["name"],
            data["collaborative"],
            data["pid"],
            data["modified_at"],
            data["num_albums"],
            data["num_tracks"],
            data["num_followers"],
            data["num_edits"],
            data["duration_ms"],
            data["num_artists"],
        )

    def to_cypher(self):
        return (
            f"name: {self.name}, collaborative: {to_cypher_value(self.collaborative)},"
            f" pid: {to_cypher_value(self.pid)}, modified_at:"
            f" {to_cypher_value(self.modified_at)}, num_albums:"
            f" {to_cypher_value(self.num_albums)}, num_tracks:"
            f" {to_cypher_value(self.num_tracks)}, num_followers:"
            f" {to_cypher_value(self.num_followers)}, num_edits:"
            f" {to_cypher_value(self.num_edits)}, duration_ms:"
            f" {to_cypher_value(self.duration_ms)}, num_artists:"
            f" {to_cypher_value(self.num_artists)}"
        )

    def to_map(self):
        return self.__dict__


from prediction import recommend_jobs
import streamlit as st

def predict_jobs(userid):
    response = recommend_jobs(userid)
    print(response)
    return response

def main():
    html_temp = """

Job Recommendation Application

    """
    st.markdown(html_temp, unsafe_allow_html=True)
    userid = st.slider('Slide to select User ID', min_value=1, max_value=671)
    result = " "
    if st.button("Recommend"):
        result = predict_jobs(userid=userid)
    st.success(f'The recommended jobs for user {userid} are:')
    st.write(result)

if __name__ == '__main__':
    main()


import cv2
import numpy as np

import PIL
from PIL import Image, ImageOps
from PIL.ImageStat import Stat

from ggb.utils.constant import ColorSpace

def preprocessing(image, input_color=ColorSpace.RGB):
    """Preprocess source image.

    :param image: source image
    :param input_color: source image color space
    :return: preprocessed image
    """
    img = image
    if input_color == ColorSpace.BGR:
        img = np.array(img)
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        img = Image.fromarray(img)
    elif input_color == ColorSpace.HSV:
        img = np.array(img)
        img = cv2.cvtColor(img, cv2.COLOR_HSV2RGB)
        img = Image.fromarray(img)
    elif input_color == ColorSpace.YUV:
        img = np.array(img)
        img = cv2.cvtColor(img, cv2.COLOR_YUV2RGB)
        img = Image.fromarray(img)
    return img

def split_normalize(image):
    """Splitting source image then normalize it.

    :param image: source image
    :return: blue and green channel
    """
    im = Image.Image.split(image)
    g = ImageOps.equalize(im[1], mask=None)
    mean = Stat(im[2]).mean[0]
    b = np.array(im[2]).astype('float32')
    b /= (1.0 + mean)
    mean = Stat(g).mean[0]
    g = np.array(g).astype('float32')
    g /= (1.0 + mean)
    b = np.clip(b, 0, 1)
    g = np.clip(g, 0, 1)
    b *= 255.0
    g *= 255.0
    b = Image.fromarray(b.astype('uint8'))
    g = Image.fromarray(g.astype('uint8'))
    return b, g

def postprocessing(b, g, **kwargs):
    """Final GGB process.

    :param b: blue channel
    :param g: green channel
    :param kwargs: dict of custom variable
    :return: GGB image
    """
    img = Image.merge('RGB', (g, g, b))
    return img


import os
import json
import IDELIST.url
import EM_FOREX.url

def make_text_file(filename, data):
    print("make text file for " + filename + "...")
    text = json.dumps(data)
    script_dir = os.path.dirname(__file__)
    rel_path = "../download/IDELIST/" + filename + ".txt"
    abs_file_path = os.path.join(script_dir, rel_path)
    with open(abs_file_path, "w") as f:
        f.write(text)
    print(filename + " file was made successfully!")

if __name__ == "__main__":
    # checking if download folder exists or not.
    if not os.path.isdir("../download"):
        os.mkdir(os.path.dirname(__file__) + "/../download")
    if not os.path.isdir("../download/IDELIST"):
        os.mkdir(os.path.dirname(__file__) + "/../download/IDELIST")

    # stock list
    print("load stock list from Internet...")
    response = IDELIST.url.fetch_push_init(IDELIST.url.url_CALIST(pn=1, pz=10000), "stock")
    print("downloaded stock list!")
    make_text_file("CALIST", response)

    #index list
    print("load index list from Internet...")
    response = IDELIST.url.fetch_push_init(IDELIST.url.url_CILIST(pn=1, pz=10000), "index")
    print("downloaded index list!")
    make_text_file("CILIST", response)

    #HY list
    print("load HY list from Internet...")
    response = IDELIST.url.fetch_push_init(IDELIST.url.url_HYLIST(pn=1, pz=10000), "BK_HY")
    print("downloaded HY list!")
    make_text_file("HYLIST", response)

    # DQ list
    print("load DQ list from Internet...")
    response = IDELIST.url.fetch_push_init(IDELIST.url.url_DQLIST(pn=1, pz=10000), "BK_DQ")
    print("downloaded DQ list!")
    make_text_file("DQLIST", response)

    #GN list
    print("load GN list from Internet...")
    response = IDELIST.url.fetch_push_init(IDELIST.url.url_GNLIST(pn=1, pz=10000), "BK_GN")
    print("downloaded GN list!")
    make_text_file("GNLIST", response)

    #FOREXLIST
    print("load Forex list from Internet...")
    response = EM_FOREX.url.fetch_push_init(EM_FOREX.url.url_LIST(pn=1, pz=1000), "forex")
    print("downloaded Forex list!")
    make_text_file("FOREXLIST", response)


import ezrM
from sys import argv
from requests import get, ConnectionError
GITHUB = 'https://github.com/Uralstech/ezrMlang/releases'

def check_version():
	try:
		ov_text = get('https://pastebin.com/raw/Qz8bKPpN').text
		ov, cv = ov_text.split('.'), ezrM.VERSION.split('.')
		for i, v in enumerate(cv):
			if ov[i] > v:
				if i == 0: print(f'UPDATE AVAILABLE: v{ov_text} [MAJOR UPDATE] -> {GITHUB}'); return
				elif i == 1: print(f'UPDATE AVAILABLE: v{ov_text} [Feature update] -> {GITHUB}'); return
				elif i == 2: print(f'UPDATE AVAILABLE: v{ov_text} [Function update] -> {GITHUB}'); return
				elif i == 3: print(f'UPDATE AVAILABLE: v{ov_text} [Library update] -> {GITHUB}'); return
				elif i == 4: print(f'UPDATE AVAILABLE: v{ov_text} [Patch] -> {GITHUB}'); return
			elif ov[i] < v: return
	except ConnectionError: print('Warning: Could not check for latest ezrM version')

def main():
	print(f'ezr Malayalam Shell v{ezrM.VERSION} ({ezrM.VERSION_DATE}) - Ctrl+C to exit')
	check_version()

	first_command = None
	if len(argv) > 1:
		path = argv[1].replace('\\', '//')
		first_command = f'നിർവഹിക്കുക(\'{path}\')'

	while True:
		try:
			if first_command == None:
				input_ = input('>>> ')
				if input_.strip() == '': continue
			else:
				print(f'>>> {first_command}')
				input_ = first_command
				first_command = None

			result, error = ezrM.run('__പ്രധാന_നിർവ്വഹണം__', input_)

			if error: print(error.as_string())
			elif result:
				if len(result.elements) == 1: print(repr(result.elements[0]))
				else: print(repr(result))
		except KeyboardInterrupt: break
		except EOFError: break

if __name__ == '__main__':
	main()


import unittest
import re

from google.appengine.api import apiproxy_stub_map
from google.appengine.api.capabilities import capability_stub
from google.appengine.api import datastore_file_stub
from google.appengine.api import urlfetch_stub
from google.appengine.api.memcache import memcache_stub
from google.appengine.api import user_service_stub

from werkzeug import BaseResponse, Client, Request

import kay
from kay.app import get_application
from kay.conf import LazySettings
from kay.tests import capability_stub as mocked_capability_stub

class MaintenanceCheckTestCase(unittest.TestCase):

  def setUp(self):
    apiproxy_stub_map.apiproxy = apiproxy_stub_map.APIProxyStubMap()
    stub = datastore_file_stub.DatastoreFileStub('test','/dev/null',
                                                 '/dev/null')
    apiproxy_stub_map.apiproxy.RegisterStub('datastore_v3', stub)

    apiproxy_stub_map.apiproxy.RegisterStub(
      'user', user_service_stub.UserServiceStub())

    apiproxy_stub_map.apiproxy.RegisterStub(
      'memcache', memcache_stub.MemcacheServiceStub())

    apiproxy_stub_map.apiproxy.RegisterStub(
      'urlfetch', urlfetch_stub.URLFetchServiceStub())

    s = LazySettings(settings_module='kay.tests.settings')
    app = get_application(settings=s)
    self.client = Client(app, BaseResponse)
    if apiproxy_stub_map.apiproxy\
          ._APIProxyStubMap__stub_map.has_key('capability_service'):
      del(apiproxy_stub_map.apiproxy\
            ._APIProxyStubMap__stub_map['capability_service'])

  def tearDown(self):
    pass

  def test_success(self):
    """Test with normal CapabilityServiceStub"""
    apiproxy_stub_map.apiproxy.RegisterStub(
      'capability_service',
      capability_stub.CapabilityServiceStub())
    response = self.client.get('/')
    self.assertEqual(response.status_code, 200)

  def test_failure(self):
    """Test with DisabledCapabilityServiceStub
    """
    apiproxy_stub_map.apiproxy.RegisterStub(
      'capability_service',
      mocked_capability_stub.DisabledCapabilityServiceStub())
    response = self.client.get('/')
    self.assertEqual(response.status_code, 302)
    self.assertEqual(response.headers['Location'],
                     'http://localhost/maintenance_page')

    response = self.client.get('/index2')
    self.assertEqual(response.status_code, 302)
    self.assertEqual(response.headers['Location'],
                     'http://localhost/no_decorator')
    response = self.client.get('/no_decorator')
    self.assertEqual(response.status_code, 200)

if __name__ == "__main__":
  unittest.main()


import json

class Model:
    title = "title_val"
    text = "text_val"
    author = "author_val"

    def save(self):
        d = {}
        for attr in dir(Model):
            if attr == "save" or attr.startswith("_"):
                continue
            d[attr] = getattr(self, attr)
        with open('model.json', 'w') as f:
            json.dump(d, f)
        print(d)

m = Model()
m.save()


#!/nfs/stak/users/shressag/sagar/venv/bin/python3.6
from slf_dataset import SLFDataset, SLFDatasetMat
from torch.utils.data import DataLoader
import torch
from collections import OrderedDict, namedtuple
import os
from params import ROOT, MODEL_PATH_VAE, RESULT_PATH_VAE, VALIDATION_SET_PATH
from networks.model import Network as Network_raw
from networks.model_batch_norm import Network as Network_batch_norm
from networks.adversarial_model import EncoderDecoder, EncoderDecoder12, AutoencoderLinear, EncoderDecoder128
from run_manager import RunBuilder, RunManager
from tqdm import tqdm
from networks.vae import VAE

if torch.cuda.is_available():
    devices = ['cuda']
else:
    devices = ['cpu']

class VAELoss(torch.nn.Module):
    def __init__(self):
        super(VAELoss, self).__init__()

    def forward(self, bce_loss, mu, logvar):
        """
        This function will add the reconstruction loss (BCELoss) and the
        KL-Divergence.
        KL-Divergence = 0.5 * sum(1 + log(sigma^2) - mu^2 - sigma^2)
        :param bce_loss: recontruction loss
        :param mu: the mean from the latent vector
        :param logvar: log variance from the latent vector
        """
        BCE = bce_loss
        KLD = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp())
        return BCE + KLD

print('starting')
networks = {
    'network_raw': Network_raw,
    'network_batch_norm': Network_batch_norm,
    'encoder_decoder': EncoderDecoder128,
    'autoencoder': AutoencoderLinear,
    'vae64': VAE
}

params = OrderedDict(
    lr = [0.001],
    batch_size = [128],
    device = devices,
    network = ['vae64'],
    shuffle = [True],
    num_workers = [5],
    loss='vae',
    model='vae64_1'
)

train_set = SLFDatasetUnsampled(root_dir=os.path.join(ROOT, 'slf_mat'),
                    csv_file=os.path.join(ROOT, 'details.csv'), total_data=500000)

validation_set = SLFDatasetUnsampled(root_dir=os.path.join(VALIDATION_SET_PATH, 'slf_mat'),
                    csv_file=os.path.join(VALIDATION_SET_PATH, 'details.csv'), total_data=5000)

m = RunManager()
vae_loss = VAELoss()
mse_loss = torch.nn.MSELoss()
for run in RunBuilder.get_runs(params):
    device = torch.device(run.device)
    network = networks[run.network]().to(run.device)
    loader = torch.utils.data.DataLoader(train_set, batch_size=run.batch_size, shuffle=run.shuffle, num_workers=run.num_workers)
    validation_loader = torch.utils.data.DataLoader(validation_set, batch_size=run.batch_size, shuffle=run.shuffle, num_workers=run.num_workers)

    optimizer  = torch.optim.Adam(network.parameters(), lr=run.lr)

    PATH = MODEL_PATH_VAE
    saved_epoch = 0
    lr = run.lr

    l1_loss = torch.nn.L1Loss()

    if os.path.isfile(PATH):
        checkpoint = torch.load(PATH)
        network.load_state_dict(checkpoint['model_state_dict'])
        optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
        saved_epoch = checkpoint['epoch']
        lr = checkpoint['lr']
        # loss = checkpoint['loss']
    m.begin_run(run, network, loader, validation_loader)

    for epoch in range(saved_epoch, 150):
        m.begin_epoch()

        if epoch==30:
            for param_group in optimizer.param_groups:
                param_group['lr'] = 0.0001
        if epoch>70:
            for param_group in optimizer.param_groups:
                param_group['lr'] = 0.00002
        for batch in tqdm(loader):

            # Get data
            in_features, t_slf = batch
            in_features = in_features.to(run.device)
            t_slf = t_slf.to(run.device)
            preds, mu, logvar = network(in_features)

            mse  = mse_loss(t_slf, preds)
            loss = vae_loss(mse, mu, logvar)

            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

            m.track_loss(loss)

        for validation_batch in validation_loader:
            in_features, t_slf = validation_batch
            in_features = in_features.to(run.device)
            t_slf = t_slf.to(run.device)
            preds, mu, logvar = network(in_features)

            mse_valid  = mse_loss(t_slf, preds)
            valid_loss = vae_loss(mse_valid, mu, logvar)
            m.track_validation_loss(valid_loss)
        m.end_epoch()

        for param_group in optimizer.param_groups:
            print(param_group['lr'])
        print('epoch: {}, loss: {}, v_loss: {}, lr: {}'.format(epoch, m.item_loss, m.validation_loss, lr))
        torch.save({'epoch': epoch,
                    'model_state_dict': network.state_dict(),
                    'optimizer_state_dict': optimizer.state_dict(),
                    'loss': m.epoch_loss,
                    'lr': lr},
                    MODEL_PATH_VAE)

    m.end_run()
m.save(RESULT_PATH_)

# PATH = 'models/current.model'
# if os.path.isfile(PATH):
#     checkpoint = torch.load(PATH)
#     network.load_state_dict(checkpoint['model_state_dict'])
#     optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
#     epoch = checkpoint['epoch']
#     # loss = checkpoint['loss']


import base64
import httplib
import json

""" returns a zip file from a github PUBLIC repo.
parameters: filename on github repo is the repository name on
github repo_owner is the owner of the repo
returns: zip file obtained
"""
def get_zipfile(filename, repo, repo_owner):
    # form call components and make google call
    host = 'api.github.com'
    body = ''
    path = '/repos/' + repo_owner + '/' + repo + '/contents/' + filename
    method = 'GET'
    # make connection using https
    github = httplib.HTTPSConnection(host)
    # make request
    github.request(
        method,
        path,
        body,
        {"User-Agent" : "mkSpace Application"}
        )
    response = github.getresponse()
    if response.status != 200:
        return False, response.status

    ghobj = json.loads(response.read())
    # decode content field of returned object
    zip_file = base64.b64decode(ghobj['content'])

    return True, zip_file


from openpyxl import load_workbook
import pandas as pd
import json

class ExcelReader:
    """

    """
    def __init__(self, sheet):
        """

        :param sheet:
        """
        self.sheet = sheet

        f = open("input/files_description.json", "r")
        files_description = json.loads(f.read())

        for description in files_description:
            if description["sheet"] == sheet:
                self.columns = description["columns"]
                self.data = description["data"]
                self.id = description["id"]

    def look_for_sheet(self, input_file):

        wb = load_workbook(input_file)
        sheet_names = wb.sheetnames
        if self.sheet in sheet_names:
            return True
        else:
            return False

    def combine_sheets(self, file_list):
        df = pd.DataFrame()

        f = open(file_list, "r")
        data = json.loads(f.read())

        try:
            for dt in data:
                if dt[self.sheet] == 1:
                    file = dt["file_path"] + dt["file_name"]
                    print(file)
                    df = df.append(pd.read_excel(file, sheet_name=self.sheet), ignore_index=True)

            print(len(df))
            df = df.drop_duplicates(subset=[self.id])
            df = df.sort_values(by=self.id)
            print(len(df))

            print(df.info())

            df.to_csv("output/output.csv", sep=';', encoding='utf-8-sig', index=False)

        except Exception as error:
            print(error)


from dataclasses import dataclass

from global_var import COST_DIVISION
from qsort import quick_sort

@dataclass(frozen=True)
class Technic:
    name: str
    cost: float
    avail: bool

if __name__ == '__main__':
    """ Задание 1."""
    tech = [
        Technic('denn', 1.0, True),
        Technic('pin', 501.0, True),
        Technic('cisco', 300.2, False)
        # Add more technic
    ]

    # def set_category(product_cost: float) -> str:
    #     return '"budget"' if product_cost < COST_DIVISION else '"costly"'
    #
    #
    # for t in tech:
    #     print(
    #         ' '.join(['Product name:', t.name]),
    #         ' '.join(['Category:', set_category(t.cost)]),
    #         ' '.join(['In stock:', 'exist' if t.avail else 'not exist'])
    #     )

    """ Задание 2."""
    # Magic method 1
    product_names = [tech[i].name for i in range(len(tech))]
    product_names.sort(key=len)
    print(product_names)

    # Magic method 2
    print(sorted(tech, key=lambda tech: len(tech.name)))

    # My function quick sort
    quick_sort(tech, 0, len(tech) - 1)
    print(tech)


#!/usr/bin/python3
""" Tests for the Person class """

import inspect
import unittest
import models
import pep8 as pycodestyle

from datetime import datetime
from models.engine import storage
Person = models.person.Person
module_doc = models.person.__doc__

class TestPersonDocs(unittest.TestCase):
    """
        Tests to check the documentation and style of Person class
    """

    @classmethod
    def setUpClass(self):
        """ SetUp for docstring tests """

        self.person_funcs = inspect.getmembers(Person, inspect.isfunction)

    def test_pep8_conformance(self):
        """ Test that models/person.py conforms to PEP8. """

        for path in ['models/person.py',
                     'tests/test_models/test_person.py']:
            with self.subTest(path=path):
                errors = pycodestyle.Checker(path).check_all()
                self.assertEqual(errors, 0)

    def test_module_docstring(self):
        """ Test for the existence of module docstring """

        self.assertIsNot(module_doc, None,
                         "person.py needs a docstring")
        self.assertTrue(len(module_doc) > 1,
                        "person.py needs a docstring")

    def test_class_docstring(self):
        """ Test for the Person class docstring """

        self.assertIsNot(Person.__doc__, None,
                         "Person class needs a docstring")
        self.assertTrue(len(Person.__doc__) >= 1,
                        "Person class needs a docstring")

    def test_func_docstrings(self):
        """ Test for the presence of docstrings in Person methods """

        for func in self.person_funcs:
            if func[0] != 'get_id':
                with self.subTest(function=func):
                    self.assertIsNot(
                        func[1].__doc__,
                        None,
                        "{:s} method needs a docstring".format(func[0])
                    )
                    self.assertTrue(
                        len(func[1].__doc__) > 1,
                        "{:s} method needs a docstring".format(func[0])
                    )

class TestPerson(unittest.TestCase):
    """ Tests for the person class """

    def test_init(self):
        """ Tests the initialization of the person class """

        pass


import argparse
import logging
import os
import sys

from tortuga.config.configManager import ConfigManager
from tortuga.db.dbManager import DbManager
from tortuga.exceptions.componentNotFound import ComponentNotFound
from tortuga.kit.loader import load_kits
from tortuga.kit.registry import get_kit_installer
from tortuga.logging import CLI_NAMESPACE

logger = logging.getLogger(CLI_NAMESPACE)

def main():
    cm = ConfigManager()

    p = argparse.ArgumentParser()

    p.add_argument('-f', '--force', dest='force', action='store_true',
                   default=False)

    p.add_argument('name', help='Software profile name')
    p.add_argument('kit', help='Kit descriptor (NAME-VERSION-ITERATION)')
    p.add_argument('component', help='Component descriptor (NAME-VERSION)')

    args = p.parse_args()

    kitNameAndVersion, kitIteration = args.kit.rsplit('-', 1)
    kitName, kitVersion = kitNameAndVersion.split('-', 1)

    compName, _ = args.component.split('-', 2)

    flagFile = os.path.join(
        cm.getRoot(),
        'var/run/actions/%s/component_%s_%s_post_install' % (
            args.name, args.kit, args.component)
    )

    if os.path.exists(flagFile):
        if not args.force:
            sys.stderr.write(
                'post-install component action for [%s] already run\n' % (
                    compName))
            sys.exit(0)

        # Remove the existing flag file, we're forcing a run
        os.unlink(flagFile)

    load_kits()
    kit_spec = (kitName, kitVersion, kitIteration)

    try:
        with DbManager().session() as session:
            kit_installer = get_kit_installer(kit_spec)()
            kit_installer.session = session
            c = kit_installer.get_component_installer(compName)
            if c is None:
                raise ComponentNotFound(
                    'Component [%s] not found in kit [%s]' % (
                        compName, kitName))

            c.run_action('post_install')

        logger.debug(
            'post_install component action run for [%s] from kit [%s]' % (
                args.component, args.kit))

        # Ensure destination directory exists
        if not os.path.exists(os.path.dirname(flagFile)):
            os.makedirs(os.path.dirname(flagFile))

        # touch flagFile
        open(flagFile, 'w').close()

    except Exception as exc:  # noqa pylint: disable=broad-except
        print('Error: {}'.format(exc), file=sys.stderr)
        sys.exit(0)


import logging

from django.conf import settings
from django.db.models.signals import post_save

logger = logging.getLogger(__name__)

def post_save_receiver(sender, instance, created, **kwargs):
    """
    Placeholder method to execute logic when a custom user is saved or updated.
    """

    # Just logging for now to check functionality
    logger.debug(
        "Hey Veer you just saved/updated a CustomUser!\n \
        I am the post_save hook that got triggered"
    )
    logger.debug("sender %s" % sender)
    logger.debug("instance %s" % instance)
    logger.debug("created %s" % created)
    logger.debug("kwargs %s" % kwargs)

    # Your stuff here

# Wire up our callback with active AUTH USER MODEL
post_save.connect(
    post_save_receiver,
    sender=settings.AUTH_USER_MODEL,
    dispatch_uid="post_save_receiver",
)


from functools import partial
from typing import Optional

import torch
import torch.nn.functional as F
from torch.nn.modules.loss import _Loss

# Copypasted from https://github.com/BloodAxe/pytorch-toolbelt

__all__ = ["FocalLoss"]

BINARY_MODE = "binary"
MULTICLASS_MODE = "multiclass"

def focal_loss_with_logits(
        input: torch.Tensor,
        target: torch.Tensor,
        gamma=2.0,
        alpha: Optional[float] = 0.25,
        reduction="mean",
        normalized=False,
        reduced_threshold: Optional[float] = None,
) -> torch.Tensor:
    """Compute binary focal loss between target and output logits.
    See :class:`~pytorch_toolbelt.losses.FocalLoss` for details.
    Args:
        input: Tensor of arbitrary shape
        target: Tensor of the same shape as input
        reduction (string, optional): Specifies the reduction to apply to the output:
            'none' | 'mean' | 'sum' | 'batchwise_mean'. 'none': no reduction will be applied,
            'mean': the sum of the output will be divided by the number of
            elements in the output, 'sum': the output will be summed. Note: :attr:`size_average`
            and :attr:`reduce` are in the process of being deprecated, and in the meantime,
            specifying either of those two args will override :attr:`reduction`.
            'batchwise_mean' computes mean loss per sample in batch. Default: 'mean'
        normalized (bool): Compute normalized focal loss (https://arxiv.org/pdf/1909.07829.pdf).
        reduced_threshold (float, optional): Compute reduced focal loss (https://arxiv.org/abs/1903.01347).
    References::
        https://github.com/open-mmlab/mmdetection/blob/master/mmdet/core/loss/losses.py
    """
    target = target.type(input.type())

    logpt = F.binary_cross_entropy_with_logits(input, target, reduction="none")
    pt = torch.exp(-logpt)

    # compute the loss
    if reduced_threshold is None:
        focal_term = (1 - pt).pow(gamma)
    else:
        focal_term = ((1.0 - pt) / reduced_threshold).pow(gamma)
        focal_term[pt < reduced_threshold] = 1

    loss = focal_term * logpt

    if alpha is not None:
        loss *= alpha * target + (1 - alpha) * (1 - target)

    if normalized:
        norm_factor = focal_term.sum() + 1e-5
        loss /= norm_factor

    if reduction == "mean":
        loss = loss.mean()
    if reduction == "sum":
        loss = loss.sum()
    if reduction == "batchwise_mean":
        loss = loss.sum(0)

    return loss

class FocalLoss(_Loss):
    def __init__(self, mode=MULTICLASS_MODE, alpha=None, gamma=2, ignore_index=None,
                 reduction="mean", normalized=False, reduced_threshold=None):
        """
        Focal loss for multi-class problem.
        :param mode: Metric mode {'binary', 'multiclass'}
        :param alpha:
        :param gamma:
        :param ignore_index: If not None, targets with given index are ignored
        :param reduced_threshold: A threshold factor for computing reduced focal loss
        """
        super().__init__()
        self.mode = mode
        self.ignore_index = ignore_index
        self.focal_loss_fn = partial(
            focal_loss_with_logits,
            alpha=alpha,
            gamma=gamma,
            reduced_threshold=reduced_threshold,
            reduction=reduction,
            normalized=normalized,
        )

    def forward(self, input, target):
        if self.mode == BINARY_MODE:
            target = target.view(-1)
            input = input.view(-1)

            if self.ignore_index is not None:
                # Filter predictions with ignore label from loss computation
                not_ignored = target != self.ignore_index
                input = input[not_ignored]
                target = target[not_ignored]

            loss = self.focal_loss_fn(input, target)
            return loss
        elif self.mode == MULTICLASS_MODE:
            num_classes = input.size(1)
            loss = 0

            # Filter anchors with -1 label from loss computation
            if self.ignore_index is not None:
                not_ignored = target != self.ignore_index

            for cls in range(num_classes):
                cls_label_target = (target == cls).long()
                cls_label_input = input[:, cls, ...]

                if self.ignore_index is not None:
                    cls_label_target = cls_label_target[not_ignored]
                    cls_label_input = cls_label_input[not_ignored]

                loss += self.focal_loss_fn(cls_label_input, cls_label_target)
            return loss
        else:
            raise NotImplementedError("Mode you are asking for is not implemented.")


import time
import json
from google.cloud import pubsub_v1

with open('config/config.json') as config_file:
    config = json.load( config_file )

gcp_project_id = config['GCP_PROJECT_ID']
gcp_pubsub_topic_name = config['GCP_PUBSUB_TOPIC_NAME']

publisher = pubsub_v1.PublisherClient()
topic_path = publisher.topic_path( gcp_project_id, gcp_pubsub_topic_name )

futures = dict()

def main():

    def get_callback( fut, data ):
        def callback( fut ):
            try:
                print( "publish callback " + fut.result() )
                futures.pop( data )
            except:
                print( 'Please handle {} for {}.'.format( fut.exception(), data ) )
        return callback

    for i in range( 3 ):
        data = str( i )
        futures.update( { data: None } )
        future = publisher.publish( topic_path, data = data.encode( 'utf-8' ) )
        future.add_done_callback( get_callback( future, data ) )

    while futures:
        time.sleep( 5 )


#@Author:pakchungy
#@Date:2021/5/27
#@Time:0:23
#@Project_name:finalproject

import time

import torch
import torch.nn as nn
from RNN import temperature_model_RNN as tm_RNN
import temperature_dataset as td
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
import numpy as np

from score import *

def test(model, test_loader, criterion):
    y_pred_list = []
    y_true_list = []
    loss = 0
    for i, (x, y) in enumerate(test_loader, 0):
        # 计算预测值
        y_pred = model(x)
        loss += criterion(y_pred, y)
        y_pred = y_pred.detach().numpy().reshape(y_pred.shape[0])
        y = y.detach().numpy().reshape(y.shape[0])
        if i == 0:
            y_pred_list = y_pred
            y_true_list = y
        else:
            y_pred_list = np.concatenate((y_pred_list, y_pred))
            y_true_list = np.concatenate((y_true_list, y))

    loss /= i
    # 画图
    plt.figure(figsize=(10, 5))
    plt.plot(y_true_list, 'r+', label='real data')
    plt.plot(y_pred_list, 'b*', label='pred data')
    plt.title('loss={}'.format(loss))
    plt.legend()
    plt.savefig('pre_temperature_RNN_3_test.jpg', dpi=256)
    plt.close()

    print(len(y_true_list))
    print(len(y_pred_list))

    mse(y_true_list, y_pred_list)
    rmse(y_true_list, y_pred_list)
    evs(y_true_list, y_pred_list)

if __name__ == '__main__':
    start_time = time.time()
    model = tm_RNN.TemperatureModel_RNN()
    # 加载数据
    test_loader = DataLoader(td.TemperatureDataset("C:\\Users\\ziting\\Desktop\\yanzheng\\E_weather\\weather\\meant_1901to2000.csv", mode="test", testset_ratio=1),
                             batch_size=64, shuffle=False)
    criterion = nn.MSELoss()
    # 加载模型

    # model = torch.load("CPU/temperature_model_RNN.pth")
    model = torch.load("RNN/GPU/3/temperature_model_RNN_with_GPU.pth", map_location=torch.device('cpu'))
    # 测试
    test(model, test_loader, criterion)
    print("总耗时:{}min".format((time.time() - start_time) / 60))


#!/usr/local/env python
from pathlib import Path

with (Path(__file__).parent / "input.txt").open() as text:
    lines = [ line.strip() for line in text.read().split("\n") if line]

def find_all_uniques_in_list(solution: dict, _list:list):
    def find_unique(x: str):
        if len(x) == 2 or len(x) == 3 or len(x) == 4 or len(x) == 7:
            return len(x)
        return None
    for x in _list:
        unique = find_unique(x)
        if unique is not None:
            solution[unique] = x

def get_remainder(i: str, o: str):
    return [x for x in list(i) + list(o) if  x not in i]

def decipher(solution: dict, left: list):
    one = solution[2]
    seven = solution[3]
    four = solution[4]
    eight = solution[7]
    ret_str = ""
    for f in left:
        c_one = len(get_remainder(f, one))
        c_four = len(get_remainder(f, four))
        c_seven = len(get_remainder(f, seven))
        c_eight = len(get_remainder(f, eight))
        if c_one == 0 and c_four == 0 and c_seven == 0 and c_eight == 1:
            ret_str += "9"
        elif c_one == 1 and c_four == 1 and c_seven == 1 and c_eight == 1:
            ret_str += "6"
        elif c_one == 1 and c_four == 1 and c_seven == 1 and c_eight == 2:
            ret_str += "5"
        elif c_eight == 2 and c_seven == 0 and c_one == 0 and c_four == 1:
            ret_str += "3"
        elif c_eight == 2 and c_seven == 1 and c_one == 1 and c_four == 2:
            ret_str += "2"
        elif c_eight == 1 and c_four == 1 and c_seven == 0 and c_one == 0:
            ret_str += "0"
        elif c_eight == 5 and c_one == 0 and c_four == 2 and c_seven == 1:
            ret_str += "1"
        elif c_eight == 3 and c_four == 0 and c_seven == 1 and c_one == 0:
            ret_str += "4"
        elif c_eight == 4 and c_seven == 0 and c_one == 0 and c_four == 2:
            ret_str += "7"
        elif c_eight == 0:
            ret_str += "8"
        else:
            print(f, "---------")
            print(list(f) + list(one))
            print(one, c_one)
            print(four, c_four)
            print(seven, c_seven)
            print(eight, c_eight)
            exit(1)
    return int(ret_str)

def solve2(init_list: list) -> int:
    counter = 0
    solution = { k: "" for k in range(0,10)}
    for line in init_list:
        inp, outp = line.split(" | ")
        inputs = inp.split(" ")
        outputs = outp.split(" ")
        find_all_uniques_in_list(solution, inputs)
        find_all_uniques_in_list(solution, outputs)
        counter += decipher(solution, outputs)
    return counter

example = [ e.strip() for e in """be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe
edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc
fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg
fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb
aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea
fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb
dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe
bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef
egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb
gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce
""".split("\n") if e ]

simple_example = ["acedgfb cdfbe gcdfa fbcad dab cefabd cdfgeb eafb cagedb ab | cdfeb fcadb cdfeb cdbaf"]

spart2 = solve2(simple_example)
print('Example part 2:', spart2)
assert spart2 == 5353

part2 = solve2(example)
print('Example part 2:', part2)
assert part2 == 61229
print('Part 2:', solve2(lines))


from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.contrib import messages
from .forms import UserRegisterForm, UserUpdateForm, ProfileUpdateForm
from django.contrib.auth.decorators import login_required
from rest_framework import viewsets

from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Request, Listing, Profile, Review
from django.contrib.auth.models import User
from django.db.models import Q
from .serializers import *

# Create your views here.

def home(request):
    return render(request, 'flitting/home.html')

def listing(request):
    return render(request, 'flitting/listing.html')

def register(request):
    if request.method == 'POST':
        form = UserRegisterForm(request.POST)
        if form.is_valid():
            form.save()
            username = form.cleaned_data.get('username')
            messages.success(request, f'Your account has been created')
            return redirect('login')
    else:
        form = UserRegisterForm()
    return render(request, 'flitting/register.html', {'form': form})

# define profile for flitting app

@login_required
def profile(request):
    if request.method == 'POST':
        u_form = UserUpdateForm(request.POST, instance=request.user)
        p_form = ProfileUpdateForm(request.POST,
                                   request.FILES,
                                   instance=request.user.profile)
        if u_form.is_valid() and p_form.is_valid():
            u_form.save()
            p_form.save()
            messages.success(request, f'Your account has been udpated')
            return redirect('flitting-profile')
    else:
        u_form = UserUpdateForm(instance=request.user)
        p_form = ProfileUpdateForm(instance=request.user.profile)
    context = {
        'u_form': u_form,
        'p_form': p_form
    }
    return render(request, 'flitting/profile.html', context)

# Viewset for profile android call
@api_view(['GET'])
def getRequest(request, pk):
    try:
        r = Request.objects.get(pk=pk)
    except Request.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    serializer = RequestSerializer(r)
    return Response(serializer.data)

@api_view(['GET'])
def getListing(request, pk):
    try:
        r = Listing.objects.get(pk=pk)
    except Listing.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    serializer = ListingSerializer(r)
    return Response(serializer.data)

@api_view(['GET'])
def getUser(request, pk):
    try:
        r = Profile.objects.get(user=pk)
    except Profile.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    serializer = ProfileSerializer(r)
    return Response(serializer.data)

@api_view(['GET'])
def getListingsOf(request, userId):
    try:
        r = Listing.objects.all().filter(user=userId)
    except Listing.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    serializer = ListingSerializer(r, many=True)
    return Response(serializer.data)

@api_view(['GET'])
def getReviewsOf(request, userId):
    try:
        r = Review.objects.all().filter(helper=userId)
    except Review.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    serializer = ReviewSerializer(r, many=True)
    return Response(serializer.data)

@api_view(['GET'])
def getRequestsOf(request, userId):
    try:
        r = Request.objects.all().filter(helper=userId)
    except Request.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    serializer = RequestSerializer(r, many=True)
    return Response(serializer.data)

@api_view(['GET'])
def searchListing(request):
    query = request.GET.get('q', None)
    try:
        ps = [u.user.id for u in Profile.objects.all()
              .filter(Q(user__first_name__icontains=query) | Q(user__last_name__icontains=query))]
        print(len(ps))
        ls = Listing.objects.all().filter(Q(city__icontains=query)
                                          | Q(country__icontains=query)
                                          | Q(category__icontains=query)
                                          | Q(user__in=ps))
        print(len(ls))
    except Profile.DoesNotExist:
        print("no users!")
    except Listing.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    serializer = ListingSerializer(ls, many=True)
    return Response(serializer.data)

@api_view(['GET'])
def getReviewsOf(request, userId):
    try:
        r = Review.objects.all().filter(helper=userId)
    except Review.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    serializer = ReviewSerializer(r, many=True)
    return Response(serializer.data)

# class ProfileViewSet(viewsets.ModelViewSet):
#     quertset=


import kivy
kivy.require('1.9.1')

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.core.window import Window

class MainApp(App):
    def build(self):
        main = BoxLayout(orientation='vertical', height=800)
        grid = GridLayout(cols=1)
        title = Label(text='ytDl', size_hint_y=None, height=200, font_size=150)
        songLabel = Label(text='Song:', size_hint_y=None, height=150, font_size=100)
        artistLabel = Label(text='Artist:',  size_hint_y=None, height=150, font_size=100)
        song = TextInput(multiline=False, size_hint_y=None, height=100, font_size=80)
        artist = TextInput(multiline=False, size_hint_y=None, height=100, font_size=80)
        download = Button(text='Download', size_hint_y=None, height=100, font_size=80)

        grid.add_widget(title)
        grid.add_widget(songLabel)
        grid.add_widget(song)
        grid.add_widget(artistLabel)
        grid.add_widget(artist)
        grid.add_widget(download)
        main.add_widget(grid)

        return main

if __name__=='__main__':
    Window.size = (500, 800)
    MainApp().run()