# -*- coding: utf-8 -*-
from __future__ import absolute_import

from django.contrib.auth import get_user_model

from rest_framework import serializers

class AuthorSerializer(serializers.ModelSerializer):

    class Meta:
        model = get_user_model()
        fields = (
            'first_name',
            'last_name',
        )
        read_only_fields = ('first_name', 'last_name')


import requests
from bs4 import BeautifulSoup as bs
import pandas as pd

url = 'http://www.yes24.com/24/category/bestseller?CategoryNumber=001&sumgb=09'
res = requests.get(url)
html = res.content
book = bs(html, 'html.parser')
# print(book)

best = pd.DataFrame(columns=['Book', 'Authod', 'Price', 'URL'])
for index, book_info in enumerate(book.select('td.goodsTxtInfo')) :
    book_title = book_info.select_one('a').text.strip()
    book_author = book_info.select_one('div.aupu > a').text.strip()
    book_price = book_info.select_one('span.priceB').text.strip()
    book_url = book_info.select_one('a').attrs['href']
    # print(book_title, book_author, book_price, book_url)
    best.loc[index+1] = (book_title, book_author, book_price, book_url)

best.to_excel('bestseller.xlsx')


import PIL.ImageDraw as ImageDraw, PIL.Image as Image, PIL.ImageShow as ImageShow

mx, my = -1, -1
with open('img.csv')as f:
    im = Image.new("RGB", (300, 41))
    for l in f.readlines():
        x, y, r, g, b = map(int, l.split(','))
        mx = max(mx, x)
        my = max(my, y)
        im.putpixel((x,y), (r, g, b))
    im.save("g.jpg")

print(mx, my)


#!/usr/bin/env python3

#
# Description: Changes headers in plasFlow assembly fasta from contig# length=length# depth=depthx to Name_contig#_length_length#_depth_depthx
#
# Usage: ./fasta_headers_plasFlow.py -i input.fasta -o output.fasta
#
# Output location: parameter
#
# Modules required: Biopython must be available in python instance
#
# V1.0
#
# Created by Erisa Sula (nvd4@cdc.gov) and Nick Vlachos (nvx4@cdc.gov)
#

from Bio import SeqIO
import sys
import os
import argparse

#Create an arg parser...someday
def parseArgs(args=None):
	parser = argparse.ArgumentParser(description='Script to rename contigs in re-assembled plasFlow filtered assemblies')
	parser.add_argument('-i', '--input', required=True, help='input fasta filename')
	parser.add_argument('-o', '--output', required=True, help='output filename')
	return parser.parse_args()

args = parseArgs()
sequences = []
for record in SeqIO.parse(args.input,"fasta"):
    #print(record.id)
    name=os.path.basename(args.input).split("_")[::-1]
    name=name[2:]
    name='_'.join(name[::-1])
    #print(name)
    #record.id = record.id.split("_cov")[0].replace("NODE",name)
    print(record)
    print(name)
    print(record.description.split(" ")[0])
    contig = record.description.split(" ")[0]
    record.description.split(" ")[1]
    length = record.description.split(" ")[1].split("=")[1]
    depth = record.description.split(" ")[2].split("=")[1]
    record.id = name+"_"+contig+"_length_"+length+"_depth_"+depth

    #print(record.id)
    record.description = ""
#    print(record.description)
#    print(record)
    sequences.append(record)

SeqIO.write(sequences, args.output, "fasta")


# -*- coding: utf-8 -*-
import numpy as np
import scipy as sp
import scipy.linalg as linalg

from itertools import islice

class GP:
    """Représente et simule un champ gaussien variant dans le temps.

    À un instant donné, le champ aux position z et w ont une covariance
    donnée par la fonction kernel. Ce noyau est paramétré par variance,
    spacescale. Le champ est calculé aux position locations. Le
    paramètre timescale permet de calculer la valeur du champs au
    prochain instant. Ce type de champs ne modèlise pas le bruit de
    mesure qui est à prendre en compte autre part.

    Le champs fourni la valeur des paramètres du noyau et la position
    des points de calcul. L'attribut samples contient la valeur du champ
    aux positions données par locations.

    Pour passer à l'instant suivant, un appel à la méthode next suffit.
    Autrement, il est possible d'iterer sur le champ pour obtenir la
    suite de ses valeurs au cours du temps.

    La méthode de simulation est rapide car elle n'est pas exacte. Soit
    X(t) la valeur du champ à l'instant t aux points locations et soit
    X(t+1) celle à l'instant suivant t+1. On a en notant tau=timescale

    [X(t); X(t+dt)] ~ N(0, [K, K*exp(-1/tau^2); K*exp(-1/tau^2), K])

    car le noyau complet avec le temps est homogène est vaut k(x,y) *
    e^(-((tx-ty)/timescale^2). Par conséquent,

    X(t+dt) | X(t) ~ N(X(t) * exp(-1/timespace^2), K(1-exp(-1/tau^2))).
    """

    def __init__(self, variance, spacescale, timescale, locations):
        """Construit un champ gaussien variant dans le temps."""
        self.variance = variance
        self.spacescale = spacescale
        self.timescale = timescale

        self.locations = locations
        self.covariance = self.kernel(locations, locations)
        self.samples = np.zeros_like(locations)

        self._meancoef = np.exp(-1.0/self.timescale**2)
        D, V = linalg.eig(self.covariance)
        D = np.real(D)
        D[D < 0.0] = 0.0
        A = V.dot(np.diag(np.sqrt(D)))
        self.samples = A.dot(np.random.normal(size=self.samples.size)).reshape(self.samples.shape)

        D *= 1.0 - self._meancoef
        self._L = A * np.sqrt(1.0 - self._meancoef)
        D[D > 0.0] = 1.0 / D[D > 0.0]
        self._Q = V.dot(np.diag(D).dot(np.conj(V.T)))
        self.next()

    def kernel(self, z, w):
        """retourne la matrice de covariance du noyau entre les points z et w de
        l'espace à un instant donné. Les coefficients sont donnés par le noyau
        variance*exp(-|z-w|^2/spacescale^2)."""
        z = np.asarray(z)
        w = np.asarray(w)
        if z.shape == ():
            Z, W = z, w
        else:
            Z = z.flatten()[:, np.newaxis].repeat(w.size, axis=1)
            W = w.flatten()[np.newaxis, :].repeat(z.size, axis=0)
        return self.variance * np.exp(-np.abs((Z - W) / self.spacescale)**2)

    def __iter__(self):
        while True:
            yield self.next().copy()

    def next(self):
        """Simule le champ à l'instant suivant.

        Simule la valeur du champ aux points locations à l'instant
        suivant t+1 sachant la valeur du champ à ces même points à
        l'instant t."""
        W = np.random.normal(size=self.samples.size) # ~ N(O,I)
        self.samples *= self._meancoef
        self.samples += self._L.dot(W).reshape(self.samples.shape)
        return self.samples

    def regression(self, positions, samples=None, noise=None):
        """Fait une regression sur la valeur du champs.

        La méthode retourne la moyenne et la matrice de covariance de la
        valeur du champs aux positions 'positions' sachant la valeurs du
        champs aux positions self.locations. Le bruit de mesure ajouté
        ici est gaussien de variance noise. Si samples vaut None, la
        valeur actuelle du champs aux positions self.locations est
        utilisée sinon l'argument la donne."""
        K = self.covariance
        if samples is None:
            samples = self.samples
        if noise is not None:
            samples = samples.copy() + np.sqrt(noise) * np.random.normal(size=samples.size)
            K = self.covariance.copy()
            for i in range(len(K)):
                K[i,i] = noise
        Kpp = self.kernel(positions, positions)
        Kpl = self.kernel(positions, self.locations)
        KplQ = Kpl.dot(self._Q)
        mu = KplQ.dot(samples.flatten()).reshape(positions.shape)
        cov = Kpp - KplQ.dot(Kpl.T)
        return (mu, cov)

if __name__ == '__main__':
    import matplotlib.pyplot as plt

    # Premier exemple: 1D+t
    plt.figure()
    locations = np.linspace(0.0, 1.0, 11)
    field = GP(variance=1.0, spacescale=0.44, timescale=100, locations=locations)
    example = np.asarray(list(islice(field, 200)))
    plt.plot(example)

    # Second exemple: 2D+t
    locations = np.dot([1, 1j], np.random.random((2, 10)))
    etendue = np.linspace(0, 1, 20)
    xe, ye = np.meshgrid(etendue, etendue)
    positions = xe + 1j*ye
    field = GP(variance=1.0, spacescale=0.44, timescale=10, locations=locations)
    for t in range(5):
        field.next()
        if True: # t % 20 == 1:
            [mu, cov] = field.regression(positions, noise=0.001)
            vs = cov.diagonal().reshape(positions.shape)

            plt.figure()
            plt.subplot(211)
            plt.imshow(mu, extent=(0,1,0,1), origin='lower')
            plt.plot(field.locations.real, field.locations.imag, 'ko')
            plt.subplot(212)
            plt.imshow(vs, extent=(0,1,0,1), origin='lower')
            plt.plot(field.locations.real, field.locations.imag, 'ko')

    plt.show()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# 【app】
#
#  概要:
#       FastAPI のレッスン
#
from fastapi import FastAPI
from typing import List, Dict
from typing import Optional
from fastapi import Query, Path # Query,Path
from pydantic import BaseModel
from fastapi import Body

app = FastAPI()

class ItemOut(BaseModel):
    strings: str
    aux: int = 1
    text: str

# method and endopoint
@app.get('/', response_model=ItemOut)
async def response(strings: str, integer: int):
    return {"text": "hello world!", "strings": strings, "integer": integer}

#async def hello():
#    return {"text": "hello world!"}

@app.get('/get/{path}')
async def path_and_query_params(
        path: str,
        query: int,
        default_none: Optional[str] = None): # optional で型
    return {"text": f"hello, {path}, {query} and {default_none}"}

# 第一引数はデフォルト値を指定。デフォルト値なし (required)にしたい場合は、...を渡す
@app.get('/validation/{path}')
async def validation(
        string: str = Query(None, min_length=2, max_length=5, regex=r'[a-c]+.'),
        integer: int = Query(..., gt=1, le=3),  # required
        alias_query: str = Query('default', alias='alias-query'),
        path: int = Path(10)):
    return  {"string": string, "integer": integer, "alias-query": alias_query, "path": path}

# POST method の場合
class Data(BaseModel):
    """class Data(BaseModel)"""
    string: str
    default_none: Optional[int] = None
    lists: List[int]

# post
#
# 以下のjson を受ける
#
# {
#     "string": "string",
#     "default_none": 0,
#     "lists": [1, 2]
# }
#
@app.post('/post')
async def declare_request_body(data: Data):
    return {"text: hello {}, {}. {}".format(data.string, data.default_none, data.lists)}

# post/embed
#
# 以下のjson を受ける
#
# {
#     "data": {
#         "string": "string",
#         "default_none": 0,
#         "lists": [1, 2]
#     }
# }
#
@app.post('/post/embed')
async def declare_embedded_request_body(data: Data = Body(..., embed=True)):
    return {"text: hello {}, {}. {}".format(data.string, data.default_none, data.lists)}

# post/nest
#
# 以下のjsonを受ける
#
# {
#     "subData": {
#         "strings": "string",
#         "integer": 0
#     },
#     "subDataList": [
#         {"strings": "string0", "integer": 0},
#         {"strings": "string1", "integer": 1},
#         {"strings": "string2", "integer": 2}
#     ]
# }
#

# subData の型ヒント
class subDict(BaseModel):
    string: str
    integer: int

class NestedData(BaseModel):
    subData: subDict
    subDataList: List[subDict]

@app.post('/post/nested')
async def declare_nested_request_body(data: NestedData):
    return {"text": f"hello, {data.subData}, {data.subDataList}"}


"""
The functions in this file relate to adding cumulative case/death numbers assuming a weird data
reset in KY.
"""

import flask
import numpy as np
import pandas as pd
from time import time

from app.api import utils

def preclean_KY(df):
    # some county names are "Jefferson" vs "Jefferson County", so standardizing by removing "County"
    # and fixing some county typos while here
    replace_strings = {
        ' COUNTY': '',
        'BULLIT': 'BULLITT',
        'SHLEBY': 'SHELBY',
        'WOODFOORD': 'WOODFORD',
    }
    for key, val in replace_strings.items():
        df['County'] = df['County'].str.replace(key, val)

    return df

# are there any facilities that have dates in 2021 that aren't consecutive from the max? If this
# returns False, we just propagate the group as is because there's something weird about the dates
def is_2021_info_okay(df_group, dates_2021):
    df_group_dates_2021 = set(x for x in set(df_group.Date) if x > 20210000)
    seen_2021 = False
    for date in dates_2021:
        if seen_2021 and date not in df_group_dates_2021:
            print('%s' % set(df_group.Facility))
            return False
        if not seen_2021 and date in df_group_dates_2021:
            seen_2021 = True
    return True

# Adds extra rows for 2021 if any are missing, and recomputes the cumulative values using the counts
# from 20201231 as the base: KY reset their cumulative counts in 2021 so we're correcting for that.
#
# If any facilities used to be reported but were dropped before 20201231, add them to the
# early_disappeared_facilities set.
def update_ky_2021_data(df_group, col_map, dates_2021, early_disappeared_facilities):
    # if something is wrong with this group, flag, return
    if not is_2021_info_okay(df_group, dates_2021):
        return df_group

    # if we don't have data for this facility on 12/31/2020, flag it as a possible other issue,
    # return group
    if 20201231 not in set(df_group.Date):
        early_disappeared_facilities.update(df_group.Facility)
        return df_group

    # create rows for missing 2021 dates with no data
    missing_2021_dates = set(dates_2021).difference(set(df_group.Date))
    if len(missing_2021_dates) > 0:
        # take the 20201231 data and propagate it forward, set the dates, remove all metric counts
        df_head = df_group.head(1)
        replicated_row_df = df_head.loc[df_head.index.repeat(len(missing_2021_dates))]
        replicated_row_df['Date'] = missing_2021_dates
        for col1, col2 in col_map.items():
            replicated_row_df.loc[:, col1] = np.nan
            replicated_row_df.loc[:, col2] = np.nan

        df_group = pd.concat([df_group, replicated_row_df])
        df_group.sort_values(
            by=['Date', 'ctp_id'], inplace=True, ignore_index=True)

    # within each group, take the case/death numbers as of 20201231. Use that as the base number for
    # when they reset in 2021. Set each 2021 cumulative value to the sum of what's there now and
    # what was on 12/31
    base_row = df_group.loc[df_group.Date == 20201231].iloc[0]
    for i, row in df_group.iterrows():
        if row.Date < 20210000:  # skip 2020 rows
            continue

        for col in ['Cume_Res_Pos', 'Cume_Staff_Pos', 'Cume_Res_Death', 'Cume_Staff_Death']:
            base_val = base_row[col]
            cur_val = df_group.loc[i, col]
            if pd.isnull(cur_val):
                cur_val = 0
            df_group.at[i, col] = base_val + cur_val

    return df_group

def really_update_ky_2021_data(df):
    col_map = utils.make_matching_column_name_map(df)
    dates_2021 = sorted([x for x in set(df.Date) if x > 20210101])

    # group facilities and update each group as needed
    early_disappeared_facilities = set()
    processed_df = df.groupby(['ctp_id'], as_index=False).apply(
        lambda x: update_ky_2021_data(x, col_map, dates_2021, early_disappeared_facilities))

    # log which facilities disappeared before 20201231
    if len(early_disappeared_facilities) > 0:
        flask.current_app.logger.info('Facilities dropped before 20201231:')
        flask.current_app.logger.info(early_disappeared_facilities)

    return processed_df


import time
from torch.utils.data import DataLoader
from sentence_transformers import SentenceTransformer

from data.dataset import MyDataset
from AE.AE_Bank import *

class My_ChatBot(nn.Module):
    def __init__(self, model_path='jhgan/ko-sroberta-multitask',
                 csv_path='data/QA_data.csv',
                 embed_dim=768,
                 batch_size=512,
                 device='cpu'):
        super(My_ChatBot, self).__init__()

        # settings values #
        self.device = device
        self.batch_size = batch_size
        self.user_embed = 0

        # settings data #
        self.dataset = MyDataset(root='data/', csv_path=csv_path, embed_dim=embed_dim)
        self.loader = DataLoader(self.dataset, batch_size=batch_size)

        # settings forward module #
        self.bert = SentenceTransformer(model_path)
        if embed_dim==768:
            self.AE = nn.Sequential()
        else:
            self.AE = torch.load('AE/AE' + str(embed_dim) + '.pt').encoder
        self.cos = nn.CosineSimilarity(dim=-1)

    def set_user_embed(self, text):
        embed = self.sub_forward(text)
        embed = torch.tensor(embed)
        embed = embed.view(1, -1).to(self.device) #(1, dim)
        embed = self.AE(embed)
        self.user_embed = embed

    def sub_forward(self, x):
        x = self.bert.encode(x)
        return x

    def forward(self, x):
        sim = self.cos(self.user_embed, x) # Compare (1, dim) to (batch, dim) => (batch,) : Similarity
        return sim

    def get_max(self, sim, max_sim, max_idx, batch_idx):
        v, i = torch.max(sim, dim=-1)
        if max_sim < v.item():
            max_sim = v.item()
            max_idx = i.item() + (self.batch_size * batch_idx)

        return max_sim, max_idx

    def inference(self, loader, text):
        self.eval()
        self.set_user_embed(text)
        max_sim = 0
        max_idx = 0

        with torch.no_grad():
            for b_idx, data in enumerate(loader):
                data = data.to(self.device)

                batch_sim = self(data)

                max_sim, max_idx = self.get_max(batch_sim, max_sim, max_idx, b_idx)
        answer = self.dataset.get_answer(max_idx)
        return answer, max_sim, max_idx

    def chat(self, s=False, t=False):
        """
        Ultimately, the method used by the user
        :param s: Whether to output similarity
        :param t: Whether to output the output time
        """
        while (True):
            user = input("USER >>> ")
            if user == 'exit' or user == 'quit':
                break

            f = time.time()
            answer, sim, _ = self.inference(self.loader, user)
            f = time.time() - f

            print(" BOT >>>", answer)
            if s : print("\t유사도 : {:.4f}%".format(sim * 100))
            if t : print("\t추론 시간 :", f)

def main():
    device = 'cuda' if torch.cuda.is_available() else 'cpu'
    model = My_ChatBot(device=device, embed_dim=64)
    model.to(device)

    model.chat(True, True)

if __name__ == "__main__":
    main()


# Python Unit Tests
# Written for INFOTC4320 Module 13
# Written by: Jacob McIntosh jam6m4
# ---------------------------------------------

# imports
import unittest
import inputs
from datetime import date

class InputTest(unittest.TestCase):

    def setUp(self):
        self.symbol = "AAPL"
        self.chart_type = "1"
        self.time_series = "2"
        self.start_date = "2020-3-20"
        self.end_date = "2021-10-18"

    def test_symbol(self):
        print("Checking symbol...")
        self.assertEqual(inputs.symbol(self.symbol), self.symbol)

    def test_chart_type(self):
        print("Checking chart type...")

        if self.chart_type == "1":
            self.assertEqual(inputs.chart_type(self.chart_type), "Line")
        elif self.chart_type == "2":
            self.assertEqual(inputs.chart_type(self.chart_type), "Bar")

    def test_time_series(self):
        print("Checking time series")

        if self.time_series == "1":
            self.assertEqual(inputs.time_series(self.time_series), "Intraday")
        elif self.time_series == "2":
            self.assertEqual(inputs.time_series(self.time_series), "Daily")
        elif self.time_series == "3":
            self.assertEqual(inputs.time_series(self.time_series), "Weekly")
        elif self.time_series == "4":
            self.assertEqual(inputs.time_series(self.time_series), "Monthly")

    def test_start_date(self):
        print("Checking start date...")

        y = int(self.start_date.split("-")[0])
        m = int(self.start_date.split("-")[1])
        d = int(self.start_date.split("-")[2])

        s_date = date(y, m, d)
        s_date = s_date.strftime('%Y-%m-%d')

        self.assertEqual(inputs.start_date(self.start_date), s_date)

    def test_start_date(self):
        print("Checking end date...")

        y = int(self.end_date.split("-")[0])
        m = int(self.end_date.split("-")[1])
        d = int(self.end_date.split("-")[2])

        e_date = date(y, m, d)
        e_date = e_date.strftime('%Y-%m-%d')

        self.assertEqual(inputs.end_date(self.end_date), e_date)

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


import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

def read_image() -> np.ndarray:
    return cv.imread("LegosGrises 1.jpg")

def plot_histogram(image: np.ndarray) -> None:
    histogram = cv.calcHist([image], [0], None, [256], [0, 256])
    plt.plot(histogram)

def apply_threshold(image: np.ndarray, min: int, max: int) -> np.ndarray:
    _, image_thresh = cv.threshold(image, min, max, cv.THRESH_BINARY)
    return image_thresh

def main() -> None:
    image = read_image()
    plot_histogram(image)
    image_thresh = apply_threshold(image, 100, 130)

    cv.imshow("image", image_thresh)
    plt.show()

    while True:
        k = cv.waitKey(0) & 0xFF
        if k == 27:
            cv.destroyAllWindows()
            break

if __name__ == "__main__":
    main()


import time
import json
import boto3
import cfnresponse
from datetime import datetime
from dateutil import tz
gatewayClient = boto3.client('storagegateway')
def create(properties, physical_id):
    activationKey = properties['ActivationKey']
    instanceRegion = properties['InstanceRegion']
    gatewayName = properties['GatewayName']
    gatewayTimezone = properties['GatewayTimezone']
    zone=datetime.now(tz.gettz(gatewayTimezone)).strftime('%z')
    timezonesign = zone[0:1]
    timezonehour = str(int(zone[1:3]))
    timezoneminute = zone[3:5]
    gatewayTimezoneOffset = f'GMT{timezonesign}{timezonehour}:{timezoneminute}'
    print(f'GatewayTimezoneOffset = {gatewayTimezoneOffset}')
    gatewayARN = gatewayClient.activate_gateway(
        ActivationKey=activationKey,
        GatewayName=gatewayName,
        GatewayTimezone=gatewayTimezoneOffset,
        GatewayRegion=instanceRegion,
        GatewayType='FILE_S3'
    )['GatewayARN']
    print(f'Gateway ARN = {gatewayARN}, Gateway Name = {gatewayName}')
    returnAttribute = {}
    returnAttribute['Arn'] = gatewayARN
    returnAttribute['Name'] = gatewayName
    returnAttribute['Action'] = 'CREATE'
    return cfnresponse.SUCCESS, gatewayARN, returnAttribute
def update(properties, physical_id):
    gatewayARN = physical_id
    gatewayName = properties['GatewayName']
    gatewayTimezone = properties['GatewayTimezone']
    zone=datetime.now(tz.gettz(gatewayTimezone)).strftime('%z')
    timezonesign = zone[0:1]
    timezonehour = str(int(zone[1:3]))
    timezoneminute = zone[3:5]
    gatewayTimezoneOffset = f'GMT{timezonesign}{timezonehour}:{timezoneminute}'
    gatewayName = gatewayClient.update_gateway_information(
        GatewayARN=gatewayARN,
        GatewayName=gatewayName,
        GatewayTimezone=gatewayTimezoneOffset
    )['GatewayName']
    returnAttribute = {}
    returnAttribute['Arn'] = gatewayARN
    returnAttribute['Name'] = gatewayName
    returnAttribute['Action'] = 'UPDATE'
    return cfnresponse.SUCCESS, gatewayARN, returnAttribute
def delete(properties, physical_id):
    gatewayARN = physical_id
    gatewayName = properties['GatewayName']
    gatewayARN = gatewayClient.delete_gateway(
        GatewayARN=gatewayARN
    )['GatewayARN']
    returnAttribute = {}
    returnAttribute['Arn'] = gatewayARN
    returnAttribute['Name'] = gatewayName
    returnAttribute['Action'] = 'DELETE'
    return cfnresponse.SUCCESS, gatewayARN, returnAttribute
def handler(event, context):
    print('Received event: ' + json.dumps(event))
    status = cfnresponse.FAILED
    new_physical_id = None
    returnAttribute = {}
    try:
        properties = event.get('ResourceProperties')
        physical_id = event.get('PhysicalResourceId')
        status, new_physical_id, returnAttribute = {
            'Create': create,
            'Update': update,
            'Delete': delete
        }.get(event['RequestType'], lambda x, y: (cfnresponse.FAILED, None))(properties, physical_id)
    except Exception as e:
        print('Exception: ' + str(e))
        status = cfnresponse.FAILED
    finally:
        cfnresponse.send(event, context, status, returnAttribute, new_physical_id)


import debug_toolbar

from django.urls import include, path
from django.contrib import admin

# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
    path('admin/', admin.site.urls),
    path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
    path('auth/', include(('authentication.urls',
                           "authentication"), namespace='authentication')),
    path('todo/', include(('todo.urls', 'todo'), namespace='todo')),
    path('__debug__/', include(debug_toolbar.urls)),
]


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Mar 26 10:40:24 2020

@author: nelson
"""
import csv
from Bio import SeqIO
from Bio import SeqRecord
from Bio.Seq import Seq
from Bio.Alphabet import generic_dna
from Bio import BiopythonWarning
import warnings
import ray
import numpy as np

class ComplexityMasker:
    """This class takes a genome (multi-sequence fasta file) or a single sequence
    as a biopython SeqRecord object and returns a .GTF interval file containing
    annotated regions of low-complexity as well as a fasta file containing the
    sequences contained within these intervals.

    Attributes:
        verbose: Used to print various helpful debuging statements.

        window_size: The size of the window of sequence which is
        kmerized. The window size rougly defines the resolution of your
        analysis. Smaller window sizes can identify smaller repeats but
        consumes more resources.

        step_size: The amount of nucleotides that the window slides
        over each iteration. This parameter also defines the resolution of
        your analysis. A smaller step size increases the number of samples
        taken from the genome, but it consumes more resources.

        cutoff: The percentage drop in complexity which is considered
        significant enough to be annotated as a region of interest.

        kmer_length: The kmer length that is used for all analysis.

        genome: Holds the dictionary object containing the genome to be
        analyzed.

        sequence: Holds the SeqRecord object which contains the single sequence
        to be analyzed.
    """
    def __init__(self, num_cores=8, verbose=True, window_size=10000, step_size=5000,
                 cutoff=0.8, kmer_length=21, padding=10000):

        """Constructs a ComplexityFilter object"""
        self.verbose = verbose
        self.window_size = window_size
        self.step_size = step_size
        self.cutoff = cutoff
        self.kmer_length = kmer_length
        self.padding = padding
        self.genome = None
        self.sequence = None
        self.num_cores = num_cores

    def load_genome(self, filepath):
        """Loads a genome using the Biopython SeqIO module. It is stored as
        a dictionary with the .fasta sequence ID as the key and a SeqRecord
        object as the value.

        Args:
            filepath: A string which provides the filepath to the genome file
            to be loaded.

        Returns:
            None

        Raises:
            FileNotFoundError: The specific filepath is invalid.
        """
        print(filepath)
        try:
            self.genome = SeqIO.to_dict(SeqIO.parse(filepath, "fasta"))
        except FileNotFoundError:
            print("FileNotFoundError: the filepath you specified does not exist!")
            return
        self.genome_or_sequence = "Genome"
        if self.verbose: print("Genome loaded!")

    def load_sequence(self, sequence):
        """Loads a single sequence as a Biopython SeqRecord object.

        Args:
            sequence: The sequence to be loaded. Can be a generic string,
            a biopython Seq object, or a SeqRecord object.

        Returns:
            None

        Raises:
            TypeError: The passed sequences was not a valid datatype.
            """

        if type(sequence) is SeqIO.SeqRecord:
            self.sequence = sequence
        elif type(sequence) is Seq:
            self.sequence = SeqIO.SeqRecord(sequence)
        elif type(sequence) is str:
            sequence = Seq(sequence, alphabet=generic_dna)
            self.sequence = SeqIO.SeqRecord(sequence)
        else:
            print("Sequence must be a biopython SeqRecord object!")
            raise TypeError

    def non_canonical_kmerize(self, sequence):
        """PRIVATE: Generates a (non-canonical) kmer dictionary of a specified sequence.

        Args:
            sequence: The sequence to be kmerized

        Returns:
            kmer_dict: A kmer dictionary containing each kmer as a key and the
            number of times it appears in the sequence as the value.

        Raises:
            None
        """
        kmer_dict = {}
        for i in range(0,len(sequence)-self.kmer_length):
            kmer = sequence[i:i+self.kmer_length]
            if kmer in kmer_dict:
                kmer_dict[str(kmer)] += 1
            else:
                kmer_dict[str(kmer)] = 1
        return kmer_dict

    def generate_kmer_trace(self, sequence):
        """Scans the provided sequence with a resolution of the provided window
        size and determines the number of unique kmers within that region.

        Args:
            sequence: The sequence to be analyzed

        Returns:
            indices, kmer_counts

        Raises:
            None
        """
        index = 0
        sub_sequence = sequence[index:index+self.window_size]
        kmer_counts = []
        while(index+self.window_size < len(sequence)):
            kmer_dict = self.non_canonical_kmerize(sub_sequence)
            kmer_counts.append(len(kmer_dict.keys())/self.window_size)
            index += self.step_size
            sub_sequence = sequence[index:index+self.window_size]
        return range(0, len(sequence), self.step_size)[0:len(kmer_counts)], kmer_counts

    @ray.remote
    def helper_generate_kmer_trace(self, sequence):
        """Scans the provided sequence with a resolution of the provided window
        size and determines the number of unique kmers within that region.

        Args:
            sequence: The sequence to be analyzed

        Returns:
            indices, kmer_counts

        Raises:
            None
        """

        index = 0
        sub_sequence = sequence[index:index+self.window_size]
        kmer_trace = []
        while(index+self.window_size < len(sequence)):
            with warnings.catch_warnings():
                warnings.simplefilter('ignore')
                kmer_dict = self.non_canonical_kmerize(sub_sequence)
            kmer_trace.append(len(kmer_dict.keys())/self.window_size)
            index += self.step_size
            sub_sequence = sequence[index:index+self.window_size]
        return range(0, len(sequence), self.step_size)[0:len(kmer_trace)], kmer_trace

    def multi_generate_kmer_trace(self, sequence):
        """Scans the provided sequence with a resolution of the provided window
        size and determines the number of unique kmers within that region.

        Args:
            sequence: The sequence to be analyzed

        Returns:
            indices, kmer_counts

        Raises:
            None
        """
        #ray.shutdown()
        #ray.init(num_cpus=self.num_cores)
        anchors = range(0, len(sequence), self.step_size)
        chunks = np.array_split(anchors, self.num_cores)
        kmer_traces_obj = []
        for chunk in chunks:
            try:
                kmer_traces_obj.append(self.helper_generate_kmer_trace.remote(self, sequence[chunk[0]:chunk[-1] + self.window_size + self.step_size]))
            except IndexError:
                kmer_traces_obj.append(self.helper_generate_kmer_trace.remote(self, sequence[chunk[0]:len(sequence)]))
        kmer_trace = []
        for trace in kmer_traces_obj:
            kmer_trace += ray.get(trace)[1]
        return range(0, len(sequence), self.step_size)[0:len(kmer_trace)], kmer_trace
        #ray.shutdown()

    def analyze_sequence(self, contig_name, sequence, export_gtf = False, export_sequences = False):

        if self.verbose: print("Analyzing " + contig_name)
        if len(sequence) >= self.window_size * self.num_cores * 10:
            coordinates, kmer_trace = self.multi_generate_kmer_trace(sequence)
        else:
            coordinates, kmer_trace = self.generate_kmer_trace(sequence)
        intervals = self.find_ROIs(len(sequence), coordinates, kmer_trace, self.padding)
        gtf_intervals = []
        for interval in intervals:
                gtf_intervals.append([contig_name, "Low-Complexity", "exon", interval[0], interval[1], 0, "+", ".", "gene_id\"Low_Complexity\""])
        if self.verbose: print("Completed analyzing " + contig_name)
        return gtf_intervals

    def analyze_genome(self, cm_fasta_filename = "Low_Complexity_Intervals.fasta", cm_gtf_filename = "Low_Complexity_Intervals.gtf"):

        if self.genome == None:
            print("No genome has been loaded!")
            return None
        #ray.shutdown()
        #ray.init(num_cpus=self.num_cores)
        gtf_intervals = []
        for contig in self.genome.keys():
            gtf_intervals.append(self.analyze_sequence(contig, self.genome[contig].seq))
        #ray.shutdown()
        self.export_as_GTF(gtf_intervals, filename = cm_gtf_filename)
        self.export_sequences(gtf_intervals, filename = cm_fasta_filename)

    #Code from Uvar (https://stackoverflow.com/questions/49071081/merging-overlapping-intervals-in-python)
    #Merges overlapping intervals into a single super-interval.
    def recursive_merge(self, intervals, start_index = 0):
        for i in range(start_index, len(intervals) - 1):
            if intervals[i][1] >= intervals[i+1][0]:
                new_start = intervals[i][0]
                new_end = intervals[i+1][1]
                intervals[i] = [new_start, new_end]
                del intervals[i+1]
                return self.recursive_merge(intervals.copy(), start_index=i)
        return intervals

    #Finds regions of interest (ROIs), which are 4 element tuples consisting of (Genomic Contig, Start, End, Sequence)
    def find_ROIs(self, length, coordinates, kmer_trace, padding):
        ROIs = []
        for index in range(0, len(coordinates)):
            if kmer_trace[index] < self.cutoff:
                if coordinates[index]-padding <= 0:
                    ROIs.append([0, padding])
                elif coordinates[index]+padding >= length:
                    ROIs.append([coordinates[index], length])
                else:
                    ROIs.append([coordinates[index] - padding, coordinates[index] + padding])
        return self.recursive_merge(ROIs)

    def search_sequences(self, ids):
        intervals = []
        for contig in ids:
            if self.verbose:
                print("Analyzing " + contig)
            coordinates, kmer_trace = self.generate_kmer_trace(self.genome[contig].seq)
            interval_list = self.find_ROIs(len(self.genome[contig].seq), coordinates, kmer_trace, 2 * self.window_size)
            for interval in interval_list:
                intervals.append([contig, "Low-Complexity", "exon", interval[0], interval[1], 0, "+", ".", "gene_id\"Low_Complexity\""])
        return intervals

    def search_sequence(self, contig_name):
        intervals = []
        if self.verbose:
            print("Analyzing sequence!")
        coordinates, kmer_trace = self.generate_kmer_trace(self.sequence)
        interval_list = self.find_ROIs(len(self.sequence), coordinates, kmer_trace, 2 * self.window_size)
        for interval in interval_list:
            intervals.append([contig_name, "Low-Complexity", "exon", interval[0], interval[1], 0, "+", ".", "gene_id\"Low_Complexity\""])
        return intervals

    def extract_sequences(self, intervals):
        sequences = []
        for contig in intervals:
            for region in  contig:
                sequence = self.genome[region[0]].seq[region[3]:region[4]]
                record = SeqRecord.SeqRecord(sequence, id=region[0] + ","+str(region[3])+","+str(region[4]))
                sequences.append(record)
        return sequences

    def export_sequences(self, intervals, filename):
        sequences = self.extract_sequences(intervals)
        SeqIO.write(sequences, filename, "fasta")

    def export_as_GTF(self, intervals, filename):
        with open(filename, 'w', newline='') as f_output:
            tsv_output = csv.writer(f_output, delimiter='\t', escapechar=' ', quoting=csv.QUOTE_NONE)
            for contig in intervals:
                for region in  contig:
                    tsv_output.writerow(region)


# -*- coding: UTF-8 -*-
import logging

LOG_FILENAME = '/tmp/example.log'
logging.basicConfig(filename=LOG_FILENAME,level=logging.INFO)
logging.debug('This DEBUG should go to the log file')
logging.info('This INFO should go to the log file')

logger = logging.getLogger('jobs')
logger.debug("test")
logger.info('info')


"""There are n servers numbered from 0 to n-1 connected by undirected server-to-server connections forming a network where connections[i] = [a, b] represents a connection between servers a and b. Any server can reach any other server directly or indirectly through the network.

A critical connection is a connection that, if removed, will make some server unable to reach some other server.

Return all critical connections in the network in any order.
"""

# Strong connected component
from collections import defaultdict

class Solution:
    def criticalConnections(self, n: int, connections: List[List[int]]) -> List[List[int]]:

        graph = defaultdict(list)

        for i, j in connections:
            graph[i].append(j)
            graph[j].append(i)

        low = {}
        ans = []

        def dfs(node, rank, parent): # important to pass parent
            nonlocal graph, low, ans

            # if node is in low
            if node not in low:
                low[node] = rank
                for nei in graph[node]:
                    if nei != parent: # we dont use visited to track!
                        actual = dfs(nei, rank + 1, node)
                        # check if expect == rank + 1
                        if actual >= rank + 1:
                            ans.append([node, nei])

                        # nodes in cycle all have the same rank
                                        # not rank!!!
                        low[node] = min(low[node], actual)

            return low[node]

        # main
        dfs(connections[0][0], 0, -1)

        return ans


#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# @Time : 2020/6/17 0017 上午 9:51
# @Author : West Field
# @File : algo.py

from sklearn import tree
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
import pandas as pd
import graphviz
import matplotlib.pyplot as plt
from sklearn.datasets import load_boston
from sklearn.model_selection import cross_val_score
from sklearn.tree import DecisionTreeRegressor
import numpy as np

pd.set_option('display.max_columns', 20)  # a就是你要设置显示的最大列数参数
pd.set_option('display.max_rows', 100)  # b就是你要设置显示的最大的行数参数
pd.set_option('display.width', 1000)  # x就是你要设置的显示的宽度，防止轻易换行

def classify_tree():
    ## 加载红酒数据集
    wine = load_wine()
    # print(type(wine), wine) # sklearn.utils.Bunch 字典，key是data, vale是target
    print(wine.data.shape, wine.data)
    print(wine.target)
    # 把特征和标签拼接成表
    data_table = pd.concat([pd.DataFrame(wine.data), pd.DataFrame(wine.target)], axis=1)
    print(data_table)
    # 特征名称、标签名称
    print(wine.feature_names, wine.target_names)
    # 划分数据集，train_test_split会随机划分数据集
    Xtrain, Xtest, Ytrain, Ytest = train_test_split(wine.data, wine.target, test_size=0.3, random_state=30)
    print(Xtrain.shape, Xtest.shape, Ytrain.shape, Ytest.shape)
    ## 开始建模
    clf = tree.DecisionTreeClassifier(criterion="entropy",  # criterion用来设置不纯度的计算的，entropy是使用信息熵，gini是使用基尼系数
                                      random_state=30,  # 决策树会随机的选取特征建模，使用random_state随机种子来固定。
                                      splitter="random")  # splitter是用来控制决策树中的随机选项的，best是决策树分支时优先使用更重要的特征进行分支，random是随机选择特征分支。
    clf = clf.fit(Xtrain, Ytrain)  # 训练数据
    score = clf.score(Xtest, Ytest)  # 返回预测的准确率accuracy
    print(score)
    ## 画树
    feature_name = ['酒精', '苹果酸', '灰', '灰的碱性', '镁', '总酚', '类黄酮', '非黄烷类酚类', '花青素', '颜色强度', '色调', 'od280/od315稀释葡萄酒',
                    '脯氨酸']
    # dot_data = tree.export_graphviz(clf
    #                                 , out_file='tree.dot'
    #                                 , feature_names=feature_name
    #                                 , class_names=["琴酒", "雪莉", "贝尔摩德"]
    #                                 , filled=True
    #                                 , rounded=True
    #                                 )
    # with open("tree.dot", encoding='utf-8') as f:
    #     dot_graph = f.read()
    # graph = graphviz.Source(dot_graph.replace("helvetica", "FangSong"))
    # graph.view()
    # 决策树中使用到的特征的特征重要性
    print(clf.feature_importances_)
    print([*zip(feature_name, clf.feature_importances_)])
    ## 剪枝参数，防止过拟合
    score = clf.score(Xtrain, Ytrain)
    print(score)
    clf = tree.DecisionTreeClassifier(criterion="entropy", random_state=30, splitter="random",
                                      max_depth=3,  # 树的最大深度
                                      # min_samples_leaf=10, # 一个节点在分支后的每个子节点都必须包括至少min_samples_leaf个训练样本
                                      # min_samples_split=25 # 一个节点至少包含min_samples_split个训练样本才允许被分支
                                      )
    clf = clf.fit(Xtrain, Ytrain)
    # dot_data = tree.export_graphviz(clf
    #                                 , out_file='tree.dot'
    #                                 , feature_names=feature_name
    #                                 , class_names=["琴酒", "雪莉", "贝尔摩德"]
    #                                 , filled=True
    #                                 , rounded=True
    #                                 )
    # with open("tree.dot", encoding='utf-8') as f:
    #     dot_graph = f.read()
    # graph = graphviz.Source(dot_graph.replace("helvetica", "FangSong"))
    # graph.view()
    print(clf.score(Xtest, Ytest))
    # 超参数学习，确认最优的剪枝参数
    test = []
    for i in range(10):
        clf = tree.DecisionTreeClassifier(max_depth=i + 1,
                                          criterion="entropy",
                                          random_state=30,
                                          splitter="random")
        clf = clf.fit(Xtrain, Ytrain)
        score = clf.score(Xtest, Ytest)
        test.append(score)
    plt.plot(range(1, 11), test, color="red", label="max_depth")
    plt.legend()
    plt.show()
    ## 重要属性和接口，决策树结构接受的数据至少是一个二维矩阵
    print(clf.apply(Xtest))  # apply返回每个测试样本所在的叶子节点的索引
    print(clf.predict(Xtest))  # predict返回每个测试样本的分类/回归结果

def regression_tree():
    ## 加载波士顿房价数据集
    boston = load_boston()
    # print(boston, boston.data.shape, boston.target.shape)
    ## 实例化回归模型
    regressor = DecisionTreeRegressor(random_state=0)
    ## 交叉验证
    score = cross_val_score(regressor, boston.data, boston.target, cv=10,
                            scoring="neg_mean_squared_error")  # 使用scoring衡量模型
    print(score)
    ## 一维回归的图像绘制
    # 生成随机数种子
    rng = np.random.RandomState()
    # 生成80行1列的二维数据，应为回归树接受至少二维以上的数据
    X = np.sort(5 * rng.rand(80, 1))  # rand生成0到1的数据
    y = np.sin(X).ravel()  # 标签y只能是一维的，使用ravel降维
    y[::5] += 3 * (0.5 - rng.rand(16))  # y的值每隔5个加上一个噪声
    # 画散点图
    plt.scatter(X, y, s=20, edgecolors="black", c="darkorange", label="data")
    plt.show()
    # 建立两个模型，观察效果对比
    regr_1 = DecisionTreeRegressor(max_depth=2)
    regr_2 = DecisionTreeRegressor(max_depth=5)
    regr_1.fit(X, y)
    regr_2.fit(X, y)
    # 测试
    X_test = np.arange(0.0, 5.0, 0.01)[:, np.newaxis]  # np.newaxis是数据升维
    y_1 = regr_1.predict(X_test)
    y_2 = regr_2.predict(X_test)
    # 画图
    plt.figure()
    plt.scatter(X, y, s=20, edgecolor="black", c="darkorange", label="data")
    plt.plot(X_test, y_1, color="cornflowerblue", label="max_depth=2", linewidth=2)
    plt.plot(X_test, y_2, color="yellowgreen", label="max_depth=5", linewidth=2)
    plt.xlabel("data")
    plt.ylabel("target")
    plt.title("Decision Tree Regression")
    plt.legend()
    plt.show()

if __name__ == "__main__":
    # 分类树
    classify_tree()
    # 回归树
    regression_tree()


'https://github.com/ionelmc/python-redis-lock'

import sys
import threading
import weakref
from base64 import b64encode
from logging import getLogger
from os import urandom

from redis import StrictRedis

__version__ = '3.7.0'
"""
loggers = {
    k: getLogger(".".join((__name__, k)))
    for k in [
        "acquire",
        "refresh.thread.start",
        "refresh.thread.stop",
        "refresh.thread.exit",
        "refresh.start",
        "refresh.shutdown",
        "refresh.exit",
        "release",
    ]
}
"""

PY3 = sys.version_info[0] == 3

if PY3:
    text_type = str
    binary_type = bytes
else:
    text_type = unicode  # noqa
    binary_type = str

# Check if the id match. If not, return an error code.
UNLOCK_SCRIPT = b"""
    if redis.call("get", KEYS[1]) ~= ARGV[1] then
        return 1
    else
        redis.call("del", KEYS[2])
        redis.call("lpush", KEYS[2], 1)
        redis.call("pexpire", KEYS[2], ARGV[2])
        redis.call("del", KEYS[1])
        return 0
    end
"""

# Covers both cases when key doesn't exist and doesn't equal to lock's id
EXTEND_SCRIPT = b"""
    if redis.call("get", KEYS[1]) ~= ARGV[1] then
        return 1
    elseif redis.call("ttl", KEYS[1]) < 0 then
        return 2
    else
        redis.call("expire", KEYS[1], ARGV[2])
        return 0
    end
"""

RESET_SCRIPT = b"""
    redis.call('del', KEYS[2])
    redis.call('lpush', KEYS[2], 1)
    redis.call('pexpire', KEYS[2], ARGV[2])
    return redis.call('del', KEYS[1])
"""

RESET_ALL_SCRIPT = b"""
    local locks = redis.call('keys', 'lock:*')
    local signal
    for _, lock in pairs(locks) do
        signal = 'lock-signal:' .. string.sub(lock, 6)
        redis.call('del', signal)
        redis.call('lpush', signal, 1)
        redis.call('expire', signal, 1)
        redis.call('del', lock)
    end
    return #locks
"""

class AlreadyAcquired(RuntimeError):
    pass

class NotAcquired(RuntimeError):
    pass

class AlreadyStarted(RuntimeError):
    pass

class TimeoutNotUsable(RuntimeError):
    pass

class InvalidTimeout(RuntimeError):
    pass

class TimeoutTooLarge(RuntimeError):
    pass

class NotExpirable(RuntimeError):
    pass

class Lock(object):
    """
    A Lock context manager implemented via redis SETNX/BLPOP.
    """
    unlock_script = None
    extend_script = None
    reset_script = None
    reset_all_script = None

    def __init__(self, redis_client, name, expire=None, id=None, auto_renewal=False, strict=True, signal_expire=1000):
        """
        :param redis_client:
            An instance of :class:`~StrictRedis`.
        :param name:
            The name (redis key) the lock should have.
        :param expire:
            The lock expiry time in seconds. If left at the default (None)
            the lock will not expire.
        :param id:
            The ID (redis value) the lock should have. A random value is
            generated when left at the default.

            Note that if you specify this then the lock is marked as "held". Acquires
            won't be possible.
        :param auto_renewal:
            If set to ``True``, Lock will automatically renew the lock so that it
            doesn't expire for as long as the lock is held (acquire() called
            or running in a context manager).

            Implementation note: Renewal will happen using a daemon thread with
            an interval of ``expire*2/3``. If wishing to use a different renewal
            time, subclass Lock, call ``super().__init__()`` then set
            ``self._lock_renewal_interval`` to your desired interval.
        :param strict:
            If set ``True`` then the ``redis_client`` needs to be an instance of ``redis.StrictRedis``.
        :param signal_expire:
            Advanced option to override signal list expiration in milliseconds. Increase it for very slow clients. Default: ``1000``.
        """
        if strict and not isinstance(redis_client, StrictRedis):
            raise ValueError("redis_client must be instance of StrictRedis. "
                             "Use strict=False if you know what you're doing.")
        if auto_renewal and expire is None:
            raise ValueError("Expire may not be None when auto_renewal is set")

        self._client = redis_client

        if expire:
            expire = int(expire)
            if expire < 0:
                raise ValueError("A negative expire is not acceptable.")
        else:
            expire = None
        self._expire = expire

        self._signal_expire = signal_expire
        if id is None:
            self._id = b64encode(urandom(18)).decode('ascii')
        elif isinstance(id, binary_type):
            try:
                self._id = id.decode('ascii')
            except UnicodeDecodeError:
                self._id = b64encode(id).decode('ascii')
        elif isinstance(id, text_type):
            self._id = id
        else:
            raise TypeError("Incorrect type for `id`. Must be bytes/str not %s." % type(id))
        self._name = 'lock:' + name
        self._signal = 'lock-signal:' + name
        self._lock_renewal_interval = (float(expire) * 2 / 3
                                       if auto_renewal
                                       else None)
        self._lock_renewal_thread = None

        self.register_scripts(redis_client)

    @classmethod
    def register_scripts(cls, redis_client):
        global reset_all_script
        if reset_all_script is None:
            reset_all_script = redis_client.register_script(RESET_ALL_SCRIPT)
            cls.unlock_script = redis_client.register_script(UNLOCK_SCRIPT)
            cls.extend_script = redis_client.register_script(EXTEND_SCRIPT)
            cls.reset_script = redis_client.register_script(RESET_SCRIPT)
            cls.reset_all_script = redis_client.register_script(RESET_ALL_SCRIPT)

    @property
    def _held(self):
        return self.id == self.get_owner_id()

    def reset(self):
        """
        Forcibly deletes the lock. Use this with care.
        """
        self.reset_script(client=self._client, keys=(self._name, self._signal), args=(self.id, self._signal_expire))

    @property
    def id(self):
        return self._id

    def get_owner_id(self):
        owner_id = self._client.get(self._name)
        if isinstance(owner_id, binary_type):
            owner_id = owner_id.decode('ascii', 'replace')
        return owner_id

    def acquire(self, blocking=True, timeout=None):
        """
        :param blocking:
            Boolean value specifying whether lock should be blocking or not.
        :param timeout:
            An integer value specifying the maximum number of seconds to block.
        """
       # logger = loggers["acquire"]

       # logger.debug("Getting %r ...", self._name)

        if self._held:
            raise AlreadyAcquired("Already acquired from this Lock instance.")

        if not blocking and timeout is not None:
            raise TimeoutNotUsable("Timeout cannot be used if blocking=False")

        if timeout:
            timeout = int(timeout)
            if timeout < 0:
                raise InvalidTimeout("Timeout (%d) cannot be less than or equal to 0" % timeout)

            if self._expire and not self._lock_renewal_interval and timeout > self._expire:
                raise TimeoutTooLarge("Timeout (%d) cannot be greater than expire (%d)" % (timeout, self._expire))

        busy = True
        blpop_timeout = timeout or self._expire or 0
        timed_out = False
        while busy:
            busy = not self._client.set(self._name, self._id, nx=True, ex=self._expire)
            if busy:
                if timed_out:
                    return False
                elif blocking:
                    timed_out = not self._client.blpop(self._signal, blpop_timeout) and timeout
                else:
                  #  logger.warning("Failed to get %r.", self._name)
                    return False

      #  logger.info("Got lock for %r.", self._name)
        if self._lock_renewal_interval is not None:
            self._start_lock_renewer()
        return True

    def extend(self, expire=None):
        """Extends expiration time of the lock.

        :param expire:
            New expiration time. If ``None`` - `expire` provided during
            lock initialization will be taken.
        """
        if expire:
            expire = int(expire)
            if expire < 0:
                raise ValueError("A negative expire is not acceptable.")
        elif self._expire is not None:
            expire = self._expire
        else:
            raise TypeError(
                "To extend a lock 'expire' must be provided as an "
                "argument to extend() method or at initialization time."
            )

        error = self.extend_script(client=self._client, keys=(self._name, self._signal), args=(self._id, expire))
        if error == 1:
            raise NotAcquired("Lock %s is not acquired or it already expired." % self._name)
        elif error == 2:
            raise NotExpirable("Lock %s has no assigned expiration time" % self._name)
        elif error:
            raise RuntimeError("Unsupported error code %s from EXTEND script" % error)

    @staticmethod
    def _lock_renewer(lockref, interval, stop):
        """
        Renew the lock key in redis every `interval` seconds for as long
        as `self._lock_renewal_thread.should_exit` is False.
        """
        while not stop.wait(timeout=interval):
         #   loggers["refresh.thread.start"].debug("Refreshing lock")
            lock = lockref()
            if lock is None:
          #      loggers["refresh.thread.stop"].debug(
             #       "The lock no longer exists, stopping lock refreshing"
            #    )
                break
            lock.extend(expire=lock._expire)
            del lock
       # loggers["refresh.thread.exit"].debug("Exit requested, stopping lock refreshing")

    def _start_lock_renewer(self):
        """
        Starts the lock refresher thread.
        """
        if self._lock_renewal_thread is not None:
            raise AlreadyStarted("Lock refresh thread already started")

       # loggers["refresh.start"].debug(
       #     "Starting thread to refresh lock every %s seconds",
       #     self._lock_renewal_interval
       # )
        self._lock_renewal_stop = threading.Event()
        self._lock_renewal_thread = threading.Thread(
            group=None,
            target=self._lock_renewer,
            kwargs={'lockref': weakref.ref(self),
                    'interval': self._lock_renewal_interval,
                    'stop': self._lock_renewal_stop}
        )
        self._lock_renewal_thread.setDaemon(True)
        self._lock_renewal_thread.start()

    def _stop_lock_renewer(self):
        """
        Stop the lock renewer.

        This signals the renewal thread and waits for its exit.
        """
        if self._lock_renewal_thread is None or not self._lock_renewal_thread.is_alive():
            return
      #  loggers["refresh.shutdown"].debug("Signalling the lock refresher to stop")
        self._lock_renewal_stop.set()
        self._lock_renewal_thread.join()
        self._lock_renewal_thread = None
       # loggers["refresh.exit"].debug("Lock refresher has stopped")

    def __enter__(self):
        acquired = self.acquire(blocking=True)
        assert acquired, "Lock wasn't acquired, but blocking=True"
        return self

    def __exit__(self, exc_type=None, exc_value=None, traceback=None):
        self.release()

    def release(self):
        """Releases the lock, that was acquired with the same object.

        .. note::

            If you want to release a lock that you acquired in a different place you have two choices:

            * Use ``Lock("name", id=id_from_other_place).release()``
            * Use ``Lock("name").reset()``
        """
        if self._lock_renewal_thread is not None:
            self._stop_lock_renewer()
        #loggers["release"].debug("Releasing %r.", self._name)
        error = self.unlock_script(client=self._client, keys=(self._name, self._signal), args=(self._id, self._signal_expire))
        if error == 1:
            raise NotAcquired("Lock %s is not acquired or it already expired." % self._name)
        elif error:
            raise RuntimeError("Unsupported error code %s from EXTEND script." % error)

    def locked(self):
        """
        Return true if the lock is acquired.

        Checks that lock with same name already exists. This method returns true, even if
        lock have another id.
        """
        return self._client.exists(self._name) == 1

reset_all_script = None

def reset_all(redis_client):
    """
    Forcibly deletes all locks if its remains (like a crash reason). Use this with care.

    :param redis_client:
        An instance of :class:`~StrictRedis`.
    """
    Lock.register_scripts(redis_client)

    reset_all_script(client=redis_client)  # noqa


import os;
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import warnings

from helper import prepare_production
from helper import forecast_err

from import_helper import getProduction, getArea, getRainfalls

def data_plot():
    #------- production
    production = getProduction(fileName)

    #make a little extra space between the subplots

    for r in regions:
        plt.plot(production['Date'], production[r], label=r) #, marker='o'

    plt.title('Production vs time')
    plt.xlabel('Time')
    plt.ylabel('Production')
    plt.grid(True)
    plt.legend(loc='upper left')
    plt.show()

    ##------- area
    area = getArea(fileName)
    for r in regions:
        plt.plot(area['Year'], area[r], label=r) #, marker='o'

    plt.title('Area vs year')
    plt.xlabel('Year')
    plt.ylabel('Area')
    plt.grid(True)
    plt.legend(loc='upper left')
    plt.show()

    #rainfalls
    rainfalls = getRainfalls(fileName)

    rainfalls.reset_index()
    for r in regions:
        plt.plot(rainfalls.index, rainfalls[r], label=r) #, marker='o'

    plt.title('Rainfalls vs time')
    plt.xlabel('Time')
    plt.ylabel('Rainfalls')
    plt.grid(True)
    plt.legend(loc='upper left')
    plt.show()

    #EMA
    reg_name = 'JHR'
    production[reg_name].plot(label = reg_name)
    production[reg_name].ewm(span=5).mean().plot(label='EMA5')
    production[reg_name].ewm(span=10).mean().plot(label='EMA10')
    production[reg_name].ewm(span=20).mean().plot(label='EMA20')
    plt.title(reg_name + ' and EMAs')
    plt.legend(loc='upper left')
    plt.show()

dirname = os.path.dirname(__file__)
fileName = os.path.join(dirname, 'data/palm.xlsx')
regions = ['JHR', 'PHG', 'PRK', 'SBH', 'SWK', 'OTHERPEN']

data_plot()


from fastai.vision import *
from torchvision import datasets, transforms
from torch import nn
import PIL
import subprocess
from tqdm import tqdm
from sklearn import metrics
from collections import defaultdict
from dlcliche.data import *
from dlcliche.math import *
from dlcliche.fastai import *
from util_visualize import *

def delete_saved_models(data_path):
    print(f'Deleting *.pth under {Path(data_path).absolute()}...')
    subprocess.Popen(['find', str(Path(data_path).absolute()), '-name', '*.pth', '-delete'])

class Normalize(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self, input):
        return F.normalize(input)

def body_feature_model(model, normalize=False):
    """
    Returns a model that output flattened features directly from CNN body.
    """
    try:
        body, head = list(model.org_model.children()) # For XXNet defined in this notebook
    except:
        body, head = list(model.children()) # For original pytorch model
    return nn.Sequential(body, nn.Sequential(head[:-1], Normalize()) if normalize else head[:-1])

def get_embeddings(embedding_model, data_loader, label_catcher=None, return_y=False):
    """
    Calculate embeddings for all samples in a data_loader.

    Args:
        label_catcher: LearnerCallback for keeping last batch labels.
        return_y: Also returns labels, for working with training set.
    """
    embedding_model.eval()
    embs, ys = [], []
    for X, y in data_loader:
        # For each batch (X, y),
        #   Set labels (y) if label_catcher's there.
        if label_catcher:
            label_catcher.on_batch_begin(X, y, train=False)
        #   Get embeddings for this batch, store in embs.
        with torch.no_grad():
            # Note that model's output is not softmax'ed.
            out = embedding_model(X).cpu().detach().numpy()
            out = out.reshape((len(out), -1))
            embs.append(out)
        ys.append(y.cpu())
    # Putting all embeddings in shape (number of samples, length of one sample embeddings)
    embs = np.concatenate(embs) # Maybe in (10000, 10)
    ys   = np.concatenate(ys)
    if return_y:
        return embs, ys
    return embs

def visualize_embeddings(title, embeddings, ys, classes):
    return show_2D_tSNE(many_dim_vector=embeddings, target=[int(y) for y in ys], title=title, labels=classes)

def visualize_learner_embeddings(learn, title, all_data, size=0.5, normalize=True):
    valid_ds, valid_dl = prepare_subset_ds_dl(all_data.path/'valid', size=size, tfms=None)
    embs = get_embeddings(body_feature_model(learn.model, normalize=normalize), valid_dl)
    return visualize_embeddings(title=title, embeddings=embs, ys=[int(y) for y in valid_ds.y],
                                classes=valid_ds.y.classes)

def barplot_paired_charts(df_a, df_b, name_a, name_b, figsize=(14, 10), rot=30):
    a = df_a.copy()
    b = df_b.copy()
    a.columns = [org+'\n'+name_a for org in a.columns]
    b.columns = [org+'\n'+name_b for org in b.columns]
    la = [pd.DataFrame(a[col]) for col in a.columns]
    lb = [pd.DataFrame(b[col]) for col in b.columns]
    return (pd.concat([pd.concat([_a, _b], axis=1) for _a, _b in zip(la, lb)], axis=1)
            .boxplot(figsize=figsize, rot=rot))

def set_fastai_random_seed(seed=42):
    # https://docs.fast.ai/dev/test.html#getting-reproducible-results

    # python RNG
    random.seed(seed)

    # pytorch RNGs
    import torch
    torch.manual_seed(seed)
    torch.backends.cudnn.deterministic = True
    if torch.cuda.is_available(): torch.cuda.manual_seed_all(seed)

    # numpy RNG
    import numpy as np
    np.random.seed(seed)

def prepare_full_MNIST_databunch(data_path=Path('data_MNIST'), tfms=get_transforms(do_flip=False)):
    """Creates MNIST full set databunch."""
    restructured_path = prepare_full_MNIST(data_path)
    return ImageDataBunch.from_folder(restructured_path, valid_pct=None, ds_tfms=tfms)

def prepare_CIFAR10_databunch(data_path=Path('data_CIFAR10'), tfms=get_transforms(do_flip=False)):
    """Creates CIFAR10 full set databunch."""
    restructured_path = prepare_CIFAR10(data_path)
    return ImageDataBunch.from_folder(restructured_path, valid_pct=None, ds_tfms=tfms)

def prepare_subsampled_databunch(data_path, size=120, valid_pct=0.2, tfms=None, random_seed=42):
    if random_seed is not None: set_fastai_random_seed(seed=random_seed)
    files  = [Path(f) for f in subsample_files_in_tree(data_path/'train', '*.png', size=size)]
    files += [Path(f) for f in subsample_files_in_tree(data_path/'valid', '*.png', size=size)]
    labels = [Path(f).parent.name for f in files]
    return ImageDataBunch.from_lists(data_path, files, labels, valid_pct=valid_pct, ds_tfms=tfms)

def prepare_CIFAR10_train_subsampled_databunch(size=120, valid_pct=0.2, random_seed=42):
    """Creates CIFAR10 sub-sampled training databunch."""
    restructured_path = prepare_CIFAR10(data_path=Path('data_CIFAR10'))
    tfms=get_transforms(do_flip=False)
    return prepare_subsampled_databunch(restructured_path, size=size, valid_pct=valid_pct,
                                        tfms=tfms, random_seed=random_seed)

def prepare_subset_ds_dl(data_path, files=None, labels=None, size=0.1,
                         tfms=None, img_size=None, extension='.png'):
    # Sub-sample files
    if files is None:
        files = [Path(f) for f in subsample_files_in_tree(data_path, '*'+extension, size=size)]
    if labels is None:
        labels = [Path(f).parent.name for f in files]
    # Once create data bunch
    tmp_data = ImageDataBunch.from_lists(data_path, files, labels, valid_pct=0, ds_tfms=tfms, size=img_size)
    # Create dataloader again so that it surely set `shuffle=False`
    dl = torch.utils.data.DataLoader(tmp_data.train_ds, batch_size=tmp_data.batch_size, shuffle=False)
    dl = DeviceDataLoader(dl, tmp_data.device)
    return tmp_data.train_ds, dl

class ToyAnomalyDetection:
    "Toy Anomaly detection problem class"

    def __init__(self, base_databunch, n_anomaly_labels=1, n_cases=10, distance='cosine',
                 n_worsts=5, subsample_size=1, test_size=0.5, pred_fn=np.min):
        """
        Prerequisite:
            Create base databunch object in advance. Call prepare_full_MNIST_databunch()
            for example. (DATA ROOT)/images and valid folders will be used as data source.

        Args:
            base_databunch: Databunch fast.ai class object that holds whole dataset.
            n_anomaly_labels: Number of anomaly labels
            n_cases: Number of test cases; 1 to c
            distance: 'cosine' or 'euclidean'
            n_worsts: Number of samples to show worst cases.
            subsample_size: (0, 1) or 1 or integer to set size of subsampling train/valid sets.
            test_size: (0, 1) or 1 or integer to set size of subsampling test set.
            pred_fn: Function to predict distance; np.min() by default.
        """
        self.base_data, self.n_anomaly_labels, self.n_cases = base_databunch, n_anomaly_labels, n_cases
        self.distance, self.n_worsts, self.test_size, self.pred_fn = distance, n_worsts, test_size, pred_fn
        self.create_test_data(size=subsample_size)
        self.results = defaultdict(list)

    @property
    def c(self): return self.base_data.c

    @property
    def classes(self): return self.base_data.train_ds.y.classes

    @property
    def path(self): return self.base_data.path

    def anomaly_classes(self, case_no):
        def rotate(l, n):
            return l[n:] + l[:n]
        return rotate(list(range(self.c)), case_no)[:self.n_anomaly_labels]

    def all_classes(self):
        return list(range(self.c))

    def create_test_data(self, size=1):
        """
        Creates test case folders for unknown anomaly class detection problem.
        Each test cases removes `n_anomaly_labels` classes from training set,
        and model will detect removed class as anomaly class.

        Output:
            Data_root/images/case[0-9]/train and valid folders.
        """
        data_path = self.path
        for case_no in range(self.n_cases):
            case_folder = data_path/f'case{case_no}'
            ensure_delete(case_folder)
            ensure_folder(case_folder)
            ensure_folder(case_folder/'train')
            ensure_folder(case_folder/'valid')
            for ci in range(self.c):
                if ci in self.anomaly_classes(case_no): continue
                label = self.classes[ci]
                copy_subsampled_files(root=data_path/f'train/{label}', dest=case_folder/f'train/{label}',
                                      wildcard='[A-Za-z0-9_]*.*', size=size)
                copy_subsampled_files(root=data_path/f'valid/{label}', dest=case_folder/f'valid/{label}',
                                      wildcard='[A-Za-z0-9_]*.*', size=size)

    def databunch(self, case_no, tfms=get_transforms(do_flip=False)):
        """Creates test case ImageDataBunch."""
        return ImageDataBunch.from_folder(self.path/f'case{case_no}', ds_tfms=tfms)

    def store_results(self, name, result):
        self.results[name].append(result)

    def test(self, name, learner_fn, case_no):
        # train learner
        anomaly_data = self.databunch(case_no)
        learn = learner_fn(anomaly_data)

        # Create evaluation data: `test` is evaluation target, while this `train` is subset of training set
        eval_test_ds, eval_test_dl = prepare_subset_ds_dl(self.path/'valid', size=self.test_size, tfms=None)
        eval_train_ds, eval_train_dl = prepare_subset_ds_dl(self.path/f'case{case_no}/train', size=self.test_size, tfms=None)
        test_embs,  test_y  = get_embeddings(body_feature_model(learn.model), eval_test_dl, return_y=True)
        train_embs, train_y = get_embeddings(body_feature_model(learn.model), eval_train_dl, return_y=True)

        print(f'Evaluation size => test:{test_embs.shape}, train{train_embs.shape}')
        distances = n_by_m_distances(test_embs, train_embs, how=self.distance)
        print(f'Calculated distances in shape {distances.shape}')

        # Get basic values
        false_ys = self.anomaly_classes(case_no)
        test_anomaly_mask = [y in  false_ys for y in test_y]
        test_anomaly_idx = np.where(test_anomaly_mask)[0]
        y_true = np.array(list(map(int, test_anomaly_mask)))
        preds = self.pred_fn(distances, axis=1)

        # 1. worst case
        preds_y1 = preds[test_anomaly_mask]
        worst_anidxs = preds_y1.argsort()[:self.n_worsts]
        worst_test_idxs = test_anomaly_idx[worst_anidxs]
        worst_train_idxs = np.argmin(distances[worst_test_idxs], axis=1)

        worst_train_info = eval_train_ds.to_df().iloc[worst_train_idxs]
        worst_test_info  = eval_test_ds.to_df().iloc[worst_test_idxs]
        worst_test_info['distance'] = [distances[test_idx, trn_idx]
                                       for trn_idx, test_idx in zip(worst_train_idxs, worst_test_idxs)]
        worst_test_info['train_idx'] = worst_train_info.index
        worst_test_info['train_x'] = worst_train_info.x.values
        worst_test_info['train_y'] = worst_train_info.y.values

        # 2. ROC/AUC
        fpr, tpr, thresholds = metrics.roc_curve(y_true, preds)
        auc = metrics.auc(fpr, tpr)

        # 3. mean_class_distance
        mean_class_distance = [[np.mean(distances[test_y == cur_test_y, :][:, train_y == cur_trn_y])
                                for cur_trn_y in range(eval_train_dl.c)]
                               for cur_test_y in range(eval_test_dl.c)]
        distance_df = pd.DataFrame(mean_class_distance,
                                   columns=[self.classes[c] for c in range(eval_train_dl.c)])

        result = distance_df, (auc, fpr, tpr), worst_test_info
        self.store_results(name, result)
        return result

    def do_tests(self, name, learner_fn, delete_models=False):
        for case_no in range(self.n_cases):
            print(f'\nTesting {name} for case #{case_no}')
            self.test(name, learner_fn, case_no)
        if delete_models:
            delete_saved_models(self.path)

    def test_summary(self, results=None, names=None, auc_range=[0.4, 0.9], dist_range=list(range(10))):
        if results is None:
            names = self.results.keys()
            results = self.results.values()
        normal_dists = {name: [] for name in names}
        anomaly_dists = {name: [] for name in names}
        aucs = pd.DataFrame()
        for case_no in range(self.n_cases):
            for result, name in zip(results, names):
                distance_df, (auc, fpr, tpr), worst_test_info = result[case_no]
                # collect distances
                min_dists = distance_df.min(axis=1).values
                anocls = self.anomaly_classes(case_no)
                anomaly_dists[name].extend(min_dists[anocls])
                normal_dists[name].extend(min_dists[[c for c in self.all_classes() if c not in anocls]])
                # collect auc
                aucs.loc[case_no, name] = auc
        # distance metric
        distance_norms = pd.DataFrame(normal_dists).mean()
        normalized_anomaly_distances = pd.DataFrame(anomaly_dists)/distance_norms
        normalized_normal_distances = pd.DataFrame(normal_dists)/distance_norms

        print('# Stat: AUC')
        ax = aucs.boxplot(figsize=(5, 4), rot=30)
        if auc_range is not None: ax.set_ylim(*auc_range)
        plt.show()

        print('# Stat: Normalized distances')
        ax = barplot_paired_charts(normalized_anomaly_distances,
                                   normalized_normal_distances, 'Anomaly', 'Normal',
                                   figsize=(10, 5))
        if dist_range is not None: ax.set_yticks(dist_range)
        plt.show()

        # case detail
        for case_no in range(self.n_cases):
            case_df = pd.DataFrame(np.array([r[case_no][0].min(axis=1) for r in results]).T,
                                   columns=names)
            case_df.index = [f'<unk> {c}' if c in self.anomaly_classes(case_no) else str(c)
                             for c in self.all_classes()]
            print(f'\n## {self.anomaly_classes(case_no)}: normalized mean distance')
            display(case_df / distance_norms)

        self.normalized_anomaly_distances, self.aucs = normalized_anomaly_distances, aucs
        self.normalized_normal_distances = normalized_normal_distances
        return normalized_anomaly_distances, normalized_normal_distances, aucs

    def save_results(self, to_folder):
        ensure_folder(to_folder)
        self.normalized_anomaly_distances.to_csv(f'{str(to_folder)}/norm-ano-dist_anomaly={self.n_anomaly_labels}'
                                                 +f'_{self.distance}.csv')
        self.aucs.to_csv(f'{str(to_folder)}/auc_anomaly={self.n_anomaly_labels}_{self.distance}.csv')

    def show_worst_test_images(self, title, worst_test_info, case_no):
        fig, all_axes = plt.subplots(2, 5, figsize=(18, 7))
        fig.suptitle(title)
        for j, axes in enumerate(all_axes):
            for i, ax in enumerate(axes):
                cur = worst_test_info.loc[worst_test_info.index[i]]
                if j == 0:
                    img = load_rgb_image(self.path/f'valid/{cur.x}')
                    ax.set_title(f'Failed test/{cur.x}\ndistance={cur.distance:.6f}')
                else:
                    img = load_rgb_image(self.path/f'train/{cur.train_x}')
                    ax.set_title(f'confused w/ {cur.train_x}')
                show_np_image(img, ax=ax)

    def show_all_worst_test_images(self, case_no):
        for name, result in self.results.items():
            distance_df, (auc, fpr, tpr), worst_test_info = result[case_no]
            self.show_worst_test_images(f'{name} in test case #{case_no}', worst_test_info, case_no)


#! python 3
# kennex
#
import pygame

pygame.font.init()

class Control_Panel():
    """A class to store the control panel for the drawing editor."""

    def __init__(self, gs, screen):
        """Initialize the control panel."""
        self.gs = gs
        self.screen = screen
        self.color = gs.black
        self.selected = None
        self.dots = []

    def draw_control_panel(self, gs, screen):
        # Control Panel
        self.cp_bg = pygame.Rect(0, 0, 170, 80)
        pygame.draw.rect(screen, gs.white, self.cp_bg)
        pygame.draw.rect(screen, gs.black, self.cp_bg, 2)

        # Dot
        self.dot_text_image = gs.verdana12.render('DOT', True, gs.black)
        screen.blit(self.dot_text_image, (10, 10))
        self.dot_color = gs.black
        self.dot_text_image_rect = self.dot_text_image.get_rect()
        self.cp_button1 = pygame.Rect((self.dot_text_image_rect.right + 15), self.dot_text_image_rect.centery, 20, 20)

        # Line
        self.line_text_image = gs.verdana12.render('LINE', True, gs.black)
        screen.blit(self.line_text_image, (75, 10))
        self.line_color = gs.black
        self.line_text_image_rect = self.line_text_image.get_rect()
        self.cp_button2 = pygame.Rect((self.line_text_image_rect.right + 85), self.line_text_image_rect.centery, 20, 20)

        # Multiline
        self.mline_text_image = gs.verdana12.render('MLINE', True, gs.black)
        screen.blit(self.mline_text_image, (10, 40))
        self.mline_color = gs.black
        self.mline_text_image_rect = self.mline_text_image.get_rect()
        self.cp_button3 = pygame.Rect((self.mline_text_image_rect.right + 15), self.mline_text_image_rect.centery + 30, 20, 20)

        # Clear
        self.clear_text_image = gs.verdana12.render('CLEAR', True, gs.black)
        screen.blit(self.clear_text_image, (85, 40))
        self.clear_color = gs.black
        self.clear_text_image_rect = self.clear_text_image.get_rect()
        self.cp_button4 = pygame.Rect((self.clear_text_image_rect.right + 95), self.clear_text_image_rect.centery + 30, 20, 20)

        # Draw Buttons
        if self.selected == 1:
            self.dot_color = gs.red
        elif self.selected == 2:
            self.line_color = gs.red
        elif self.selected == 3:
            self.mline_color = gs.red
        elif self.selected == 4:
            self.dot_color = gs.black
            self.line_color = gs.black
            self.mline_color = gs.black
            self.clear_color = gs.black
            print(self.dots)
            self.selected = None
            self.dots = []

        pygame.draw.rect(screen, self.dot_color, self.cp_button1)
        pygame.draw.rect(screen, self.line_color, self.cp_button2)
        pygame.draw.rect(screen, self.mline_color, self.cp_button3)
        pygame.draw.rect(screen, self.clear_color, self.cp_button4)

    def draw_dots(self, gs, screen):
        # Draws dots to the screen until Clear is pressed
        for dot in self.dots:
            if self.dots.index(dot) > 0:
                pygame.draw.circle(screen, gs.red, dot, 5)

        #pygame.display.update()

    def draw_line(self, gs, screen, event):
        # Draws lines to the screen until Clear is pressed
        pass

    def draw_mline(self, gs, screen, event):
        # Draws multi-lines to the screen until Clear is pressed
        # Double click stops the lines
        pass

    def check_clicked_setting(self, gs, screen, event):
        # Choose which setting in control panel required
        if self.cp_button1.collidepoint(event.pos):
            self.selected = 1
        elif self.cp_button2.collidepoint(event.pos):
            self.selected = 2
        elif self.cp_button3.collidepoint(event.pos):
            self.selected = 3
        elif self.cp_button4.collidepoint(event.pos):
            self.selected = 4


import collections
import openpathsampling as paths
from openpathsampling.netcdfplus import StorableNamedObject
from openpathsampling.progress import SimpleProgress
import pandas as pd
import numpy as np

def steps_to_weighted_trajectories(steps, ensembles):
    """Bare function to convert to the weighted trajs dictionary.

    This prepares data for the faster analysis format. This preparation only
    need to be done once, and it will cover a lot of the analysis cases.

    Parameters
    ----------
    steps: iterable of :class:`.MCStep`
        steps to be analyzed
    ensembles: list of :class:`.Ensemble`
        ensembles to include in the list. Note: ensemble must be given!

    Returns
    -------
    dict of {:class:`.Ensemble`: collections.Counter}
        the result, with the ensemble as key, and a counter mapping each
        trajectory associated with that ensemble to its counter of time
        spent in the ensemble.
    """
    results = {e: collections.Counter() for e in ensembles}

    # loop over blocks # TODO: add blocksize parameter, test various sizes
    block_steps = steps
    block = collections.defaultdict(list)
    for step in block_steps:
        for ens in ensembles:
            block[ens].append(step.active[ens].trajectory)

    block_counter = {e: collections.Counter(block[e]) for e in ensembles}

    for e in results:
        results[e] += block_counter[e]

    return results

class TransitionDictResults(StorableNamedObject):
    """Analysis result object for properties of a transition.

    Each value is associated with a specific (analysis/physical) transition.
    This object allows those values to be accessed either using (as a key,
    i.e., in square brackets) any of:

    * the transition object for the (initial_state, final_state) pair
    * the tuple of (initial_state, final_state) for the transition
    * the sampling transition object, if ``allow_sampling==True``; this is
      only desired if the quantity is only dependent on the sampling
      transition

    Note that results cannot be changed in this; a new object must be made
    if that is desired (but the original input can be accessed with the
    .results_dict attribute, and then modified as needed).

    Parameters
    ----------
    results_dict : dict of 2-tuple of :class:`.Volume` to float or Quantity
        dict connecting tuple of (initial_state, final_state) to the
        associated quantity
    network : :class:`.TransitionNetwork`
        the transition network associated with these results
    allow_sampling : bool
        whether to allow elements of network.sampling_transitions to be used
        as keys for to retrieve the stored results; this only makes sense if
        the stored result is only dependent on the sampling transition
    """
    # allows you to use analysis transition, 2-tuple of states, or sampling
    # transition as the key to retrieve the stored results
    def __init__(self, results_dict, network, allow_sampling=True):
        # allow_sampling: can the sampling transitions be input?
        self.results_dict = results_dict
        self.network = network
        self.allow_sampling = allow_sampling

    def __iter__(self):
        return self.results_dict.__iter__()

    def __getitem__(self, key):
        if key in self.network.sampling_transitions and self.allow_sampling:
            key = self.network.sampling_to_analysis[key][0]
        try:
            key = (key.stateA, key.stateB)
        except AttributeError:
            # we have a stateA, stateB tuple
            pass
        return self.results_dict[key]

    def to_pandas(self, order=None):
        """Output stored results as pandas.DataFrame

        Parameters
        ----------
        order : list of :class:`.Volume`
            order in which to list the states; if not used, the order may be
            unpredictable

        Returns
        -------
        :class:`pandas.DataFrame`
            DataFrame with initial states as rows and final states as
            columns
        """
        key_map = lambda key: key.name
        keys = list(self.results_dict.keys())
        idx_vols = [k[0] for k in keys]
        col_vols = [k[1] for k in keys]
        if order is None:
            order = set(idx_vols + col_vols)
        index = [key_map(k) for k in order if k in idx_vols]
        columns = [key_map(k) for k in order if k in col_vols]
        result = pd.DataFrame(index=index, columns=columns)
        for k in keys:
            result.at[key_map(k[0]), key_map(k[1])] = self.results_dict[k]

        return result

    def __str__(self):  # pragma: no cover
        return self.to_pandas().__str__()

    def __repr__(self):
        return self.to_pandas().__repr__()

class MultiEnsembleSamplingAnalyzer(SimpleProgress, StorableNamedObject):
    """
    Abstract class for statistics from MC steps sampling multiple ensembles.

    Parameters
    ----------
    ensembles : list of :class:`.Ensemble`
        ensembles to be used in the calculation; can be overridden by
        :meth:`.calculate`
    """
    def __init__(self, ensembles=None):
        self.ensembles = ensembles

    def calculate(self, steps, ensembles=None):
        """Perform the analysis, using `steps` as input.

        This is the main analysis for the abstract
        :class:`.MultiEnsembleSamplingAnalyzer`. Specific results depend on
        the specific subclass. Most objects simply need to override
        :meth:`.from_weighted_trajectories` in order to obtain reasonable
        behavior.

        Parameters
        ----------
        steps : iterable of :class:`.MCStep`
            the steps to use as input for this analysis
        ensembles : list of :class:`.Ensemble`
            ensembles to include in the calculation (other ensembles will be
            stripped); default is `None` meaning all ensembles given during
            initialization.

        Returns
        -------
        See .from_weighted_trajectories for this class.
        """
        if ensembles is None:
            ensembles = self.ensembles
        if ensembles is None:
            raise RuntimeError("If self.ensembles is not set, then "
                               + "ensembles must be given as argument to "
                               + "calculate")
        steps = self.progress(steps, desc="Weighted trajectories")
        weighted_trajs = steps_to_weighted_trajectories(steps, ensembles)
        return self.from_weighted_trajectories(weighted_trajs)

    def from_weighted_trajectories(self, input_dict):
        """Calculate results from weighted trajectories dictionary.

        Must be implemented in subclass.
        """
        raise NotImplementedError

    @staticmethod
    def combine_results(result_1, result_2):
        """Combine two sets of results from this analysis.

        This can be used to combine results after parallelizing the
        analysis. The default is not implemented; it will only be
        implemented in cases where such a combination is feasible.
        """
        # to be used to simplify parallelization
        # TODO: implement this in subclasses in the future
        raise NotImplementedError

class EnsembleHistogrammer(MultiEnsembleSamplingAnalyzer):
    """
    Generic code to calculate the properly weighted histograms of trajectory
    properties per ensemble.

    Parameters
    ----------
    ensembles: list of :class:`.Ensemble`
        ensembles to be included in the histogram
    f: callable
        the function to be histogrammed
    hist_parameters: dict
        allowed keys are 'bin_width' and 'bin_range'; value for 'bin_width'
        is a float; for 'bin_range' is a tuple with `(left_edge,
        right_edge)` (only left edge is used)
    """
    _label = "Ensembles"
    def __init__(self, ensembles, f, hist_parameters):
        super(EnsembleHistogrammer, self).__init__(ensembles)
        self.f = f
        self.hist_parameters = hist_parameters
        self.hists = {e: paths.numerics.Histogram(**self.hist_parameters)
                      for e in self.ensembles}

    def from_weighted_trajectories(self, input_dict):
        """Calculate results from a weighted trajectories dictionary.

        Parameters
        ----------
        input_dict : dict of {:class:`.Ensemble`: collections.Counter}
            ensemble as key, and a counter mapping each trajectory
            associated with that ensemble to its counter of time spent in
            the ensemble (output of `steps_to_weighted_trajectories`)

        Returns
        -------
        dict of {:class:`.Ensemble`: :class:`.numerics.Histogram`}
            calculated histogram for each ensemble
        """
        hists = self.progress(self.hists, desc=self._label)
        for ens in hists:
            trajs = input_dict[ens].keys()
            weights = list(input_dict[ens].values())
            data = [self.f(traj)
                    for traj in self.progress(trajs, leave=False)]
            self.hists[ens].histogram(data, weights)
        return self.hists

class TISAnalysis(StorableNamedObject):
    """
    Generic class for TIS analysis. One of these for each network.

    In general, the TIS rate is split into the flux and the transition
    probability.

    Parameters
    ----------
    network : :class:`.TransitionNetwork`
        the reaction network to be analyzed
    flux_method : flux calculation method
        the method to use to calculate the flux; typical classes are
        :class:`.MinusMoveFlux` and :class:`.DictFlux`
    transition_probability_methods : dict of :class:`.Transition` to method
        the method for calculating the transition probability (one for each
        transition).
    """
    def __init__(self, network, flux_method, transition_probability_methods):
        self.network = network
        self.transitions = network.transitions
        self.flux_method = flux_method
        self.transition_probability_methods = transition_probability_methods
        self.results = {}

    def calculate(self, steps):
        """Perform the analysis, using `steps` as input.

        Parameters
        ----------
        steps : iterable of :class:`.MCStep`
            the steps to use as input for this analysis
        """
        self.results = {}
        flux_m = self.flux_method
        fluxes = flux_m.calculate(steps)
        self.results['flux'] = fluxes
        weighted_trajs = steps_to_weighted_trajectories(
            steps,
            self.network.sampling_ensembles
        )
        self.from_weighted_trajectories(weighted_trajs)

    def from_weighted_trajectories(self, input_dict):
        """Calculate results from weighted trajectories dictionary.

        Parameters
        ----------
        input_dict : dict of {:class:`.Ensemble`: collections.Counter}
            ensemble as key, and a counter mapping each trajectory
            associated with that ensemble to its counter of time spent in
            the ensemble (output of `steps_to_weighted_trajectories`)
        """
        # dict of transition to transition probability
        tp_m = self.transition_probability_methods
        trans_prob = {t: tp_m[t].from_weighted_trajectories(input_dict)
                      for t in tp_m.keys()}
        self.results['transition_probability'] = TransitionDictResults(
            {(t.stateA, t.stateB) : trans_prob[t] for t in trans_prob},
            self.network
        )

        fluxes = self.flux_matrix
        rates = {}
        for (trans, transition_probability) in trans_prob.items():
            trans_flux = fluxes[(trans.stateA, trans.interfaces[0])]
            rates[(trans.stateA, trans.stateB)] = \
                    trans_flux * transition_probability

        self.results['rate'] = TransitionDictResults(rates, self.network)
        return self.results

    def _access_cached_result(self, key):
        try:
            return self.results[key]
        except KeyError:
            raise AttributeError("Can't access results for '" + key
                                 + "' until analysis is performed")

    @property
    def flux_matrix(self):
        """dict of {(:class:`.Volume`, :class:`.Volume`): float}: keys are
        (state, interface); values are the associated flux
        """
        return self._access_cached_result('flux')

    def flux(self, from_state, through_interface=None):
        """Flux from a volume and through and interface.

        Shortcut to be used after the actual calculation has been performed.

        Parameters
        ----------
        from_state : :class:`.Volume`
            the volume the flux should start from
        through_interface : :class:`.Volume`
            the interface the flux should cross; default is None which uses
            the ``from_state`` volume

        Returns
        -------
        float or Quantity
            the flux out of the given state and through the given interface
        """
        fluxes = self._access_cached_result('flux')
        if through_interface is None:
            through_interface = from_state

        return fluxes[(from_state, through_interface)]

    def state_fluxes(self, from_state):
        """All fluxes associated with a given initial state.

        Shortcut to be used after the actual calculation has been performed.

        Parameters
        ----------
        from_state : :class:`.Volume`
            the volume the fluxes should start from

        Returns
        -------
        dict of 2-tuple of :class:`.Volume` to float
            dictionary of (state, interface) to the associated flux -- same
            as the flux dictionary given be :meth:`.flux_matrix`, but only
            including the cases with the desired state volume
        """
        fluxes = self._access_cached_result('flux')
        state_keys = [k for k in fluxes.keys() if k[0] == from_state]
        return {k: fluxes[k] for k in state_keys}

    @property
    def transition_probability_matrix(self):
        """
        :class:`.TransitionDictResults`: matrix of transition probabilities
        """
        return self._access_cached_result('transition_probability')

    def transition_probability(self, from_state, to_state):
        """Transition probability between two states.

        Parameters
        ----------
        from_state : :class:`.Volume`
            initial state in the transition
        to_state : :class:`.Volume`
            final state in the transition

        Returns
        -------
        float
            transition probability for the `from_state`->`to_state`
            transition
        """
        trans_probs = self._access_cached_result('transition_probability')
        return trans_probs[(from_state, to_state)]

    def rate_matrix(self, steps=None):
        """Calculate the rate matrix.

        Parameters
        ----------
        steps : iterable of :class:`.MCStep`
            the steps from a simulation to use for calculating the rate. If
            `None` (default), then use the existing cached results.

        Returns
        -------
        :class:`.TransitionDictResults`
            the rate matrix
        """
        if steps is not None:
            self.calculate(steps)
        return self._access_cached_result('rate')

    def rate(self, from_state, to_state):
        """Rate for the transition between two states

        Parameters
        ----------
        from_state : :class:`.Volume`
            initial state in the transition
        to_state : :class:`.Volume`
            final state in the transition

        Returns
        -------
        float or Quantity
            rate for the `from_state`->`to_state` transition
        """
        return self._access_cached_result('rate')[(from_state, to_state)]


import time
import pyautogui
import os
import random
import string

pyautogui.PAUSE = 1
pyautogui.FAILSAFE = True

search_amount = int(input("Enter the amount of searchs you want to perform: "))

os.system("google-chrome --new-tab")
pyautogui.click(x=0, y=50)
pyautogui.click(pyautogui.locateCenterOnScreen(
    "images/search-bar.png", confidence=0.5), duration=1)
time.sleep(1)

pyautogui.typewrite("https://www.bing.com/ \n")

for i in range(search_amount):
    term = ''.join(random.choice(string.ascii_letters)
                   for i in range(5)) + " \n"
    pyautogui.typewrite(term, interval=0.10)
    pyautogui.click(pyautogui.locateCenterOnScreen(
        "images/bing-search-bar.png", confidence=0.5))
    time.sleep(2)
pyautogui.alert(text="Done!", title="Aviso do sistema", button="OK")


import argparse

keyword = "mackerel"

words = [keyword]

def get_words(args):
	w = words
	if args.dictionary:
		try:
			with open(args.dictionary, 'r', encoding="utf8", errors='ignore') as f:
				content = f.readlines()
				w = [x.strip() for x in content]
		except Exception as e:
			print(e)
			print("Could not open dictionary")
	return w

def get_mackerel_words(args):
	try:
		with open(args.text_file, 'r', encoding="utf8", errors='ignore') as f:
			content = f.readlines()
	except Exception as e:
		print(e)
		print("Could not open text_file")
		return []
	content = [x.strip() for x in content]
	words = get_words(args)
	mackerel_words = []
	for word in words:
		counter = 0
		letter_set = set([c for c in word.lower()])
		rearrange = []
		for entry in content:
			ent_set = set([c for c in entry.lower()])
			if ent_set.isdisjoint(letter_set):
				counter += 1
				rearrange.append(entry)
		if counter == 1:
			mackerel_words.append((rearrange[0], word))
	return mackerel_words

def main():
	parser = argparse.ArgumentParser(description='Process some integers.')
	parser.add_argument('--text-file', type=str, default='states.txt',
	                    help='an integer for the accumulator')
	parser.add_argument('--dictionary',
	                    help='Words to look for mackerel words from.')

	args = parser.parse_args()
	mackerel_words = get_mackerel_words(args)
	for word, mackerel in mackerel_words:
		print("{} is the only word which shares no letters with the word {}.".format(word, mackerel))

	print("Script finished.")
if __name__ == "__main__":
	main()


import bpy
from . existing_keys import IDKey, findsIDKeys, removesIDKey
from . data_types import dataTypeByIdentifier, dataTypeIdentifiers

@findsIDKeys(removable = True)
def getIDKeysOnObjects():
    possibleKeys = set()
    for object in getAllObjects():
        for key in object.keys():
            if key.startswith("AN*"): possibleKeys.add(key)
    return filterRealIDKeys(possibleKeys)

def filterRealIDKeys(possibleKeys):
    realIDKeys = set()
    for key in possibleKeys:
        parts = key.split("*")
        if len(parts) == 3:
            if parts[1] in dataTypeIdentifiers:
                realIDKeys.add(IDKey(parts[1], parts[2]))
        elif len(parts) == 4:
            if parts[1] in dataTypeIdentifiers:
                realIDKeys.add(IDKey(parts[1], parts[3]))
    return realIDKeys

@removesIDKey
def removeIDKey(idKey):
    typeClass = dataTypeByIdentifier[idKey.type]
    for object in getAllObjects():
        typeClass.remove(object, idKey.name)

def getAllObjects():
    return bpy.data.objects