# figure_S7_S8_data.py
'''
One of the reviewers recommended that we try a different approach to the
pruning algorithm that weighted the decision to remove individual reactions
by the impact of that reaction's removal on the biomass flux, so this script
contains that algorithm and some extra code to record information about how it
and the minimum flux pruner work so we can visualize the differences in the two
approaches
'''

import sys
import string_chem_net as scn
from cobra.flux_analysis import single_reaction_deletion as get_kos
import pandas as pd

def bm_impact_prune(cobra_model, bm_rxn):
    '''
    Prune network by identifying reactions whose removal has minimal impact on
    the biomass flux and iteratively removing them until removing any more
    reactions would eliminate flux through the biomass reaction
    '''
    # removing reactions happens in-place, so we need to make a copy of the
    # cobra model before altering it in any way
    cobra_net = cobra_model.copy()
    # assign reaction fluxes to everything before starting the loop
    solution = cobra_net.optimize()
    bm_rxn_flux = solution.fluxes.get(key = bm_rxn.id)
    # record which reactions are in the network at each step of the pruning
    # process
    rxn_lists = list()
    while True:
        # remove all non-boundary reactions with no flux
        no_flux_rxn_ids = solution.fluxes[solution.fluxes == 0].index
        boundary_rxn_ids = [rxn.id for rxn in cobra_net.boundary]
        ids_to_remove = [
            rxn for rxn in no_flux_rxn_ids if rxn not in boundary_rxn_ids
        ]
        rxns_to_remove = [
            cobra_net.reactions.get_by_id(rxn_id) for rxn_id in ids_to_remove
        ]
        cobra_net.remove_reactions(rxns_to_remove)
        # get biomass fluxes for all single reaction knockouts
        kos = get_kos(cobra_net, processes = 1)
        # make sure we don't drop a boundary reaction (takes several steps
        # because the index of kos is a bunch of frozensets of reaction ids)
        kos['rxn'] = kos.index
        kos['rxn'] = kos['rxn'].apply(lambda x: list(x)[0])
        kos = kos[~kos['rxn'].isin(boundary_rxn_ids)]
        if kos.empty:
            print('KO dataframe was emtpy after trying to remove exchange rxns')
            print(get_kos(cobra_net))
            print(boundary_rxn_ids)
            sys.exit()
        # now we can identify the reaction with the smallest impact on biomass
        # flux and drop it
        min_flux_rxn_id = list(kos['growth'].idxmax())[0]
        min_flux_rxn = cobra_net.reactions.get_by_id(min_flux_rxn_id)
        # if this reaction is the biomass reaction, we're clearly done pruning
        if min_flux_rxn.id == bm_rxn.id:
            break
        cobra_net.remove_reactions([min_flux_rxn])
        # see if that made the network unsolvable; if so, add the reaction back
        # and exit the while loop
        solution = cobra_net.optimize()
        # sometimes the solution will be feasible but the flux through the
        # biomass reaction will be some absurdly small number and then if you
        # do FBA on the same network again you won't get a feasible solution
        # so can't just check to see if the flux is 0
        bm_rxn_flux = solution.fluxes.get(key = bm_rxn.id)
        if solution.status == 'infeasible' or bm_rxn_flux < 10e-10:
            cobra_net.add_reaction(min_flux_rxn)
            break
        # now that we've made sure that reaction can be removed, add the
        # current list of reactions to rxn_lists
        rxn_lists.append([rxn.id for rxn in cobra_net.reactions])
    # we kept all of the boundary reactions around until now; drop the ones
    # that have no flux
    # have to recreate the solution object first since we probably just added
    # an essential reaction back to the network after discovering that it was
    # essential
    solution = cobra_net.optimize()
    cobra_net.remove_reactions(solution.fluxes[solution.fluxes == 0].index)
    # and add this final reaction list to rxn_lists
    rxn_lists.append([rxn.id for rxn in cobra_net.reactions])
    return(rxn_lists)

def min_flux_prune(cobra_model, bm_rxn):
    '''
    Iteratively remove reactions from the network by identifying reactions with
    the smallest flux until removing a reaction causes biomass flux to drop to
    zero
    (copied from string_chem_net instead of imported because I'm adding some
    bits to keep track of how many reactions are in the network at each stage
    of pruning)
    '''
    # removing reactions happens in-place, so we need to make a copy of the
    # cobra model before altering it in any way
    cobra_net = cobra_model.copy()
    # assign reaction fluxes to everything before starting the loop
    solution = cobra_net.optimize()
    bm_rxn_flux = solution.fluxes.get(key = bm_rxn.id)
    # record which reactions are in the network at each stage of pruning
    rxn_lists = list()
    while True:
        # remove all non-boundary reactions with no flux
        no_flux_rxn_ids = solution.fluxes[solution.fluxes == 0].index
        boundary_rxn_ids = [rxn.id for rxn in cobra_net.boundary]
        ids_to_remove = [
            rxn for rxn in no_flux_rxn_ids if rxn not in boundary_rxn_ids
        ]
        rxns_to_remove = [
            cobra_net.reactions.get_by_id(rxn_id) for rxn_id in ids_to_remove
        ]
        cobra_net.remove_reactions(rxns_to_remove)
        # find remaining reaction with smallest flux and remove it
        flux_bearers = solution.fluxes[solution.fluxes != 0]
        min_flux_rxn_id = flux_bearers.abs().idxmin()
        min_flux_rxn = cobra_net.reactions.get_by_id(min_flux_rxn_id)
        # if this reaction is the biomass reaction, we're clearly done pruning
        if min_flux_rxn.id == bm_rxn.id:
            break
        cobra_net.remove_reactions([min_flux_rxn])
        # see if that made the network unsolvable; if so, add the reaction back
        # and exit the while loop
        solution = cobra_net.optimize()
        # sometimes the solution will be feasible but the flux through the
        # biomass reaction will be some absurdly small number and then if you
        # do FBA on the same network again you won't get a feasible solution
        # so can't just check to see if the flux is 0
        bm_rxn_flux = solution.fluxes.get(key = bm_rxn.id)
        if solution.status == 'infeasible' or bm_rxn_flux < 10e-10:
            cobra_net.add_reaction(min_flux_rxn)
            break
        # now that we know this network is feasible, record which reactions are
        # in it
        rxn_lists.append([rxn.id for rxn in cobra_net.reactions])
    # we kept all of the boundary reactions around until now; drop the ones
    # that have no flux
    # have to recreate the solution object first since we probably just added
    # an essential reaction back to the network after discovering that it was
    # essential
    solution = cobra_net.optimize()
    cobra_net.remove_reactions(solution.fluxes[solution.fluxes == 0].index)
    # and now all this list to rxn_lists
    rxn_lists.append([rxn.id for rxn in cobra_net.reactions])
    return(rxn_lists)

def compare_nets(universal_network, ins, outs):
    '''
    Given a network without any input reactions or a biomass reaction, add
    those and prune it using both the minimum flux pruner and the biomass
    sensitive pruner and record information about how the two pruning
    processes occurred
    '''
    # copy the universal network so we have an unmodified version around
    net = universal_network.copy()
    # choose new input and biomass metabolites for the universal network
    bm_rxn = scn.choose_bm_mets(outs, net)
    net.objective = bm_rxn
    scn.choose_inputs(ins, net, bm_rxn)
    # prune using both approaches
    bm_pruned_rxns = bm_impact_prune(net, bm_rxn)
    min_pruned_rxns = min_flux_prune(net, bm_rxn)
    # make a dictionary to store information about how this network is pruned
    # by the two algorithms
    info_dict = {
        'step' : list(),
        'type' : list(),
        'rxn_count' : list(),
        'jaccard' : list()
    }
    # counter for pruning step
    i = 0
    # zip the two lists of lists together so we can compare the lists of reactions
    for (min_step, bm_step) in zip(min_pruned_rxns, bm_pruned_rxns):
        # record how many reactions are in both networks and find the Jaccard index
        # for this pair
        min_count = len(min_step)
        bm_count = len(bm_step)
        overlap = sum([1 for rxn in min_step if rxn in bm_step])
        jaccard = overlap / (min_count + bm_count - overlap)
        # add two "rows" to info_dict- one for each model. Will make plotting this
        # info easier later
        info_dict['step'].append(i)
        info_dict['type'].append('min')
        info_dict['rxn_count'].append(min_count)
        info_dict['jaccard'].append(jaccard)
        # both step and jaccard will be the same value
        info_dict['step'].append(i)
        info_dict['type'].append('bm')
        info_dict['rxn_count'].append(bm_count)
        info_dict['jaccard'].append(jaccard)
        # now we can increment the step counter
        i += 1

    # there's no guarantee that both pruning algorithms took the same number of
    # steps to finish, so if that's the case the zip() above will have ignored the
    # extra lists from the algorithm that took longer, so we need to look at those
    # reaction lists
    if len(bm_pruned_rxns) != len(min_pruned_rxns):
        # figure out which list was the longer one
        longer_list = list()
        longer_type = ''
        shorter_list = list()
        shorter_type = ''
        if len(bm_pruned_rxns) > len(min_pruned_rxns):
            longer_list = bm_pruned_rxns
            longer_type = 'bm'
            shorter_list = min_pruned_rxns
        else:
            longer_list = min_pruned_rxns
            longer_type = 'min'
            shorter_list = bm_pruned_rxns
        # we know that i is the index we left off at, so continue looping through
        # the longer list at i+1 and make a new counter to keep track of the number
        # of extra steps in longer_list
        j = 0
        j += i # do it this way so that i and j are actually independent variables
        for rxns in longer_list[i+1:]:
            longer_count = len(rxns)
            # get number of reactions in last list in shorter_list
            shorter_count = len(shorter_list[-1])
            overlap = sum([1 for rxn in rxns if rxn in shorter_list[-1]])
            jaccard = overlap / (longer_count + shorter_count - overlap)
            # only need to add info for longer_list
            info_dict['step'].append(j)
            info_dict['type'].append(longer_type)
            info_dict['rxn_count'].append(longer_count)
            info_dict['jaccard'].append(jaccard)
            j += 1
    # now that that's taken care of, turn this dict into a pandas dataframe and
    # return it
    info_df = pd.DataFrame(info_dict)
    return(info_df)

if __name__ == '__main__':
    try:
        (monos, max_len, ins, outs, reps) = sys.argv[1:]
    except ValueError:
        sys.exit(
            'Specify monomers to use, maximum length of polymer, number of ' +
            'food sources, number of biomass precursors, and number of times to ' +
            'prune'
        )

    # setup network of specified size
    SCN = scn.CreateNetwork(monos, int(max_len))
    cobra_model = scn.make_cobra_model(SCN.met_list, SCN.rxn_list)

    # prepare dataframe to hold info from all rounds of pruning
    all_data = pd.DataFrame({
        'step' : list(),
        'type' : list(),
        'rxn_count' : list(),
        'jaccard' : list()
    })
    # prune reps times and store all information in all_data
    for i in range(int(reps)):
        if (i+1) % 10 == 0:
            print(f'On rep {i+1} of {reps}')
        some_data = compare_nets(cobra_model, int(ins), int(outs))
        # make another column to put i in so we can separate out all the different
        # trajectories
        some_data['trial'] = i+1
        all_data = all_data.append(some_data)
    # write all_data to a csv so we can tweak the plotting details without having
    # to run this script again
    all_data.to_csv('data/figure_S7_S8_data.csv', index = False)


import pytest
import os

pynvml = pytest.importorskip("pynvml")

from distributed.diagnostics import nvml

def test_one_time():
    output = nvml.one_time()
    assert "memory-total" in output
    assert "name" in output

    assert len(output["name"]) > 0

def test_1_visible_devices():
    os.environ["CUDA_VISIBLE_DEVICES"] = "0"
    output = nvml.one_time()
    assert len(output["memory-total"]) == 1

@pytest.mark.parametrize("CVD", ["1,0", "0,1"])
def test_2_visible_devices(CVD):
    os.environ["CUDA_VISIBLE_DEVICES"] = CVD
    idx = int(CVD.split(",")[0])

    h = nvml._pynvml_handles()
    h2 = pynvml.nvmlDeviceGetHandleByIndex(idx)

    s = pynvml.nvmlDeviceGetSerial(h)
    s2 = pynvml.nvmlDeviceGetSerial(h2)

    assert s == s2


RemoveDuplicateFromList.py
l1 = [21,1,32,1,43,1,54,23,46,78,43]
print("Before Removing the Duplicate ",l1)
c = []
for i in l1:
    if i not in c:
        c.append(i)
print(c)


#!/usr/bin/python3

import time
import board
import adafruit_dht
import logging
import os
import RPi.GPIO as GPIO

# AC Control Commands
encender = 'irsend SEND_ONCE mitsubishi SWITCH_ON'
apagar = 'irsend SEND_ONCE mitsubishi SWITCH_OFF'
subir_temp = 'irsend SEND_ONCE mitsubishi UP_TEMP'
bajar_temp = 'irsend SEND_ONCE mitsubishi DOWN_TEMP'
mostrar_comandos = 'irsend LIST mitsubishi ""'

# Create LOG file
logging.basicConfig(filename='/YOUR/PATH/ac_ir_control.log', filemode='a', format='%(asctime)s - %(levelname)s - %(message)s')

#Let us Create an object
logger=logging.getLogger('server_logger')
logger.setLevel(logging.DEBUG)

# We need to set up PIN26 in OUTPUT and HIGH (1) mode to get 3V to supply Temperature Sensore (DHT)
GPIO.setup(26, GPIO.OUT)
GPIO.output(26, GPIO.HIGH)

# Initial the dht device, with data pin connected to PIN 40 GPIO 21:
dhtDevice = adafruit_dht.DHT22(board.D21)

# Initial Log
logger.info('AA script started:')

# you can pass DHT22 use_pulseio=False if you wouldn't like to use pulseio.
# This may be necessary on a Linux single board computer like the Raspberry Pi,
# but it will not work in CircuitPython.
# dhtDevice = adafruit_dht.DHT22(board.D18, use_pulseio=False)

while True:
    try:
        temperature = dhtDevice.temperature
        humidity = dhtDevice.humidity
        logger.info(f"Temperature: {temperature} C -  Humidity: {humidity}% ")

        if GPIO.gpio_function(26) == 1:
           GPIO.setup(26, GPIO.OUT)
           GPIO.output(26, GPIO.HIGH)
           logger.warning("Pin 26 changed to OUT also the value is 1 --> 3V")

        if temperature <= 25.0:
           logger.info('COLD Temperature: switch Off AA')
           os.system(apagar)
           time.sleep(6000.0)

        elif temperature >= 28.0:
           logger.info('HOT Temperature: switch Off AA')
           os.system(encender)
           time.sleep(6000.0)

    except RuntimeError as error:
        # Errors happen fairly often, DHT's are hard to read, just keep going
        logger.error(error.args[0])
        time.sleep(2.0)
        continue
    except Exception as error:
        dhtDevice.exit()
        raise error

    time.sleep(600.0)


import json
import requests

def get_links(url):
    response = requests.get(url)
    return response.text.count('ref')

def main():
    list_of_urls = []
    for i in range(5):
        list_of_urls.append(input('Введіть URL-адресу: '))
    dict_of_urls = {}
    for url in list_of_urls:
        dict_of_urls[url] = get_links(url)
    with open('14.1.json', 'w') as file:
        json.dump(dict_of_urls, file)

if __name__ == '__main__':
    main()


import sys
import numpy as np
import scipy
import os
import optuna
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score
import sklearn
import copy
import random
from scipy.stats import gaussian_kde
import time

import pandas as pd
from itertools import product
from src.general_utils import util_path
import warnings
from sklearn.exceptions import UndefinedMetricWarning
from sklearn.metrics import confusion_matrix
from itertools import combinations
import sys

from src.general_utils import util_metric

# For aspect ratio 4:3.
sns.set_context("paper")
sns.set_theme(style="ticks")

def recovered_mode(data, mu_ref, mu_synth=None, thres=0.1):

    rec_modes = 0
    if mu_synth is not None:
        mu_synth = np.array(mu_synth)
        penalty = len(mu_synth)
        for mu in mu_ref:
            d = np.linalg.norm(mu_synth - mu, axis=1)
            if (d < thres).any():
                rec_modes += 1

        #rec_modes /= penalty

    else:
        for mu in mu_ref:
            d = np.linalg.norm(data - mu, axis=1)
            if (d < thres).any():
                rec_modes += 1

    return rec_modes

def frac_points(data, mu_ref, thres=0.1):
    frac = 0
    for sample in data:
        d = np.linalg.norm(mu_ref - sample, axis=1)
        if (d < thres).any():
            frac += 1
    frac /= len(data)

    return frac

def compute_metrics(y_test_real, y_pred, aggregation='mean'):
    cm = confusion_matrix(y_test_real, y_pred)
    num_classes = cm.shape[0]

    accuracy = np.trace(cm) / float(np.sum(cm))

    precision_list = []
    recall_list = []
    f1_score_list = []
    specificity_list = []
    g_mean_list = []

    for j in range(num_classes):
        tp = cm[j, j]
        fp = np.sum(cm[:, j]) - tp
        fn = np.sum(cm[j, :]) - tp
        tn = np.sum(cm) - (fp +fn + tp)

        precision = tp / (tp + fp) if (tp + fp) != 0 else 0
        recall = tp / (tp + fn) if (tp + fn) != 0 else 0
        specificity = tn / (tn + fp) if (tn + fp) != 0 else 0

        f1 = 2 * (precision * recall) / (precision + recall) if (precision + recall) != 0 else 0
        g_mean = np.sqrt(recall * specificity)

        precision_list.append(precision)
        recall_list.append(recall)
        specificity_list.append(specificity)
        f1_score_list.append(f1)
        g_mean_list.append(g_mean)

    if aggregation == 'mean':
        precision = np.mean(precision_list)
        recall = np.mean(recall_list)
        specificity = np.mean(specificity_list)
        f1_score = np.mean(f1_score_list)
        g_mean = np.mean(g_mean_list)
    else:
        raise NotImplementedError

    return accuracy, precision, recall, specificity, f1_score, g_mean

def obj_optuna(trial, samples_real, samples_naive_list, n_obj=1, name_obj='fid_inter', pairwise=True):
    """Objective function to minimize for ensemble S."""

    samples_real = np.vstack(samples_real)
    samples_naive = np.vstack(samples_naive_list)

    max_ens = len(samples_naive_list)
    sel_ens = [trial.suggest_int(f'G{x}', 0, 1) for x in range(len(samples_naive_list))]

    n_ens = np.sum(sel_ens)
    if n_ens < 1:
        raise optuna.TrialPruned("Number of selected GANs is less than 2.")
    samples_ens_list = [samples_naive_list[j] for j in range(max_ens) if sel_ens[j] == 1]
    samples_ens = np.vstack(samples_ens_list)

    mu_ens, cov_ens = util_metric.compute_statistics(samples_ens)

    eps = np.finfo(float).eps
    if n_obj == 1:
        if name_obj == 'fid_inter':
            mu_real, cov_real = util_metric.compute_statistics(samples_real)
            fid = util_metric.FID(mu_ens, cov_ens, mu_real, cov_real)
            return fid
        elif name_obj == 'fid_intra':
            if not pairwise:
                mu_naive, cov_naive = util_metric.compute_statistics(samples_naive)
                fid = util_metric.FID(mu_ens, cov_ens, mu_naive, cov_naive)
            else:
                fid_list = []
                idxs_sel_ens = [j for j, val in enumerate(sel_ens) if val == 1]
                for idxs_comb in combinations(idxs_sel_ens, 2):

                    gan0 = samples_naive_list[idxs_comb[0]]
                    gan1 = samples_naive_list[idxs_comb[1]]
                    gan0_mu, gan0_cov = util_metric.compute_statistics(gan0)
                    gan1_mu, gan1_cov = util_metric.compute_statistics(gan1)

                    fid_list.append(util_metric.FID(gan0_mu, gan0_cov, gan1_mu, gan1_cov))
                fid = np.mean(fid_list)
            return fid

        elif name_obj == 'pr_inter':
            precision, recall = util_metric.compute_pr(samples_real, samples_ens, nearest_k=5)
            pr = 2 * (precision * recall) / (precision + recall)
            return pr
        elif name_obj == 'pr_intra':
            if not pairwise:
                precision, recall = util_metric.compute_pr(samples_naive, samples_ens, nearest_k=5)
                pr = 2 * (precision * recall) / (precision + recall)
            else:
                pr_list = []
                idxs_sel_ens = [j for j, val in enumerate(sel_ens) if val == 1]

                for idxs_comb in combinations(idxs_sel_ens, 2):

                    gan0 = samples_naive_list[idxs_comb[0]]
                    gan1 = samples_naive_list[idxs_comb[1]]

                    precision, recall = util_metric.compute_pr(gan0, gan1, nearest_k=5)
                    pr01 = 2 * (precision * recall) / ((precision + recall) + eps)
                    pr_list.append(pr01)

                pr = np.mean(pr_list)
            return pr
        elif name_obj == 'dc_inter':
            density, coverage = util_metric.compute_dc(samples_real, samples_ens, nearest_k=5)
            dc = 2 * (density * coverage) / (density + coverage)
            return dc
        elif name_obj == 'dc_intra':
            if not pairwise:
                density, coverage = util_metric.compute_dc(samples_naive, samples_ens, nearest_k=5)
                dc = 2 * (density * coverage) / (density + coverage)
            else:
                dc_list = []
                idxs_sel_ens = [j for j, val in enumerate(sel_ens) if val == 1]
                eps = np.finfo(float).eps
                for idxs_comb in combinations(idxs_sel_ens, 2):
                    gan0 = samples_naive_list[idxs_comb[0]]
                    gan1 = samples_naive_list[idxs_comb[1]]

                    density, coverage = util_metric.compute_dc(gan0, gan1, nearest_k=5)
                    dc = 2 * (density * coverage) / ((density + coverage) + eps)
                    dc_list.append(dc)

                dc = np.mean(dc_list)
            return dc
        elif name_obj == 'size':
            size_term = (n_ens / max_ens)
            return size_term
        elif name_obj == 'entropy':
            entropy =  util_metric.compute_kde_entropy(samples_ens)
            return entropy
        elif name_obj == 'coverage_real':
            _, cov_real = util_metric.compute_statistics(samples_real)
            cov = np.linalg.det(cov_ens) / np.linalg.det(cov_real)
            return cov
        elif name_obj == 'coverage_naive':
            _, cov_naive = util_metric.compute_statistics(samples_naive)
            cov = np.linalg.det(cov_ens) / np.linalg.det(cov_naive)
            return cov

    elif n_obj == 2:
        if name_obj == 'pr_inter__pr_intra':
            precision_inter, recall_inter = util_metric.compute_pr(samples_real, samples_ens, nearest_k=5)
            pr_inter = 2 * (precision_inter * recall_inter) / (precision_inter + recall_inter)
            if not pairwise:
                precision_intra, recall_intra = util_metric.compute_pr(samples_naive, samples_ens, nearest_k=5)
                pr_intra = 2 * (precision_intra * recall_intra) / (precision_intra + recall_intra)
            else:
                pr_list = []
                idxs_sel_ens = [j for j, val in enumerate(sel_ens) if val == 1]
                for idxs_comb in combinations(idxs_sel_ens, 2):

                    gan0 = samples_naive_list[idxs_comb[0]]
                    gan1 = samples_naive_list[idxs_comb[1]]

                    precision, recall = util_metric.compute_pr(gan0, gan1, nearest_k=5)
                    pr01 = 2 * (precision * recall) / ((precision + recall) + eps)
                    pr_list.append(pr01)

                pr_intra = np.mean(pr_list)
            return pr_inter, pr_intra

        if name_obj == 'dc_inter__dc_intra':
            density_inter, coverage_inter = util_metric.compute_dc(samples_real, samples_ens, nearest_k=5)
            dc_inter = 2 * (density_inter * coverage_inter) / (density_inter + coverage_inter)
            if not pairwise:
                density_intra, coverage_intra = util_metric.compute_dc(samples_naive, samples_ens, nearest_k=5)
                dc_intra = 2 * (density_intra * coverage_intra) / (density_intra + coverage_intra)
            else:
                dc_list = []
                idxs_sel_ens = [j for j, val in enumerate(sel_ens) if val == 1]
                eps = np.finfo(float).eps
                for idxs_comb in combinations(idxs_sel_ens, 2):
                    gan0 = samples_naive_list[idxs_comb[0]]
                    gan1 = samples_naive_list[idxs_comb[1]]

                    density, coverage = util_metric.compute_dc(gan0, gan1, nearest_k=5)
                    dc = 2 * (density * coverage) / ((density + coverage) + eps)
                    dc_list.append(dc)

                dc_intra = np.mean(dc_list)
            return dc_inter, dc_intra

        elif name_obj == 'fid_inter__fid_intra':
            mu_real, cov_real = util_metric.compute_statistics(samples_real)
            fid_inter = util_metric.FID(mu_ens, cov_ens, mu_real, cov_real)
            if not pairwise:
                mu_naive, cov_naive = util_metric.compute_statistics(samples_naive)
                fid_intra = util_metric.FID(mu_ens, cov_ens, mu_naive, cov_naive)
            else:
                fid_list = []
                idxs_sel_ens = [j for j, val in enumerate(sel_ens) if val == 1]
                for idxs_comb in combinations(idxs_sel_ens, 2):
                    gan0 = samples_naive_list[idxs_comb[0]]
                    gan1 = samples_naive_list[idxs_comb[1]]
                    gan0_mu, gan0_cov = util_metric.compute_statistics(gan0)
                    gan1_mu, gan1_cov = util_metric.compute_statistics(gan1)

                    fid_list.append(util_metric.FID(gan0_mu, gan0_cov, gan1_mu, gan1_cov))
                fid_intra = np.mean(fid_list)

            return fid_inter, fid_intra
    else:
        raise NotImplementedError

def generate_data(n, mu, dev):
    data = []
    per_gaussian = n // len(mu)
    for mean in mu:
        samples = np.random.normal(mean, dev, (per_gaussian, 2))
        data.append(samples)
    return np.vstack(data)

# DATA GENERATION - GAUSSIANS #
def closest_point(mean, classes):
    d = [np.linalg.norm(np.array(mean) - c) for c in classes]
    return np.argmin(d)
def generate_gaussian_data(num_gaussians, num_samples, max_covx=0.1, max_covy=0.1, min_mux=4, min_muy=4, max_mux=12, max_muy=12,seed=42):
    data_list = []
    mu_list = []
    cov_list = []
    np.random.seed(seed)  # Set numpy pseudo-random generator at a fixed value
    random.seed(seed)  # Set python built-in pseudo-random generator at a fixed value
    for _ in range(num_gaussians):
        mu = [
            np.random.uniform(min_mux, max_mux),
            np.random.uniform(min_muy, max_muy)
        ]
        cov = np.diag(
            [np.random.uniform(0.05, max_covx),
             np.random.uniform(0.05, max_covy)]
        )

        data = np.random.multivariate_normal(mu, cov, num_samples)

        data_list.append(data)
        mu_list.append(mu)
        cov_list.append(cov)

    return data_list, np.vstack(data_list), mu_list, cov_list

def create_dataset(data, labels):
    x = []
    y = []
    gauss_idx = []
    for i, label in enumerate(labels):
        samples = data[i]
        lab = np.repeat(label, len(samples)).reshape(-1, 1)
        x.append(samples)
        y.append(lab)
        gauss_idx.append(np.repeat(i, len(samples)).reshape(-1, 1))

    return np.vstack(x), np.vstack(y), np.vstack(gauss_idx)


from abc import ABCMeta

import random

from numpy import insert
from src.solution_methods.basic_operators.InsertionOperator import InsertionOperator
from src.solution_methods.SolutionMethod import SolutionMethod

class RandomInsertion(SolutionMethod):

    def __init__(self):
        super().__init__("Random Insertion")

    def initialize_class_attributes(self):
        return super().initialize_class_attributes()

    def solve(self, solution, parameters):
        new_solution = solution.copy()
        requests = parameters["requests_set"]
        i_op = InsertionOperator()
        for request in requests:
            feasible_insertions = (
                i_op.get_all_feasible_insertions_from_solution(
                    request,
                    new_solution,
                    self.obj_func,
                    self.constraints
                )
            )

            insertion_positions = []
            routes_after_insertion = []
            for feasible_insertion in feasible_insertions:
                position, route, insert_cost = feasible_insertion
                insertion_positions.append(position)
                routes_after_insertion.append(route)

            if (len(routes_after_insertion) <= 0):
                continue

            new_route_pos = random.randint(0, len(routes_after_insertion)-1)
            new_route = routes_after_insertion[new_route_pos]
            inserted_pos = insertion_positions[new_route_pos]

            old_route_identifying = (
                InsertionOperator().get_route_id_value_before_inserted(
                    new_route,
                    request
                )
            )

            old_route_pos = (
                new_solution.find_route_position_by_identifying_value(
                    old_route_identifying
                )
            )

            new_solution = i_op.insert_request_in_solution(
                new_solution,
                request,
                inserted_pos,
                new_route,
                old_route_pos,
                self.obj_func
            )

            new_solution.set_route(old_route_pos, new_route)
            new_solution.add_request(request)
            i_op.update_solution_requests_costs_after_insertion(
                new_solution,
                new_route,
                inserted_pos,
                request,
                self.obj_func
            )

        return new_solution

    def get_current_best_solution(self):
        return super().get_current_best_solution()

    def get_attr_relation_reader(self):
        return {}


import pygame
from pynput.mouse import Controller, Button
import pyautogui

pygame.init()

if pygame.joystick.get_count() == 0:
    print("Nope")
    pygame.quit()
    exit()
else:
    print("Yippe")

mouse = Controller()

joystick = pygame.joystick.Joystick(0)
joystick.init()

xMovement = 0;
yMovement = 0;

def performClick(buttonState):
    if buttonState:
        mouse.press(Button.left)
    else:
        mouse.release(Button.left)

running = True;

while running:
    pygame.event.pump()

    joystickX = joystick.get_axis(0)
    joystickY = joystick.get_axis(1)

    if abs(joystickX) < 0.1:
        joystickX = 0
    if abs(joystickY) < 0.1:
        joystickY = 0

    xMovement =  joystickX * 5 # Change the Multiplier value to achieve smoother X axis movement
    yMovement = joystickY * 5 # Change the Multiplier value to achieve smoother Y axis movement
    mouse.move(xMovement,yMovement)

    aButtonState = joystick.get_button(0)
    bButtonState = joystick.get_button(1)
    performClick(aButtonState)
    performClick(bButtonState)

    hatX, hatY = joystick.get_hat(0)

    if hatY == 1:
        pyautogui.scroll(1)
    elif hatY == -1:
        pyautogui.scroll(-1)

    rightTrigger = joystick.get_axis(5)
    if rightTrigger > 0.9:
       running = False

pygame.quit()


# -*- coding: latin-1 -*-
import os
import pytz

RESULTS_DIRECTORY = "../results/"
DATA_DIRECTORY = "../data/"
FIGS_DIRECTORY = "../figs/"

IMPORTED_DATABASE_PATH = DATA_DIRECTORY + "main.sqlite"

RAW_GTFS_ZIP_PATH =  os.path.join(DATA_DIRECTORY, "raw", "gtfs.zip")

HELSINKI_DATA_BASEDIR = os.path.join(DATA_DIRECTORY, "helsinki/2016-09-28/")
HELSINKI_NODES_FNAME = HELSINKI_DATA_BASEDIR + "main.day.nodes.csv"
HELSINKI_TRANSIT_CONNECTIONS_FNAME = os.path.join(HELSINKI_DATA_BASEDIR, "main.day.temporal_network.csv")
HELSINKI_TRANSFERS_FNAME = os.path.join(HELSINKI_DATA_BASEDIR, "main.day.transfers.csv")

DEFAULT_TILES = "CartoDB positron"
DARK_TILES = "CartoDB dark_matter"

DAY_START = 1475438400 + 3600
DAY_END = DAY_START + 24 * 3600

ROUTING_START_TIME_DEP = DAY_START + 8 * 3600  # 07:00 AM

ANALYSIS_START_TIME_DEP = ROUTING_START_TIME_DEP
ANALYSIS_END_TIME_DEP = ROUTING_START_TIME_DEP + 1 * 3600

ROUTING_END_TIME_DEP = ROUTING_START_TIME_DEP + 3 * 3600

# AALTO_STOP_ID = 3363
# # 3363,2222211,E2229,Alvar Aallon puisto,Otaniementie,60.183984,24.829145,,0,0,3363
#
# ITAKESKUS_STOP_ID = 2179
# # 2179,1453601,0023,Itäkeskus,Itäkeskus,60.209989,25.077984,7534.0,0,0,7534
#
# MUNKKIVUORI_STOP_ID = 1161
# # 1161,1304137,1396,Munkkivuori,Huopalahdentie,60.20595,24.87998,,0,2,1161

TIMEZONE = pytz.timezone("Europe/Helsinki")

# from jinja2 import defaults
# defaults.LSTRIP_BLOCKS = True
# defaults.KEEP_TRAILING_NEWLINE = False
# defaults.TRIM_BLOCKS = True

AALTO_UNIVERSITY_LAT_LON = (60.185944, 24.826750)
ITAKESKUS_LAT_LON = (60.211942, 25.082946)
MUNKKIVUORI_LAT_LON = (60.206037, 24.877290)

AALTO_UNIVERSITY_ID = "ADDED_AALTO_UNIVERSITY"
ITAKESKUS_ID = "ADDED_ITAKESKUS_UNIVERSITY" # Should have been "ADDED_ITAKESKUS" (There is no University in Itakeskus..)
MUNKKIVUORI_ID = "ADDED_MUNKKIVUORI"

SWIMMING_HALL_ID_PREFIX = "SWIMMING_HALL_"

EXTRA_LOCATIONS = [
    {'id': AALTO_UNIVERSITY_ID,
     'lat': AALTO_UNIVERSITY_LAT_LON[0],
     'lon': AALTO_UNIVERSITY_LAT_LON[1]},
    {'id': ITAKESKUS_ID,
     'lat': ITAKESKUS_LAT_LON[0],
     'lon': ITAKESKUS_LAT_LON[1]},
    {'id': MUNKKIVUORI_ID,
     'lat': MUNKKIVUORI_LAT_LON[0],
     'lon': MUNKKIVUORI_LAT_LON[1]}
]

LONG_DISTANCE_STOPS = [

]

def get_stop_I_by_stop_id(stop_id):
    from gtfspy.gtfs import GTFS
    g = GTFS(IMPORTED_DATABASE_PATH)
    query = "SELECT stop_I FROM stops WHERE stop_id='" + str(stop_id) + "';"
    print(stop_id)
    stop_I = g.execute_custom_query(query).fetchone()[0]
    return stop_I

def get_swimming_hall_stop_Is():
    from gtfspy.gtfs import GTFS
    g = GTFS(IMPORTED_DATABASE_PATH)
    query = 'SELECT stop_I FROM stops WHERE SUBSTR(stop_id, 0, 7)="SWIMMI";'
    stop_Is = [el[0] for el in g.execute_custom_query(query).fetchall()]
    return stop_Is

import matplotlib as mpl
mpl.style.use('classic')

import smopy
smopy.TILE_SERVER = "https://cartodb-basemaps-1.global.ssl.fastly.net/dark_all/{z}/{x}/{y}.png"


# SHALOMMITA P
# 71200640
# LAB 10 DICTIONARY

# INPUT
# OPSI PILIHAN
# BARANG YANG AKAN DITAMBAH/DIHAPUS
# JUMLAH BARANG YG AKAN DITAMBAH

# PROSES
# UBAH KE DALAM DICT
# LAKUKAN PERCABANGAN dan Perulangan While

# OUTPUT
import sys

keranjang={}

def utama():
    print("""
    Keranjang Stok Toko Syahdu 5.5 Big Sale
    ========================================
    1. Menambahkan Barang
    2. Menghapus Barang
    3. Melihat Keranjang
    4. Keluar
    """)

def pil():
    opsi=int(input("Pilihan Anda (1/2/3/4): "))
    while opsi != 0:
        if opsi == 1:
            inp=int(input("Jumlah barang yang akan ditambahkan: "))
            for i in range(inp):
                barang=input("Tambahkan barang: ")
                jml=int(input("Jumlah: "))
                keranjang[barang]=jml
            utama()
            pil()
        elif opsi == 2:
            barang=input("Barang yang akan dihapus: ")
            del(keranjang[barang])
            utama()
            pil()
        elif opsi == 3:
            for barang in keranjang:
                print(barang,": ",keranjang[barang])
            utama()
            pil()
        elif opsi == 4:
            print("Anda sudah keluar dari Keranjang Toko Syahdu")
            sys.exit()
        else:
            print("Pilihan Anda tidak tersedia \nSilakan cek ulang.")
            utama()
            pil()

utama()
pil()


import os,glob,sys,gc
import pyathena.dump_zprof as dz

pid = sys.argv[1]

base = '/tigress/changgoo/'
pdir=pid + '/'

if os.path.isdir(base+pdir):

    outdir='zprof_P'
    if not os.path.isdir(base+pdir+outdir+'/'): os.mkdir(base+pdir+outdir)

    dc=dz.data_container(pid,base=base,pdir=pdir)
    for f in dc.vtkfiles:
        dirname=base+pdir+outdir+'/'
        fbase=os.path.basename(f)
        zpf=dirname+fbase.replace('vtk','zprof.P.nc')
        zpf_icm=dirname+fbase.replace('vtk','zprof-icm.P.nc')
        if not (os.path.isfile(zpf) and os.path.isfile(zpf_icm)):
            zpds,zpds_icm=dz.dump_zprof_one_P(f,dc,icm_field='s4')
            zpds[['pP','mP']].to_netcdf(zpf)
            zpds_icm[['pP','mP']].to_netcdf(zpf_icm)
            n=gc.collect()
            print('GC objects:',n)


from django.urls import path
from .views import (IdeaListView,
					IdeaDetailView,
					IdeaCreateView,
					IdeaUpdateView,
					IdeaDeleteView
					)
from . import views

urlpatterns = [
    path('', IdeaListView.as_view(), name='ideabox-home'),
    path('ideas/new', IdeaCreateView.as_view(), name='ideas-create'),
    path('ideas/<int:pk>/', IdeaDetailView.as_view(), name='ideas-detail'),
    path('ideas/<int:pk>/update/', IdeaUpdateView.as_view(), name='ideas-update'),
    path('ideas/<int:pk>/delete/', IdeaDeleteView.as_view(), name='ideas-delete'),
	path('about/', views.about, name='ideabox-about')

    ]


def findPeakElement(self, nums):
    """
    :type nums: List[int]
    :rtype: int
    """
    low = 0
    hight = len(nums) - 1
    while low < hight:
        mid = (low + hight) // 2
        if nums[mid] > nums[mid + 1]:
            hight = mid
        else:
            low = mid + 1
    return low  #no matter high or low


import argparse
from multiprocessing import connection
from awscrt import io, mqtt, exceptions
from awsiot import mqtt_connection_builder
from dotenv import load_dotenv
import sys
import threading
import time
from uuid import uuid4
import json
import platform
import random
import os
import time
# Load local configuration settings
# a .env file must be located in the directory and include definitions for:
# AWS_ENDPOINT, CERT_FILE, PRI_KEY_FILE, and ROOT_CA_FILE as
load_dotenv()

parser = argparse.ArgumentParser(description="Send and receive messages through and MQTT connection.")
parser.add_argument('--sample_frequency',type=float, help='how often messages are generated and sent to AWS in seconds')

# Callback when connection is accidentally lost.
def on_connection_interrupted(connection, error, **kwargs):
    print("Connection interrupted. error: {}".format(error))

# Callback when an interrupted connection is re-established.
def on_connection_resumed(connection, return_code, session_present, **kwargs):
    print("Connection resumed. return_code: {} session_present: {}".format(return_code, session_present))

    if return_code == mqtt.ConnectReturnCode.ACCEPTED and not session_present:
        print("Session did not persist. Resubscribing to existing topics...")
        resubscribe_future, _ = connection.resubscribe_existing_topics()

        # Cannot synchronously wait for resubscribe result because we're on the connection's event-loop thread,
        # evaluate result with a callback instead.
        resubscribe_future.add_done_callback(on_resubscribe_complete)

def on_resubscribe_complete(resubscribe_future):
        resubscribe_results = resubscribe_future.result()
        print("Resubscribe results: {}".format(resubscribe_results))

        for topic, qos in resubscribe_results['topics']:
            if qos is None:
                sys.exit("Server rejected resubscribe to topic: {}".format(topic))

# Callback when the subscribed topic receives a message
def on_message_received(topic, payload, dup, qos, retain, **kwargs):
    print("Received message from topic '{}': {}".format(topic, payload))

def gen_fake_data(start=20.0, min=20.0, max=25.0):
    trending_up = True
    cur = start
    change_options = [0, 0.1, 0.2, -0.1]
    weights = [80, 8, 4, 8]
    while(True):
        change_val = random.choices(
            population= change_options,
            weights= weights
        )[0]
        cur = cur + change_val if trending_up else cur - change_val
        cur = round(cur, 3)
        if cur <= min:
            trending_up = True
        elif cur >= max:
            trending_up = False
        yield cur

if __name__ == '__main__':
    received_all_event = threading.Event()
    args, unknown = parser.parse_known_args()

    CLIENT_ID = 'test' + str(uuid4())
    TOPIC = 'test/temp'
    DEFAULT_TIMEOUT = 5
    timeout = args.sample_frequency if args.sample_frequency else DEFAULT_TIMEOUT

    # Spin up resources
    event_loop_group = io.EventLoopGroup(1)
    host_resolver = io.DefaultHostResolver(event_loop_group)
    client_bootstrap = io.ClientBootstrap(event_loop_group, host_resolver)

    mqtt_connection = mqtt_connection_builder.mtls_from_path(
        endpoint=os.getenv('AWS_ENDPOINT'),
        port=443,
        cert_filepath=os.getenv('CERT_FILE'),
        pri_key_filepath=os.getenv('PRI_KEY_FILE'),
        client_bootstrap=client_bootstrap,
        ca_filepath=os.getenv('ROOT_CA_FILE'),
        on_connection_interrupted=on_connection_interrupted,
        on_connection_resumed=on_connection_resumed,
        client_id=CLIENT_ID,
        clean_session=False,
        keep_alive_secs=30,
        http_proxy_options=None)

    print(f"Connecting to {os.getenv('AWS_ENDPOINT')} with client ID '{CLIENT_ID}'...")

    connection_attempts = 0
    while connection_attempts < 6:
        connection_attempts += 1
        try:
            connect_future = mqtt_connection.connect()
            connect_future.result()
            print("Connected!")
            break
        except exceptions.AwsCrtError:
            print("Connection Failed, retring...")
            mqtt_connection.disconnect()
            time.sleep(10)

    # Subscribe
    print("Subscribing to topic '{}'...".format(TOPIC))
    subscribe_future, packet_id = mqtt_connection.subscribe(
        topic=TOPIC,
        qos=mqtt.QoS.AT_LEAST_ONCE,
        callback=on_message_received)

    subscribe_result = subscribe_future.result()
    print("Subscribed with {}".format(str(subscribe_result['qos'])))

    # Publish message to server desired number of times.
    # This step is skipped if message is blank.
    # This step loops forever if count was set to 0.

    data_gen = gen_fake_data()
    while (True):
        message = {
            'Device_ID': platform.node(),
            'Data': {
                'Tempurature': next(data_gen)
            }
        }
        print("Publishing message to topic '{}': {}".format(TOPIC, message))
        message_json = json.dumps(message)
        mqtt_connection.publish(
            topic=TOPIC,
            payload=message_json,
            qos=mqtt.QoS.AT_LEAST_ONCE)
        time.sleep(timeout)


# -*- coding: utf-8 -*-
# @Time    : 2019/8/23 21:58
# @Author  : zhoujun
import time
from utils import schedulers

from base import BaseTrainer

class Trainer(BaseTrainer):
    def __init__(self, config, model, criterion, train_loader, val_loader=None,
                 weights_init=None):
        super(Trainer, self).__init__(config, model, criterion, weights_init)
        self.train_loader = train_loader
        self.train_loader_len = len(train_loader)
        self.val_loader = val_loader
        self.val_loader_len = len(val_loader) if val_loader is not None else 0

        self.scheduler = schedulers.PolynomialLR(self.optimizer,self.epochs * self.train_loader_len)

        self.logger.info(
            'train dataset has {} samples,{} in dataloader, val dataset has {} samples,{} in dataloader'.format(
                self.train_loader.dataset_len,
                self.train_loader_len,
                self.val_loader.dataset_len if val_loader is not None else 0,
                self.val_loader_len))

    def _train_epoch(self, epoch):
        self.model.train()
        epoch_start = time.time()
        batch_start = time.time()
        train_loss = 0.
        for i, (images, labels, training_masks) in enumerate(self.train_loader):
            if i >= self.train_loader_len:
                break
            self.global_step += 1
            self.scheduler.step()
            lr = self.optimizer.param_groups[0]['lr']

            # 数据进行转换和丢到gpu
            cur_batch_size = images.size()[0]
            images, labels, training_masks = images.to(self.device), labels.to(self.device), training_masks.to(
                self.device)

            preds = self.model(images)
            loss_all, loss_tex, loss_ker, loss_agg, loss_dis = self.criterion(preds, labels, training_masks)
            # backward
            self.optimizer.zero_grad()
            loss_all.backward()
            self.optimizer.step()

            # loss 和 acc 记录到日志
            loss_all = loss_all.item()
            loss_tex = loss_tex.item()
            loss_ker = loss_ker.item()
            loss_agg = loss_agg.item()
            loss_dis = loss_dis.item()
            train_loss += loss_all

            if self.tensorboard_enable:
                # write tensorboard
                self.writer.add_scalar('TRAIN/loss_all', loss_all, self.global_step)
                self.writer.add_scalar('TRAIN/loss_tex', loss_tex, self.global_step)
                self.writer.add_scalar('TRAIN/loss_ker', loss_ker, self.global_step)
                self.writer.add_scalar('TRAIN/loss_agg', loss_agg, self.global_step)
                self.writer.add_scalar('TRAIN/loss_dis', loss_dis, self.global_step)
                self.writer.add_scalar('TRAIN/lr', lr, self.global_step)

            if (i + 1) % self.display_interval == 0:
                batch_time = time.time() - batch_start
                self.logger.info(
                    '[{}/{}], [{}/{}], global_step: {}, Speed: {:.1f} samples/sec, loss_all: {:.4f}, loss_tex: {:.4f}, loss_ker: {:.4f}, loss_agg: {:.4f}, loss_dis: {:.4f}, lr:{:.6}, time:{:.2f}'.format(
                        epoch, self.epochs, i + 1, self.train_loader_len, self.global_step,
                                            self.display_interval * cur_batch_size / batch_time,
                        loss_all, loss_tex, loss_ker, loss_agg, loss_dis, lr, batch_time))
                batch_start = time.time()
        return {'train_loss': train_loss / self.train_loader_len, 'lr': lr, 'time': time.time() - epoch_start,
                'epoch': epoch}

    def _eval(self):
        pass

    def _on_epoch_finish(self):
        self.logger.info('[{}/{}], train_loss: {:.4f}, time: {:.4f}, lr: {}'.format(
            self.epoch_result['epoch'], self.epochs, self.epoch_result['train_loss'], self.epoch_result['time'],
            self.epoch_result['lr']))

        save_best = False
        if self.val_loader is not None:
            epoch_eval_dict = self._eval()

            val_acc = epoch_eval_dict['n_correct'] / self.val_loader.dataset_len
            edit_dis = epoch_eval_dict['edit_dis'] / self.val_loader.dataset_len

            if self.tensorboard_enable:
                self.writer.add_scalar('EVAL/acc', val_acc, self.global_step)
                self.writer.add_scalar('EVAL/edit_distance', edit_dis, self.global_step)

            self.logger.info('[{}/{}], val_acc: {:.6f}'.format(self.epoch_result['epoch'], self.epochs, val_acc))

            net_save_path = '{}/CRNN_{}_loss{:.6f}_val_acc{:.6f}.pth'.format(self.checkpoint_dir,
                                                                             self.epoch_result['epoch'],
                                                                             self.epoch_result['train_loss'],
                                                                             val_acc)
            if val_acc > self.metrics['val_acc']:
                save_best = True
                self.metrics['val_acc'] = val_acc
                self.metrics['best_model'] = net_save_path
        else:
            net_save_path = '{}/CRNN_{}_loss{:.6f}.pth'.format(self.checkpoint_dir,
                                                               self.epoch_result['epoch'],
                                                               self.epoch_result['train_loss'])
            if self.epoch_result['train_loss'] < self.metrics['train_loss']:
                save_best = True
                self.metrics['train_loss'] = self.epoch_result['train_loss']
                self.metrics['best_model'] = net_save_path
        self._save_checkpoint(self.epoch_result['epoch'], net_save_path, save_best)

    def _on_train_finish(self):
        for k, v in self.metrics.items():
            self.logger.info('{}:{}'.format(k, v))
        self.logger.info('finish train')


"""Tests for MolInventory objects, focusing on the provided SmilesListInventory."""

import pytest

from syntheseus.search.chem import Molecule
from syntheseus.search.mol_inventory import SmilesListInventory

PURCHASABLE_SMILES = ["CC", "c1ccccc1", "CCO"]
NON_PURCHASABLE_SMILES = ["C", "C1CCCCC1", "OCCO"]

@pytest.fixture
def example_inventory() -> SmilesListInventory:
    """Returns a SmilesListInventory with arbitrary molecules."""
    return SmilesListInventory(PURCHASABLE_SMILES)

def test_is_purchasable(example_inventory: SmilesListInventory) -> None:
    """
    Does the 'is_purchasable' method return true only for purchasable SMILES?
    """
    for sm in PURCHASABLE_SMILES:
        assert example_inventory.is_purchasable(Molecule(sm))

    for sm in NON_PURCHASABLE_SMILES:
        assert not example_inventory.is_purchasable(Molecule(sm))

def test_fill_metadata(example_inventory: SmilesListInventory) -> None:
    """
    Does the 'fill_metadata' method accurately fill the metadata?
    Currently it only checks that the `is_purchasable` key is filled correctly.
    At least it should add the 'is_purchasable' key.
    """

    for sm in PURCHASABLE_SMILES + NON_PURCHASABLE_SMILES:
        # Make initial molecule without any metadata
        mol = Molecule(sm)
        assert "is_purchasable" not in mol.metadata

        # Fill metadata and check that it is filled accurately.
        # To also handle the case where the metadata is filled, we run the test twice.
        for _ in range(2):
            example_inventory.fill_metadata(mol)
            assert mol.metadata["is_purchasable"] == example_inventory.is_purchasable(mol)

            # corrupt metadata so that next iteration the metadata is filled
            # and should be overwritten.
            # Type ignore is because we fill in random invalid metadata
            mol.metadata["is_purchasable"] = "abc"  # type: ignore[typeddict-item]

def test_purchasable_mols(example_inventory: SmilesListInventory) -> None:
    """
    Does the 'purchasable_mols' method work correctly? It should return a collection
    of all the purchasable molecules.
    """
    expected_set = {Molecule(sm) for sm in PURCHASABLE_SMILES}
    observed_set = set(example_inventory.purchasable_mols())
    assert expected_set == observed_set


__author__ = 'Administrator'

"""
    argument parser with choice argument
"""
import argparse

parser = argparse.ArgumentParser()

parser.add_argument("square", type=int, help="Input a number which you want to compute square.")
parser.add_argument("-v", "--verbose", choices=[1, 2, 3], type=int, help="Show detail information of result")

arguments = parser.parse_args()
resultSet = arguments.square ** 2

if arguments.verbose:
    print("The {0} square result is {1} and the verbose is {2}".format(arguments.square, resultSet, arguments.verbose))
else:
    print(resultSet)


__author__ = 'Christoph'

import nltk
import re
import distance
from nltk.corpus import wordnet as wn
from nltk.corpus import wordnet_ic
from gensim.models import word2vec
from nltk.corpus import PlaintextCorpusReader
from scipy.stats.stats import pearsonr
import os.path
import logging

# run this only if directly called and not when imported as a library

ic = None
w2v_model = None

def loadGoldData(filename, correctorFactor):
    with open(filename, 'r') as file:
        lines = file.readlines()
        simGold = []
         # scan the string array
        i = 0
        while i < len(lines):
            line = lines[i].strip()
            i += 1
            # skip all lines starting with blank, newline or 190
            if line.startswith("#"):
                continue
            if line.startswith("\n"):
                i += 1
                continue
            splits = line.split(" ") #change space or tab
            correctedsplits = [ ]
            correctedsplits.append(splits[0])
            correctedsplits.append(splits[1])
            correctedsplits.append(splits[2])
            correctedsplits.append(splits[3])

            #correctedsplits.append(float(splits[2]) * correctorFactor)
            simGold.append(correctedsplits)
        return simGold

def computeLinSimilarity(term1, term2):
    global ic
    if not ic:
        #ic = wordnet_ic.ic('ic-semcor.dat')
        ic = wordnet_ic.ic('ic-brown.dat')
    w1_syns = wn.synsets(term1)
    w2_syns = wn.synsets(term2)
    maxsim = 0
    for w1s in w1_syns:
        for w2s in w2_syns:
            try:
                sim = wn.lin_similarity(w1s, w2s, ic)
                if sim > maxsim:
                    maxsim = sim
            except Exception:
                pass
    return maxsim

def computeW2VSimilarity(term1, term2):
    global w2v_model
    model_filename="/opt3/home/lofi/word2vec_models/GoogleNews-vectors-negative300.bin.gz" #change output/outputFinal
    #GoogleNews-vectors-negative300.bin.gz
    #freebase-vectors-skipgram1000.bin.gz
    #/opt3/home/lofi/word2vec_models/freebase-vectors-skipgram1000-en.bin.gz
    #opt3/home/pratima/data/output.model.bin/
    #/opt3/home/lofi/word2vec_models/GoogleNews-vectors-negative300.bin.gz

    if (w2v_model is None):
        print("Loading W2V")
        w2v_model = word2vec.Word2Vec.load_word2vec_format(model_filename, binary=True)
    return w2v_model.similarity(term1, term2)

def analogy():
   model_filename="/opt3/home/lofi/word2vec_models/GoogleNews-vectors-negative300.bin.gz"
   model=word2vec.Word2Vec.load_word2vec_format(model_filename, binary=True)
   file_path="/opt3/home/thakkar/finalcat.txt"
   apr = loadGoldData(file_path, 1.0 / 10)

   #print(apr)
   for value in apr:
    print(value[0],value[1],value[2],value[3])
    temp=model.most_similar(positive=[value[0], value[3]], negative=[value[2]],topn=1)
    #temp=model.n_similarity([value[0], value[1]],[value[2],value[3]])
    print(temp)

    #model.similarity('woman', 'man')
    #Distance=distance.nlevenshtein(value[3]

   #temp is a list(0) strip and use it later

if __name__ == '__main__':
    print("LOADING")
    #gold = loadGoldData("EN-MC-30.txt", 1.0 / 4)
    #gold = loadGoldData("EN-RG-65.txt", 1.0 / 4)
    #gold = loadGoldData("EN-WS-353-related.txt", 1.0 / 10)
    #gold = loadGoldData("EN-WS-353-similar.txt", 1.0 / 10)
    #gold = loadGoldData("EN-WS-353-all.txt", 1.0 / 10)
    #gold = loadGoldData("EN-ES-353-verbose.txt", 1.0 / 10)
    #gold = loadGoldData("MEN-full.txt", 1.0 / 10)
    #gold = loadGoldData("/opt3/home/pratima/data/analogy.txt", 1.0 / 5)
    print("COMPUTING")
    analogy()

    ##
   #

    #
    similarity_vector = []
    reference_vector = []
   # f=open('/opt3/home/pratima/data/output.model.bin','rb')
    #for g in gold:
        #sim = computeLinSimilarity(g[0], g[1])
        #byte = f.read()
        #if g != byte:
            #sim = 0.105
        #else:
     #   sim = computeW2VSimilarity(g[0], g[1])
      #  similarity_vector.append(sim)
       # reference_vector.append(g[2])
        #print("Similarity: %20s : %-20s measured: %5.3f correct:%5.3f " % ( g[0], g[1], sim, g[2]))
    #correlation = pearsonr(reference_vector, similarity_vector)
    #print("Correlation %4.3f" % correlation[0])


# Adapted from torchvision

import bisect
from collections import defaultdict
import copy
import numpy as np

from torch.utils.data.sampler import BatchSampler, Sampler

class GroupedBatchSampler(BatchSampler):
    """
    Wraps another sampler to yield a mini-batch of indices.
    It enforces that the batch only contain elements from the same group.
    It also tries to provide mini-batches which follows an ordering which is
    as close as possible to the ordering from the original sampler.
    Arguments:
        sampler (Sampler): Base sampler.
        group_ids (list[int]): If the sampler produces indices in range [0, N),
            `group_ids` must be a list of `N` ints which contains the group id of each sample.
            The group ids must be a continuous set of integers starting from
            0, i.e. they must be in the range [0, num_groups).
        batch_size (int): Size of mini-batch.
    """
    def __init__(self, sampler, group_ids, batch_size):
        if not isinstance(sampler, Sampler):
            raise ValueError(
                "sampler should be an instance of "
                f"torch.utils.data.Sampler, but got sampler={sampler}"
            )
        self.sampler = sampler
        self.group_ids = group_ids
        self.batch_size = batch_size

    def __iter__(self):
        buffer_per_group = defaultdict(list)
        samples_per_group = defaultdict(list)

        num_batches = 0
        for idx in self.sampler:
            group_id = self.group_ids[idx]
            buffer_per_group[group_id].append(idx)
            samples_per_group[group_id].append(idx)
            if len(buffer_per_group[group_id]) == self.batch_size:
                yield buffer_per_group[group_id]
                num_batches += 1
                del buffer_per_group[group_id]
            assert len(buffer_per_group[group_id]) < self.batch_size

        # now we have run out of elements that satisfy
        # the group criteria, let's return the remaining
        # elements so that the size of the sampler is
        # deterministic
        expected_num_batches = len(self)
        num_remaining = expected_num_batches - num_batches
        if num_remaining > 0:
            # for the remaining batches, take first the buffers with largest number
            # of elements
            for group_id, _ in sorted(buffer_per_group.items(),
                                      key=lambda x: len(x[1]), reverse=True):
                remaining = self.batch_size - len(buffer_per_group[group_id])
                buffer_per_group[group_id].extend(
                    samples_per_group[group_id][:remaining])
                assert len(buffer_per_group[group_id]) == self.batch_size
                yield buffer_per_group[group_id]
                num_remaining -= 1
                if num_remaining == 0:
                    break
        assert num_remaining == 0

    def __len__(self):
        return len(self.sampler) // self.batch_size

def _quantize(x, bins):
    bins = copy.deepcopy(bins)
    bins = sorted(bins)
    quantized = list(map(lambda y: bisect.bisect_right(bins, y), x))
    return quantized

def create_aspect_ratio_groups(dataset, k=0):
    bins = (2 ** np.linspace(-1, 1, 2 * k + 1)).tolist() if k > 0 else [1.0]
    groups = _quantize(dataset._aspect_ratios, bins)
    # count number of elements per group
    counts = np.unique(groups, return_counts=True)[1]
    fbins = [0] + bins + [np.inf]
    print(f"Using {fbins} as bins for aspect ratio quantization")
    print(f"Count of instances per bin: {counts}")
    return groups


# coding=utf-8
import os
from collections import namedtuple
import concurrent.futures

import requests

from settings import *

Album = namedtuple('Album', 'uid id name size type')
Photo = namedtuple('Photo', 'name feed url')

def delay(second):
    """
    装饰器，将某个函数执行后延迟second秒
    """
    from time import sleep

    def _delay(func):
        def delayed_func(*args, **kwargs):
            ret = func(*args, **kwargs)
            sleep(second)
            return ret
        return delayed_func

    return _delay

def get_rand():
    """
    返回一个特定的随机数
    经过测试，参数中的__rnd实际上是以毫秒为单位的时间戳
    """
    from time import time
    return int(round(time() * 1000))

def get_page(url, params=None, cookies=None, attr='text'):
    """
    返回GET某url返回的数据 即Response.attr
    attr为None时返回Response本身
    """
    cookies = cookies or COOKIES
    req = requests.get(url, params=params, cookies=cookies)
    return attr and req.__getattribute__(attr) or req

def get_json(url, params):
    """
    返回GET某url返回的json数据中的data部分
    """
    from json import loads

    json_content = get_page(url, params)
    try:
        data = loads(json_content)
        assert data.get('result')
        assert data.get('data'), '获取数据不含data项'
    except Exception as e:
        print('获取数据失败，请更新Cookies后重试')
        return None

    return data['data']

def get_album_list(uid, page=1, count=20):
    """
    返回某用户相册列表，具体内容参见Album命名元组
    这里假定相册数量不超过20，特殊情况需修改page/count参数
    """
    log.info(Fore.GREEN + Style.BRIGHT + '开始获取 {0} 的相册列表'.format(uid))

    # 获取数据
    url = 'http://photo.weibo.com/albums/get_all'
    params = {
        'uid': uid,
        'page': page,
        'count': count,
        '__rnd': get_rand()
    }
    data = get_json(url, params)

    # 相册个数
    total = data.get('total')
    log.info(Fore.BLUE + '获取到 {0} 个相册列表'.format(total))

    # 相册列表
    album_list = data.get('album_list')
    result = [Album(uid=album['uid'],
                    id=album['album_id'],
                    name=album['caption'],
                    size=album['count']['photos'],
                    type=album['type'])
              for album in album_list]

    return result

def get_photo_ids(album, count=None, page=1):
    """
    返回某相册所有图片的id
    默认请求所有图片，也可修改count/page参数
    """
    if count == None:
        count = album.size + 1
    url = 'http://photo.weibo.com/photos/get_all'
    params = {
        'uid': album.uid,
        'album_id': album.id,
        'count': count,
        'page': page,
        'type': album.type,
        '__rnd': get_rand(),
    }

    data = get_json(url, params)
    ids = [p['photo_id'] for p in data['photo_list']]
    log.info(Fore.BLUE + '获取到 {0} 个项目'.format(len(ids)))
    return ids

def get_large_photos(album, photo_ids):
    """
    根据相册及图片ids返回大图数据
    """
    if not photo_ids:
        return list()

    url = 'http://photo.weibo.com/photos/get_multiple'
    params = {
        'uid': album.uid,
        'ids': ','.join(photo_ids),
        'type': album.type,
    }

    data = get_json(url, params)
    large = list()
    for i in photo_ids:
        if data[i]:
            large.append(Photo(name=data[i]['pic_name'],
                               feed=data[i].get('feed_id'),
                               url=data[i]['large_pic_tmp']))
        else:
            err = '《%s》的图片 %s 不存在或已被删除' % (album.name, i)
            log.warning(Fore.YELLOW + err)
    log.info(Fore.BLUE + '获取到 {0} 个大图'.format(len(large)))
    return large

def get_album_path(album):
    """
    生成相册保存路径，不存在则创建
    """
    path = './downloads/{name}/{album}'.format(
        name=get_username(album.uid),
        album=album.name
    )
    if not os.path.exists(path):
        os.makedirs(path)
    return path

def get_username(uid):
    """
    根据uid获取用户名
    """
    import re

    url = 'http://photo.weibo.com/{uid}/albums'
    content = get_page(url.format(uid=uid))
    name = re.search(r'title>(?P<name>.*?) -', content)
    return name.group('name')

def get_picname(photo):
    """
    生成保存的图片文件名
    """
    l = list()
    if photo.feed:
        l.append(photo.feed)
    l.append(photo.name)
    return '_'.join(l)

@delay(wait_second)
def down_pic(photo, path):
    """
    根据相册及图片，进行下载操作
    保存路径为'./相册名/图片名'
    """
    filename = get_picname(photo)
    path = os.path.join(path, filename)
    is_downloaded = False
    if not os.path.exists(path):
        is_downloaded = True
        content = get_page(photo.url, attr='content')
        with open(path, 'wb') as f:
            f.write(content)
    return is_downloaded, path

def pagenavi(total, count):
    """
    分页器，一共total个项目，每页count个，
    """
    max_page = int((total + count - 1) / count)
    for page in range(max_page):
        yield page + 1, max_page

def down_album(album, page_size=100):
    """
    执行下载album的操作
    每页请求的图片个数page_size默认为100（太大了会被服务器断开连接）
    """
    with concurrent.futures.ThreadPoolExecutor() as executor:
        future_to_pic = dict()

        # 对相册进行分页
        for page, tot in pagenavi(album.size, page_size):
            log.info(Fore.CYAN + '《{0}》{1}/{2}'.format(album.name, page, tot))

            # 获取该页包含图片id及大图
            ids = get_photo_ids(album, page_size, page)
            large_photos = get_large_photos(album, ids)

            # 开始任务
            album_path = get_album_path(album)
            future = {executor.submit(down_pic, pic, album_path): pic
                      for pic in large_photos}
            future_to_pic.update(future)
        else:
            tot = vars().get('tot', 0)
            log.info(Fore.CYAN + '《{0}》共发现 {1} 页'.format(album.name, tot))

        # 等待任务完成
        cound, total = 0, len(future_to_pic)
        for future in concurrent.futures.as_completed(future_to_pic):
            pic = future_to_pic[future]
            try:
                cound += 1
                count_info = '%d/%d ' % (cound, total)
                is_downloaded, path = future.result()
            except Exception as e:
                msg = '微博 %s 中的图片 %s 产生了异常: %s' % (pic.feed, pic.name, e)
                log.info(Fore.RED + count_info + msg)
            else:
                style = is_downloaded and Style.NORMAL or Style.DIM
                log.info(Fore.GREEN + style + count_info + path)
        else:
            color = Fore.GREEN + Style.BRIGHT
            log.info(color + '《{0}》 已完成'.format(album.name))

def run(uid):
    """
    执行对uid的操作
    """
    for album in get_album_list(uid):
        down_album(album)
    log.info(Fore.GREEN + Style.BRIGHT + '全部任务已完成')

if __name__ == '__main__':
    target = ['']
    for t in target:
        run(t)


# -*- coding: utf-8 -*-
"""
Created on Sun Apr 24 08:31:47 2022

@author: frede
"""

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import os
os.chdir(os.path.dirname(__file__))

from Helper_Functions.Custom_functions import evaluation_functions

#%% Loading answers from dermotologists and subsetting with only relevant participants

truth_path = 'Evaluation data/Diagnoses.xls'
guess_path = 'Evaluation data/Full database anonymous.xlsx'

data, useful_participants, _, _ = evaluation_functions.csv_import(truth_path, guess_path)
data = data[data['OBSERVER ID'].isin(useful_participants)]

# Getting the correct labels and image name for each picture

im_path = 'Evaluation data/Skin cancer images'
im_shape = (256,256) # This is arbitrary as we only use the labels and image indexes

_, y_eval, idx = evaluation_functions.import_X_and_y(im_path, im_shape, data)
idx = [int(x) for x in idx]

# Loading predictions from CNN

prediction_path = 'Trained models/Multiclass-deep/Multiclass-deep/dropout_0.4/eval_files/eval_target.csv'

predictions = pd.read_csv(prediction_path)
pred = [x for x in predictions['prediction']]

# Defining number of iterations for each ensemble average

n_it = 1000

#%% Comparing human ensemble performances to human and algorithm baseline

# Human average performance

x_values, x_avg, y_values, y_avg = evaluation_functions.human_fpr_tpr(data, useful_participants, idx)
plt.scatter(x_avg, y_avg, c = 'blue', label = 'Human baseline')

# Algorithm baseline

df, auc = evaluation_functions.ROC_eval(pred, y_eval)
plt.plot(df['False positive rate'],df['True positive rate'], c = 'blue', label = 'CNN baseline')

# 3-man ensemble strategy

x_avg_three, y_avg_three, third_opinions = evaluation_functions.human_fpr_tpr_three_ensemble(data, useful_participants, idx, y_eval, n_it)
plt.scatter(x_avg_three, y_avg_three, c = 'green', label = '3-man ensemble average')
human_ensemble_performance = (x_avg,y_avg)

print(f'For the three human ensemble, the fpr is {x_avg_three} and tpr is {y_avg_three}')

# Full ensemble strategy

x_avg, y_avg = evaluation_functions.human_fpr_tpr_full_ensemble(data, useful_participants, idx, y_eval)
plt.scatter(x_avg, y_avg, c = 'red', label = 'Full ensemble score')

plt.title('Human ensemble performances')
plt.legend(loc = 'lower right')
plt.xlabel('False positive rate')
plt.ylabel('True positive rate')
plt.savefig('Visualizations/Human_ensembles.jpg')
plt.show()

print(f'The average number of third opinions in the 3-man ensemble is: {third_opinions}')

#%% Creating inner and outer list and comparing human and CNN performance on those sets

s_list = [2.5,3,4,6,8]

for s in s_list:

    # Getting auc scores
    print(f'The following results relate to s={s}')

    df_full, auc = evaluation_functions.ROC_eval(pred, y_eval)
    print(f'AUC score for the full prediction list: {auc}')

    pred_inner, pred_outer, y_inner, y_outer, indexes_inner, indexes_outer, idx_inner, idx_outer = evaluation_functions.inner_outer(pred, s, y_eval, idx)

    df_outer, auc = evaluation_functions.ROC_eval(pred_outer, y_outer)
    print(f'AUC for the outer list: {auc}')

    df_inner, auc = evaluation_functions.ROC_eval(pred_inner, y_inner)
    print(f'AUC for the inner list: {auc}')

    # Plotting everything together

    plt.plot(df_inner['False positive rate'],df_inner['True positive rate'], c = 'orange', label = 'CNN inner list')
    plt.plot(df_outer['False positive rate'],df_outer['True positive rate'], c = 'violet', label = 'CNN outer list')
    plt.plot(df_full['False positive rate'],df_full['True positive rate'], c = 'blue', label = 'CNN baseline')

    for i in [(idx_inner, 'orange'), (idx_outer, 'violet'), (idx, 'blue')]:
        if i[0] == idx_inner:
            label = 'Human inner list'
        elif i[0] == idx_outer:
            label = 'Human outer list'
        else:
            label = 'Human baseline'
        x_values, x_avg, y_values, y_avg = evaluation_functions.human_fpr_tpr(data, useful_participants, i[0])
        plt.scatter(x_avg,y_avg, c = i[1], label = label)

    plt.legend(loc = 'lower right')
    plt.title(f'Performance on inner and outer lists with s = {s}')
    plt.xlabel('False positive rate')
    plt.ylabel('True positive rate')
    plt.savefig(f'Visualizations/Inner_outer_{s}.jpg')
    plt.show()

#%% Generating average ROC/AUC analysis for each of the values of s

for s in s_list:

    pred_inner, pred_outer, y_inner, y_outer, indexes_inner, indexes_outer, idx_inner, idx_outer = evaluation_functions.inner_outer(pred, s, y_eval, idx)

    averages_inner, auc_inner = evaluation_functions.averaging_ROC(n_it, data, useful_participants, idx_inner, pred, y_eval)
    averages_outer, auc_outer = evaluation_functions.averaging_ROC(n_it, data, useful_participants, idx_outer, pred, y_eval)

    print(f'The following results relate to s = {s}')
    print(f'The average auc score substituting the inner list is {auc_inner}')
    print(f'The average auc score substituting the outer list is {auc_outer}')

    # And plotting together with the baseline function

    plt.plot(averages_inner['False positive rate'], averages_inner['True positive rate'], c = 'orange', label = 'Inner substitution')
    plt.plot(averages_outer['False positive rate'], averages_outer['True positive rate'], c = 'violet', label = 'Outer substitution')
    plt.plot(df_full['False positive rate'], df_full['True positive rate'], c = 'blue', label = 'CNN baseline')
    plt.scatter(x_avg, y_avg, c = 'blue', label = 'Human baseline') # The average values are coming from the previous cell
    plt.legend()
    plt.title(f'Augmented hybrid ensemble for s = {s}')
    plt.xlabel('False positive rate')
    plt.ylabel('True positive rate')
    plt.savefig(f'Visualizations/Hybrid_augmented_{s}.jpg')
    plt.show()

#%% Calculating the majority vote hybrid ensemble results

df_full, thresholds, scoring, third_opinions = evaluation_functions.hybrid_majority_vote(data, pred, y_eval, idx, n_it)

# Identifying the threshold and related x and y values for the point with the lowest number of third opinions

min_third_opinions = np.min(third_opinions)
print(f'The minimum number of third opinions necessary is {min_third_opinions}')
min_third_opinions_threshold = thresholds[third_opinions.index(min_third_opinions)]

# Getting the x and y coordinates for this point and deleting it from the general scoring

x, y = scoring[min_third_opinions_threshold]
scoring.pop(min_third_opinions_threshold)

# Generating the value to be plotted

scoring_values = list(scoring.values())
x_values = [x[0] for x in scoring_values]
y_values = [y[1] for y in scoring_values]

# Identifying the threshold and number of third opinions for the point with similar FPR and the point with similar TPR as the three human ensemble.

res = min(enumerate(x_values), key=lambda x: abs(x_avg_three - x[1]))
print(f'The number of third opinions to match the three human ensemple FPR score is {third_opinions[res[0]]}')

res = min(enumerate(y_values), key=lambda x: abs(y_avg_three - x[1]))
print(f'The number of third opinions to match the three human ensemble TPR score is {third_opinions[res[0]]}')

# Plotting the values

plt.scatter(x_values, y_values, c = 'grey', alpha = 0.3, label = 'Hybrid ensembles')
plt.scatter(x, y, c = 'red', label = 'Least third opinions hybrid ensemble')
plt.scatter(human_ensemble_performance[0], human_ensemble_performance[1], c = 'green', label = '3-man human ensemble')

# Plotting the baseline human and CNN performance for comparison

x_values, x_avg, y_values, y_avg = evaluation_functions.human_fpr_tpr(data, useful_participants, idx)
plt.scatter(x_avg, y_avg, c = 'blue', label = 'Human baseline')
plt.plot(df_full['False positive rate'], df_full['True positive rate'], c = 'blue', label = 'CNN baseline')
plt.title('Majority vote ensemble')
plt.legend(loc = 'lower right')
plt.xlabel('False positive rate')
plt.ylabel('True positive rate')
plt.savefig('Visualizations/Hybrid_majority.jpg')
plt.show()


from collections import deque
import sys
input = sys.stdin.readline

dr = [1, -1, 0, 0]
dc = [0, 0, -1, 1]

def bfs(r, c):
    global total_sheep, total_wolf
    queue = deque()
    queue.append([r, c])
    sheep, wolf = 0, 0

    if arr[r][c] == "o":
        sheep += 1
    elif arr[r][c] == "v":
        wolf += 1

    while queue:
        r, c = queue.popleft()

        for i in range(4):
            nr = r + dr[i]
            nc = c + dc[i]

            if 0 <= nr < R and 0 <= nc < C and visit[nr][nc] == 0 and arr[nr][nc] != "#":
                if arr[nr][nc] == "o":
                    sheep += 1
                if arr[nr][nc] == "v":
                    wolf += 1

                visit[nr][nc] = 1
                queue.append([nr, nc])

    if sheep and wolf:
        if sheep > wolf:
            total_wolf -= wolf
        else:
            total_sheep -= sheep

R, C = map(int, input().split())
arr = []
visit = [[0] * C for i in range(R)]
total_sheep, total_wolf = 0, 0

for i in range(R):
    a = list(input().strip())
    for j in range(C):
        if a[j] == "o":
            total_sheep += 1
        if a[j] == "v":
            total_wolf += 1
    arr.append(a)
for i in range(R):
    for j in range(C):
        if (arr[i][j] == "o" or arr[i][j] == "v") and visit[i][j] == 0:
            visit[i][j] = 1
            bfs(i, j)
print(total_sheep, total_wolf)


# -*- coding: utf-8 -*-
"""
collinearity

@author: David André Rodríguez Méndez (AndreRdz7)
"""

# Import libraries
import pandas as pd
import statsmodels.formula.api as smf
# Import dataset
data = pd.read_csv("./Advertising.csv")

# Check collinearity on Newpaper vs TV and Radio
linearmodel_n = smf.ols(formula="Newspaper~TV+Radio",data = data).fit()
rsquared_n = linearmodel_n.rsquared
VIF = 1/(1-rsquared_n)
VIF

# Check collinearity on TV vs Newspaper and Radio
linearmodel_n = smf.ols(formula="TV~Newspaper+Radio",data = data).fit()
rsquared_n = linearmodel_n.rsquared
VIF = 1/(1-rsquared_n)
VIF

# Check collinearity on Radio vs TV and Newspaper
linearmodel_n = smf.ols(formula="Radio~TV+Newspaper",data = data).fit()
rsquared_n = linearmodel_n.rsquared
VIF = 1/(1-rsquared_n)
VIF


import socket
import threading
import pickle
from view.gamewindow import GameWindow
from view.gamewindow import lock

HEADER = 64
PORT = 5051
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "!DISCONNECT"
SERVER = "192.168.65.183"
ADDR = (SERVER, PORT)

class Client():
    def __init__(self):
        self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.client.connect(ADDR)
        self.game_window = GameWindow(self)
        self.connected = True
        self.to_disconnect = False
        self.your_move = False
        self.game_end = False

    def send(self, msg):
        message = msg.encode(FORMAT)
        msg_length = len(message)
        send_length = str(msg_length).encode(FORMAT)
        send_length += b' ' * (HEADER - len(send_length))
        self.client.send(send_length)
        self.client.send(message)
        self.your_move = False

    def receive_pickle(self):
        msg_length = self.client.recv(HEADER).decode(FORMAT)
        if msg_length:
            msg_length = int(msg_length)
            msg = self.client.recv(msg_length)
            return pickle.loads(msg)

    def receive(self):
        wrapped_msg = self.receive_pickle()
        if wrapped_msg[0] == DISCONNECT_MESSAGE:
            self.game_end = True
            self.client.close()
            self.connected = False
        elif wrapped_msg[0] == "YOUR PLAYER":
            self.game_window.player = wrapped_msg[1]
        elif wrapped_msg[0] == "CHOOSE MOVE":
            self.your_move = True
            print("Co robisz?")
            if self.to_disconnect:
                self.send("!DISCONNECT")
            else:
                self.game_window.enable_buttons()

        elif wrapped_msg[0] == "OPPONENT": #dostajemy info o jednym oponencie
            lock.acquire()
            self.game_window.update_opponent(wrapped_msg[1])
            lock.release()
        elif wrapped_msg[0] == "OPPONENTS":  #dostajemy informacje o wszystkich oponentach
            lock.acquire()
            self.game_window.opponents = wrapped_msg[1]
            dict(sorted(self.game_window.opponents.items(), key=lambda item: item[1].id))
            lock.release()
        elif wrapped_msg[0] == "CARDS":
            self.game_window.table_cards = wrapped_msg[1]
        elif wrapped_msg[0] == "WINNERS":
            self.game_window.table_cards = []
            if not self.to_disconnect:
                self.game_window.stat_window.update_history(self.game_window.player,wrapped_msg[1])
        elif wrapped_msg[0] == "GAME INFO":
            lock.acquire()
            self.game_window.game_info = wrapped_msg[1]
            lock.release()
        elif wrapped_msg[0] == "POOL":
            lock.acquire()
            self.game_window.pool = wrapped_msg[1]
            lock.release()
        elif wrapped_msg[0] == "GAME ENDED":
            self.game_end = True
            self.client.close()
            self.connected = False
        else:
            return wrapped_msg[0]

    def disconnect_at_move(self):
        self.send("!DISCONNECT")

    def listening(self):
        while self.connected:
            self.receive()

if __name__ == "__main__":
    client = Client()
    stop_threads = False
    thread = threading.Thread(target=client.listening, args=())
    thread.start()
    nick = client.game_window.login()
    client.game_window.disable_buttons()
    client.send(nick)
    client.game_window.wait_for_players()
    client.game_window.main()


import math

def factorial(numStr):
    return math.factorial(int(numStr))

def decToBin(numStr):
    return format(int(numStr), 'b')

def binToDec(numStr):
    return int(numStr, 2)

def decToRoman(numStr):
    n = int(numStr)

    romans = [
        (1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'),
        (100, 'C'), (90, 'XC'), (50, 'L'), (40, 'XL'),
        (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')
    ]

    result = ''
    for vaule, letters in romans:
        while n >= vaule:
            result += letters
            n -= vaule

    return result

def romanToDec(numStr):
    Numdic = {'M': 1000, 'D': 500, 'C': 100, 'L': 50, 'X': 10, 'V': 5, 'I': 1}
    num = 0
    L = list(numStr)
    for i in range(1, len(L)):
        if Numdic[L[i-1]] >= Numdic[L[i]]:
            num += Numdic[L[i-1]]
        else:
            num -= Numdic[L[i-1]]
    num += Numdic[L[-1]]
    return num


# This file is the codebook for the dataset. It is used to convert the
# numeric values in the dataset to meaningful labels. It only includes the
# variables that were recoded to numeric labels.

codebook = {
    'journal_code': {
        'Journal of Applied Psychology': 0,
        'Personnel Psychology': 1,
        'Academy of Management Journal': 2,
        'Organizational Research Methods': 3,
        'Journal of Management': 4,
        'Organizational Behavior and Human Decision Processes': 5,
        'Journal of Organizational Behavior': 6,
        'The Leadership Quarterly': 7,
        'Journal of Occupational Health Psychology': 8,
        'Journal of Vocational Behavior': 9,
        'Journal of Business and Psychology': 10,
        'Journal of Occupational and Organizational Psychology': 11,
        'Educational and Psychological Measurement': 12,
        'Journal of Applied Social Psychology': 13,
        'Academy of Management Learning and Education': 14,
        'International Journal of Selection and Assessment': 15,
        'European Journal of Work and Organizational Psychology': 16,
        'Human Performance': 17,
        'Human Relations': 18,
        'Personality and Individual Differences': 19,
        'Applied Psychology: An International Review': 20,
        'Work & Stress': 21,
        'Group and Organization Management': 22,
        'Journal of Personnel Psychology': 23,
        'Journal of Managerial Psychology': 24,
        'Dissertations': 25
    },
    'journal': {
        0: 'Journal of Applied Psychology',
        1: 'Personnel Psychology',
        2: 'Academy of Management Journal',
        3: 'Organizational Research Methods',
        4: 'Journal of Management',
        5: 'Organizational Behavior and Human Decision Processes',
        6: 'Journal of Organizational Behavior',
        7: 'The Leadership Quarterly',
        8: 'Journal of Occupational Health Psychology',
        9: 'Journal of Vocational Behavior',
        10: 'Journal of Business and Psychology',
        11: 'Journal of Occupational and Organizational Psychology',
        12: 'Educational and Psychological Measurement',
        13: 'Journal of Applied Social Psychology',
        14: 'Academy of Management Learning and Education',
        15: 'International Journal of Selection and Assessment',
        16: 'European Journal of Work and Organizational Psychology',
        17: 'Human Performance',
        18: 'Human Relations',
        19: 'Personality and Individual Differences',
        20: 'Applied Psychology: An International Review',
        21: 'Work & Stress',
        22: 'Group and Organization Management',
        23: 'Journal of Personnel Psychology',
        24: 'Journal of Managerial Psychology',
        25: 'Dissertations'
    },
    'sample_source': {
        -1: 'unspecified',
        0: 'student',
        1: 'employee',
        2: 'student-employee',
        3: 'mixture'
    },
    'sample_recruitment': {
        -1: 'unspecified',
        0: 'university platform',
        1: 'crowdsource platform',
        2: 'workplace',
        3: 'social media',
        4: 'listserv',
        5: 'mixture',
        6: 'other'
    },
    'sample_method': {
        -1: 'unspecified',
        0: 'random',
        1: 'volunteer',
        2: 'snowball',
        3: 'conveniance'
    },
    'sample_platform': {
        -1: 'unspecified',
        0: 'mturk',
        1: 'qualtrics',
        2: 'prolific',
        3: 'university platform',
        4: 'mixture',
        5: 'other'
    },
    'sample_mturk': {
        -1: 'unspecified/NA',
        0: 'master',
        1: 'non-master'
    },
    'sample_level': {
        -1: 'unspecified',
        0: 'undergraduate',
        1: 'graduate',
        2: 'non-managerial',
        3: 'managerial',
        4: 'mixture'
    },
    'sample_incentive': {
        -1: 'unspecified',
        0: 'none',
        1: 'course credit',
        2: 'financial',
        3: 'raffle',
        4: 'results/feedback',
        5: 'mixture'
    },
    'sample_country': {
        -1: 'unspecified',
        0: 'north america',
        1: 'international mixture',
        2: 'UK',
        3: 'Germany'
    },
    'cr_multiple': {
        0: 'no',
        1: 'yes'
    },
    'cr_sequential': {
        -1: 'NA',
        0: 'no',
        1: 'yes'
    },
    'cr_method': {
        -1: '',
        0: 'attention check items / bogus items / instructed response',
        1: 'completion pace / response time',
        2: 'avg longstring',
        3: 'max longstring',
        4: 'mahalanobis D',
        5: 'univariate outlier',
        6: 'SRSI use me',
        7: 'SRSI effort',
        8: 'SRSI attention',
        9: 'consistency',
        10: 'PsySyn',
        11: 'PsyAnt'
    },
    'cr_method_type': {
        'response_time': [1],
        'outlier_analysis': [4, 5],
        'bogus_items': [0],
        'consistency_indices': [9, 10, 11],
        'response_pattern': [2, 3],
        'self_reported': [6, 7, 8]
    },
    'design_time': {
        -1: '',
        0: 'cross-sectional',
        1: 'repeated measures'
    },
    'design_method': {
        -1: '',
        0: 'observational',
        1: 'experimental'
    },
    'design_location': {
        -1: '',
        0: 'online',
        1: 'in-person'
    }
}


# count=0
# while count<10:

#     print(count,'\n')
#     count+=1
# print('While loop exited')

#print the Sum of n natural number
val=int(input('Enter a number '))
sum=0
i=1
while i<=val:
    sum=sum+i
    i+=1
print(sum)


# This is a sample Python script.

# Press Shift+F10 to execute it or replace it with your code.
# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.

def print_hi(name):
    # Use a breakpoint in the code line below to debug your script.
    print(f'Hi, {name}')  # Press Ctrl+F8 to toggle the breakpoint.

from tkinter import messagebox
from tkinter import simpledialog
from tkinter import*

root = Tk()
root.withdraw()

def is_float(valor):
    try:
        float(valor)
    except:
        return False

    return True

def is_int(valor):
    try:
        int(valor)
    except:
        return False

    return True

# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    inteiro = False
    while inteiro == False:
            a = simpledialog.askinteger("Input","Digite um número!")
            b = simpledialog.askinteger("Input", "Digite mais um número!")
            if is_int(a) & is_int(b):
                inteiro = True
                a = int(a)
                b = int(b)
                soma = ((a+b)/2)
                soma = str(soma)
                messagebox.showinfo("Resultado","O valor de sua soma, dividido por 2, é igual a "+soma)
            else:
                print("Por favor, digite números!")


#!/usr/bin/env python

import logging

# Create a module logger named after the module
module_logger = logging.getLogger(__name__)
# Add a NullHandler for the case if no logging is configured by the application
module_logger.addHandler(logging.NullHandler())

class MimarksException(Exception):

    def __init__(self, message, key=None):
        self.key = key
        self.message = message

    def __str__(self):
        if self.key is not None:
            return "Error [%s]: %s" % (self.key, self.message)
        else:
            return "Error: %s" % self.message

class MIMARKS(object):
    _fields = {
      "adapters": str,
      "biome": str,
      "collection_date": str,
      "experimental_factor": str,
      "feature": str,
      "findex": str,
      "geo_loc_name": str,
      "investigation_type": str,
      "isol_growth_condt": str,
      "lat_lon": str,
      "lib_const_meth": str,
      "lib_reads_seqd": str,
      "lib_size": int,
      "lib_vector": str,
      "material": str,
      "nucl_acid_amp": str,
      "nucl_acid_ext": str,
      "pcr_primers": str,
      "pcr_cond": str,
      "project_name": str,
      "rel_to_oxygen": str,
      "rindex": str,
      "samp_collect_device": str,
      "samp_mat_process": str,
      "samp_size": str,
      "seq_meth": str,
      "sop": list,
      "source_mat_id": list,
      "submitted_to_insdc": bool,
      "target_gene": str,
      "target_subfragment": str,
      "url": list
    }

    @staticmethod
    def required_fields():
        return tuple(MIMARKS._fields.keys())

    @staticmethod
    def check_dict(candidate):
        valid = True

        for mimarks_key in MIMARKS.required_fields():
            if mimarks_key not in candidate:
                valid = False
                module_logger.error("MIMARKS field %s is not present." % mimarks_key)
                break

        if valid:
            for candidate_key in candidate:
                if candidate_key not in MIMARKS.required_fields():
                    module_logger.error("Provided MIMARKS field %s is not a valid field name." % candidate_key)
                    valid = False
                    break

                # The provided key IS in the MIMARKS table, now we
                # need to check the type...
                if not isinstance(candidate[candidate_key], MIMARKS._fields[candidate_key]):
                    module_logger.error("Provided MIMARKS field of %s is not the right type!" % candidate_key)
                    valid = False
                    break

        return valid


#author:wen
#date:2014-3-13
#description:Extract the authors, publish year, publication source
#            and its reference papers from the endnote file.
#------------------------------------------------------------------------#

import re

n=2468

#正则匹配式
pattern_au=r'AU\s{1}(.*)'
pattern_py=r'PY\s{1}(\d+)'
pattern_j9=r'J9\s{1}(.*)'
pattern_cr = r'([\w\s\-\.]+),\s(\d{4}),\s([0-9a-zA-Z\s\-\(\)\*]+)(,|$)'

#打开边文件，记录文献引用关系
edgefile=open('edgefile.txt','w')
edgefile.write('Sourse;Target\n')

#对每一行进行匹配，保存成{AU,PY,J9}字典的形式，并在edgefile中记录引用关系
for i in range(1,n):
    fs=open('ER'+str(i)+'.txt','r')
    fr=open('recdirfile.txt','a')
    selfdir={}
    crlist=[]
    for line in fs.readlines():
        if line.startswith('CR '):
            line = line[3:]
        match_au = re.match(pattern_au,line)
        match_py = re.match(pattern_py,line)
        match_j9 = re.match(pattern_j9,line)
        match_cr = re.match(pattern_cr,line.strip())
        if match_cr:
            crlist.append({'AU':match_cr.group(1),'PY':match_cr.group(2),\
                           'J9':match_cr.group(3)})
        if match_au:
            selfdir['AU']=match_au.group(1)
        if match_py:
            selfdir['PY']=match_py.group(1)
        if match_j9:
            selfdir['J9']=match_j9.group(1)
    recdir={'SELF':selfdir,'CR':crlist}
    for ele in recdir['CR']:
        edgefile.write(str(recdir['SELF'])+';'+str(ele)+'\n')
    fr.write(str(recdir)+'\n')
    fs.close()
    fr.close()

edgefile.close()
print('抽取结束!')


# Ejercicio 1 Ingles

x = 0

while x<=30:
    x+=1
    if x==4 or x==6 or x==10:
        print('The value',x,'of x was skipped')
        continue
    print('The value of the loop is', x)
    if x==15:
        break
print('The execution of the loop was broken when x was',x)

# Ejercicio 1

line = ""

while line != " ":
    line = input('Ingrese una palabra o frase (Vacio para salir): ').upper()
    if line == "":
        break
    print(line)

# Ejercicio 2

option = 'D'
account = 0

while option!='D' or option!='R':
    option = input('Presione D+(espacio)+monto para ingresar dinero o R+(espacio)+monto para retirar: ').upper()
    if option=="":
        break
    elif option[0]=='D':
        split_string = option.split()
        amount = int(split_string[1])
        account += amount
    elif option[0]=='R':
        split_string = option.split()
        amount = int(split_string[1])
        account -= amount
    else:
        print('No existe esa opcion')

print('Saldo:', account)

# Ejercicio 3

num = 2
prime_numbers = 0
while num>1:
    counter = 0
    num = int(input('Ingrese un numero entero positivo mayor a 1 (0 para salir): '))
    if num == 0:
        break
    for i in range(1,num+1):
        if num % i == 0:
            counter += 1
    if counter==2:
      print(num,'es primo')
      prime_numbers+=1

print('Se ingresaron',prime_numbers,'numeros primos')

# Ejercicio 4

year1 = int(input('Ingrese un año: '))
year2 = int(input('Ingrese otro año: '))

if year1<year2:
    print('Año bisiesto y multiplo de 10 entre', year1, 'y', year2, ':')
    for i in range(year1, year2+1):
        if i % 10 != 0:
            continue
        elif i % 4 == 0 and (i % 100 != 0 or i%400==0):
            print(i)

else:
    print('Año bisiesto y multiplo de 10 entre', year2, 'y', year1, ':')
    for i in range(year2, year1+1):
        if i % 10 != 0:
            continue
        elif i % 4 == 0 and (i % 100 != 0 or i%400==0):
            print(i)

# Ejercicio 5

for i in range(1, 20+1):
    if i % 2 != 0:
        continue
    print(i)

# Ejercicio 6

number_list = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
num = int(input("Que numero quiere buscar en la lista? (Del 1 al 20): "))
for i in number_list:
    print(i)
    if  i == num:
        print("Bucle terminado")
        break

# Ejercicio 7

print("Elija una opcion:\n 1. Opcion 1 \n 2. Opcion 2 \n 3. Opcion 3 \n 0. Salir")
yes_no = ''
while True:
    option = int(input("Opcion: "))
    if option == 1 or option == 2 or option == 3:
        print("Estas en la opcion", option)
    elif option == 0:
        print("Saliendo...")
        break
    else:
        print("Elija una opcion correcta.")


# https://www.acmicpc.net/problem/1439

s = input()
if "0" not in s or "1" not in s:
    print(0)
else:
    s = s.replace("10", "1.0")
    s = s.replace("01", "0.1")
    arr = s.split(".")
    d = {"0": 0, "1": 0}
    for piece in arr:
        d[piece[0]] += 1
    print(min(d["0"], d["1"]))


from utils import *
from sklearn import svm

def svm_algorithm(x_train, y_train, x_test, y_test):
    # Flatten arrays
    x_train = np.reshape(x_train, (x_train.shape[0], 128 * 128 * 3))
    x_test = np.reshape(x_test, (x_test.shape[0], 128 * 128 * 3))

    clf = svm.SVC(kernel='linear', verbose=True)
    clf.fit(x_train, y_train)
    predictions = clf.predict(x_test)

    total_accuracy = get_total_accuracy(y_test, predictions)
    waldo_accuracy = get_waldo_accuracy(y_test, predictions)
    print('Total accuracy of: ' + str(total_accuracy) + '%.')
    print('Waldo accuracy of: ' + str(waldo_accuracy) + '%.')

def svm_cross_validation(x_train, y_train, cross_validation_size):
    if cross_validation_size <= 1:
        print('Cross validation size must be 2 at least')
        return False
    for i in range(cross_validation_size):
        print('Cross validation iteration ' + str(i) + ':')
        x_train, y_train, validation_data, validation_label = \
            build_cv_data(x_train, y_train, i, cross_validation_size)

        if x_train is None:
            print("Failed to build cross validation data")
            return False

        svm_algorithm(x_train, y_train, validation_data, validation_label)

    return True


import pyaes

class Aes(object):
    @staticmethod
    def encrypt(plaintext, key):
        plaintext_bytes = [ord(c) for c in plaintext]

        aes = pyaes.AES(key.encode("UTF-8"))

        ciphertext = aes.encrypt(plaintext_bytes)

        return "".join(chr(i) for i in ciphertext)

    @staticmethod
    def decrypt(ciphertext, key):
        ciphertext_bytes = [ord(c) for c in ciphertext]

        aes = pyaes.AES(key.encode("UTF-8"))

        plaintext = aes.decrypt(ciphertext_bytes)

        return "".join(chr(i) for i in plaintext)

    @staticmethod
    def cbc_encrypt(plaintext, init_vector, key, block_size=16):
        plaintext = Aes.add_padding(plaintext, block_size)
        vector = str(init_vector)

        blocks = [plaintext[i:i+block_size] for i in range(0, len(plaintext), block_size)]
        ciphertext = ""

        for block in blocks:
            block_to_encrypt_as_list = [chr(ord(char1) ^ ord(char2)) for char1, char2 in zip(vector, block)]
            block_to_encrypt = "".join(block_to_encrypt_as_list)
            cipher_block = Aes.encrypt(block_to_encrypt, key)
            ciphertext += cipher_block
            vector = cipher_block

        return ciphertext

    @staticmethod
    def add_padding(plaintext, block_size=16):
        padding = ""

        for space_remaining in range(len(plaintext) % block_size, (len(plaintext) // block_size + 1) * block_size):
            padding += " "

        plaintext += padding
        return plaintext

    @staticmethod
    def cbc_decrypt(ciphertext, init_vector, key, block_size=16):
        vector = str(init_vector)

        cipher_blocks = [ciphertext[i:i + block_size] for i in range(0, len(ciphertext), block_size)]
        plaintext = ""

        for cipher_block in cipher_blocks:
            decrypted_block = Aes.decrypt(cipher_block, key)
            block_as_list = [chr(ord(char1) ^ ord(char2)) for char1, char2 in zip(vector, decrypted_block)]
            block = "".join(block_as_list)
            plaintext += block
            vector = cipher_block

        return plaintext.rstrip()

    @staticmethod
    def ecb_encrypt(plaintext, key, block_size=16):
        plaintext = Aes.add_padding(plaintext, block_size)

        blocks = [plaintext[i:i + block_size] for i in range(0, len(plaintext), block_size)]
        ciphertext = ""

        for block in blocks:
            cipher_block = Aes.encrypt(block, key)
            ciphertext += cipher_block

        return ciphertext

    @staticmethod
    def ecb_decrypt(ciphertext, key, block_size=16):
        cipher_blocks = [ciphertext[i:i + block_size] for i in range(0, len(ciphertext), block_size)]
        plaintext = ""

        for cipher_block in cipher_blocks:
            block = Aes.decrypt(cipher_block, key)
            plaintext += block

        return plaintext.rstrip()