#!/usr/bin/env python3

import csv
import io
import json
import logging
import shutil
import tempfile
import zipfile
from typing import Any, Dict, List, Optional, Tuple

import pandas as pd
from fastapi import UploadFile

from app import models

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

def create_condense_assembly_files_input(
    designs: List[models.Design],
) -> Tuple[bytes, bytes]:
    individual_design_csvs = []
    with tempfile.NamedTemporaryFile() as tmp:
        with zipfile.ZipFile(tmp, "w", zipfile.ZIP_DEFLATED) as archive:
            for design in designs:
                if hasattr(design, "rawdesign"):
                    design_data = design.rawdesign.data
                else:
                    design_data = design["rawdesign"]["data"]  # type: ignore  # noqa
                for key in design_data.keys():
                    if (
                        key.endswith(".csv")
                        and key.startswith("p")
                        and not key.startswith("partslist")
                    ):
                        individual_design_csvs.append(key)
                        archive.writestr(key, design_data[key])
        tmp.seek(0)
        encoded_assembly_files_zip = tmp.read()
    encoded_assembly_files_list = (
        pd.DataFrame(individual_design_csvs, columns=["Assembly File Name"])
        .sort_values("Assembly File Name")
        .to_csv(index=False)
        .encode("utf-8")
    )
    return encoded_assembly_files_list, encoded_assembly_files_zip

def gather_genbanks(designs: List[models.Design]) -> Dict[str, str]:
    genbanks: Dict[str, str] = dict()
    for design in designs:
        if hasattr(design, "rawdesign"):
            design_data = design.rawdesign.data
        else:
            design_data = design["rawdesign"]["data"]  # type: ignore  # noqa
        for key in design_data.keys():
            if key.endswith(".gb"):
                genbanks[key] = design_data[key]
    return genbanks

def process_zip(zip_handle):
    json_handle = {}
    with tempfile.NamedTemporaryFile(delete=True, suffix=".zip") as tmp:
        shutil.copyfileobj(zip_handle, tmp)
        zip_file = zipfile.ZipFile(tmp, mode="r")
        for subfile in zip_file.namelist():
            json_handle[subfile] = zip_file.read(subfile).decode("utf-8")
    return json_handle

def parse_assembly_instructions(items):
    assemblyInstructionsRawText = [
        item for item in items if item.startswith("Combinations of Assembly Pieces")
    ][0]
    assemblyInstructionsDF = pd.read_csv(
        io.StringIO(assemblyInstructionsRawText),
        sep=",",
        header=0,
        skiprows=2,
    )
    assemblyInstructionsDF = assemblyInstructionsDF.rename(
        columns={
            "Part(s)": "Part(s).0",
            "Assembly Piece ID Number": "Assembly Piece ID Number.0",
        }
    )

    skinnyAssemblyInstructions = pd.DataFrame()
    for i in range(int((assemblyInstructionsDF.shape[1] - 3) / 2)):
        tmp = (
            assemblyInstructionsDF.melt(
                id_vars=["Number", "Name", "Assembly Method"],
                value_vars=[f"Part(s).{i}"],
                value_name="Part Name",
            )
            .drop(columns=["variable"])
            .merge(
                assemblyInstructionsDF.melt(
                    id_vars=["Number", "Name", "Assembly Method"],
                    value_vars=[f"Assembly Piece ID Number.{i}"],
                    value_name="Part ID",
                ).drop(columns=["variable"]),
                on=["Number", "Name", "Assembly Method"],
            )
        )
        tmp["Part Order"] = i
        skinnyAssemblyInstructions = skinnyAssemblyInstructions.append(tmp)
    skinnyAssemblyInstructions = (
        skinnyAssemblyInstructions.dropna()
        .sort_values(["Number", "Part Order"])
        .reset_index(drop=True)
    )
    return skinnyAssemblyInstructions.to_json()

def process_combinatorial_csv(csv_handle):
    json_handle = {}
    # Read condensed J5 File
    rawText = csv.reader(csv_handle, delimiter=",", dialect="excel")
    # Split into chunks
    cleanTxt = "\n".join([",".join(row).rstrip(",").lstrip('"') for row in rawText])
    items = cleanTxt.split("\n\n")
    # Get Oligos, Synths, Digests, PCRs
    for name, header in zip(
        ["oligos", "digests", "synths", "pcrs"],
        [
            "Oligo Synthesis",
            "Digest Linearized Pieces",
            "Direct Synthesis",
            "PCR Reactions",
        ],
    ):
        try:
            rawText = [item for item in items if item.startswith(header)][0]
            jsonText = pd.read_csv(
                io.StringIO(rawText), sep=",", header=0, skiprows=1
            ).to_json()
        except IndexError:
            jsonText = "{}"
        json_handle[name] = jsonText
    # Get Parts
    # Have to account for when multiple assembly methods are being used
    try:
        assemblyPartsRawText = [
            item for item in items if item.startswith("Assembly Pieces")
        ]
        assemblyPartsDFs = [
            pd.read_csv(io.StringIO(methodPieces), sep=",", header=0, skiprows=1)
            for methodPieces in assemblyPartsRawText
        ]
        assemblyPartsDF = (
            assemblyPartsDFs[0]
            if len(assemblyPartsDFs) == 1
            else assemblyPartsDFs[0]
            .append(assemblyPartsDFs[1:], sort=False)
            .sort_values(by="ID Number")
            .reset_index(drop=True)
        )
        partJsonText = assemblyPartsDF.to_json()
    except IndexError:
        partJsonText = "{}"
    json_handle["parts"] = partJsonText
    # Get Assemblys
    # Have to skinnify original table design
    try:
        assemblyJsonText = parse_assembly_instructions(items)
    except IndexError:
        assemblyJsonText = "{}"
    except KeyError:
        assemblyJsonText = "{}"
    json_handle["assemblys"] = assemblyJsonText
    csv_handle.seek(0)
    json_handle["raw_csv"] = csv_handle.read()
    return json_handle

def process_design_upload(
    upload_file: UploadFile, write: Optional[str] = None
) -> Dict[str, Any]:
    with tempfile.NamedTemporaryFile(delete=True, suffix=".zip") as tmp:
        shutil.copyfileobj(upload_file.file, tmp)
        zip_file = zipfile.ZipFile(tmp, mode="r")
        zip_json = {"zip_file_name": upload_file.filename}
        for subfile in zip_file.namelist():
            if subfile.endswith((".gb", ".eug")):
                zip_json[subfile] = zip_file.read(subfile).decode("utf8")
            elif subfile.endswith("combinatorial.csv"):
                csv_file = io.StringIO(zip_file.read(subfile).decode("utf8"))
                zip_json["combinatorial"] = process_combinatorial_csv(csv_file)
                zip_json["combinatorial"]["name"] = subfile
            elif subfile.endswith(".csv"):
                csv_text = zip_file.read(subfile).decode("utf8")
                try:
                    df = pd.read_csv(io.StringIO(csv_text)).to_json()
                except pd.errors.ParserError:
                    df = csv_text
                zip_json[subfile] = df
            elif subfile.endswith(".zip"):
                zip_json[subfile] = process_zip(io.BytesIO(zip_file.read(subfile)))
    if write:
        with open(write, "w") as F:
            json.dump(zip_json, F, indent=2)
    return zip_json


import numpy as np
print("If You Want To Enter Elements Of The Matrix Manually Enter m Else If You Want To Read It From File Enter f:")
t = input(" ")
tf = False
while tf is not True:
    if t == "m":                       # Get Matrix From User
        n = int(input("Please Enter The Dimension Of The Matrix: "))
        A0 = np.zeros((n, n))
        for i in range(0, n):
            for j in range(0, n):
                print("A[", i, ",", j, "] :")
                A0[i, j] = int(input(""))

        b = np.zeros(n)
        print(" Please Enter The Elements Of b: ")
        for i in range(0, n):
            print("b[", i, "]: ")
            b[i] = float(input(""))
        tf = True
    elif t == "f":                   # Read Matrix from a File
        a = np.array(([1, 4], [7, 5]))
        e = np.array([1, 1])
        np.savetxt("file1.text", a, delimiter=',')
        np.savetxt("file2.text", e, delimiter=',')
        A0 = np.loadtxt("file1.text", delimiter=',')
        b = np.loadtxt("file2.text", delimiter=',')
        print(A0)
        print("RHS vector")
        print(b)
        n, _ = np.shape(A0)
        tf = True
    else:
        t = input("_You Should Enter f or m_")
print("--------------------------------------")
row = np.zeros(n)
column = np.zeros(n)
A = A0.copy()
for k in range(0, n-1):
    Max = abs(A[k, k])                                             # FIND THE MAXIMUM VALUE IN MATRIX A[k]
    for i in range(k, n):
        for j in range(k, n):
            if abs(A[i, j]) > Max:
                Max = A[i, j]
                row[k] = i                                         # ROW WHICH INCLUDE THE MAXIMUM VALUE
                column[k] = j                                      # COLUMN WHICH INCLUDE THE MAXIMUM VALUE
    file = open("file.text", 'a')
    file.write('The Maximum Value In Step' + str(k+1) + ' Is: ' + str(A[int(row[k]), int(column[k])]))
    file.write('\n So Row And Column ' + str(k) + ' Should Replace By Row' + str(row[k]) + 'Column' + str(column[k]))
    file.close()

    temp1 = A[k, k:n].copy()                                        # REPLACE ROWS
    A[k, k:n] = A[int(row[k]), k:n].copy()
    A[int(row[k]), k:n] = temp1.copy()

    temp2 = A[:, k].copy()                                         # REPLACE COLUMNS
    A[:, k] = A[:, int(column[k])].copy()
    A[:, int(column[k])] = temp2.copy()

    file = open("file.text", 'a')
    file.write('\n Matrix A After Pivoting In Step ' + str(k+1) + 'Is: \n' + str(A))
    file.close()
    for i in range(k+1, n):
        A[i, k] = A[i, k] / A[k, k]

    for i in range(k+1, n):
        for j in range(k+1, n):
            A[i, j] = A[i, j] - A[i, k] * A[k, j]
    if k == n-2:
        file = open("file.text", 'a')
        file.write('\n Matrix A(n-1) = U is:\n' + str(A))
        file.close()
    else:
        file = open("file.text", 'a')
        file.write('\n A After Step ' + str(k+1) + ' is:' + '\n' + str(A))
        file.close()

############################################################################################################
M = np.zeros((n-1, n, n))                                                   # PRELIMINARY Matrix M(k)
for i in range(0, n-1):
    M[i, :, :] = np.eye(n)
    M[i, i+1:n, i] = -A[i+1:n, i]
    file = open("file.text", 'a')
    file.write('\n The Preliminary Matrix M In Step ' + str(i+1) + 'Is:\n' + str(M[i, :, :]))
    file.close()

Q = np.zeros((n-1, n, n))                                                   # PERMUTATION MATRIX Q(k)
QQ = np.eye(n)
for r in range(0, n-1):
    Q[r, :, :] = np.eye(n)
    t1 = Q[r, :, r].copy()
    Q[r, :, r] = Q[r, :, int(column[r])].copy()
    Q[r, :, int(column[r])] = t1.copy()
    file = open("file.text", 'a')
    file.write('\n Column Permutation Matrix Q In Step' + str(r+1) + 'Is:\n' + str(Q[r, :, :]))
    file.close()
    QQ = QQ.dot(Q[r, :, :])
file = open("file.text", 'a')
file.write('\n Final Permutation Matrix Q is:\n' + str(QQ))                  # QQ = Q(1) ... Q(n-1)
file.close()

P = np.zeros((n-1, n, n))                                                    # PERMUTATION MATRIX P(k)
for r in range(0, n-1):
    P[r, :, :] = np.eye(n)
    t2 = P[r, r, :].copy()
    P[r, r, :] = P[r, int(row[r]), :].copy()
    P[r, int(row[r]), :] = t2.copy()
    file = open("file.text", 'a')
    file.write('\n Row Permutation Matrix P In Step' + str(r+1) + ' Is:\n' + str(P[r, :, :]))
    file.close()
PP = np.eye(n)
for i in range(n-2, -1, -1):                                                  # PP = P(n-1) ... P(1)
    PP = PP.dot(P[i, :, :])
file = open("file.text", 'a')
file.write('\n Final Permutation Matrix P is:\n' + str(PP))
file.close()

U = np.triu(A)                                                                # UPPER TRIANGULAR MATRIX U
file = open("file.text", 'a')
file.write('\n The Upper Triangular Matrix U is:\n' + str(U))
file.close()

MM = np.eye(n)
for i in range(n-2, -1, -1):                                                 # MM = M(n-1)P(n-1) ... M(1)P(1)
    MM = MM.dot(M[i, :, :]).dot(P[i, :, :])
file = open("file.text", 'a')
file.write('\nFinal Permutation Matrix M Is:\n' + str(MM))
file.close()

L = np.dot(PP, np.linalg.inv(MM))                     # UNIT LOWER TRIANGULAR MATRIX L
file = open("file.text", 'a')
file.write('\n The Unit Lower Triangular Matrix L is:\n' + str(L))
file.close()

file = open("file.text", 'a')
file.write('\n MAQ - U:\n' + str(MM.dot(A0.dot(QQ)) - U))                         # MAQ - U ~ 0
file.write('\n PAQ - LU:\n' + str((PP.dot(A0.dot(QQ)) - L.dot(U))))               # PAQ - LU = 0
file.close()
#####################################################################################
#                        SOLVE SYSTEM Ax = b                                        #
#####################################################################################

# MAQ = U
# Ax = b
b1 = MM.dot(b)                                  # b1 = Mb
y1 = np.zeros(n)
x1 = np.zeros(n)
s1 = 0
y1[n-1] = b1[n-1]/U[n-1, n-1]
for i in range(n-2, -1, -1):                   # Uy = b1 (backward)
    for j in range(i+1, n):
        s1 += U[i, j] * y1[j]
    if U[i, i] != 0:
        y1[i] = (b1[i] - s1) / U[i, i]
        s1 = 0

x1 = QQ.dot(y1)                                   # x = Qy
file = open("file.text", 'a')
file.write('\nThe System is Solved Using MAQ = U\n')
file.write('The Answer is:\n' + str(x1))
file.close()
print("--------------------------------------")
# PAQ = LU
# Ax = b
# SOLVE SYSTEM Ax = b USING PAQ = LU
b2 = PP.dot(b)                                                # b2 = P*b
s2 = 0
s3 = 0
x2 = np.zeros(n)
z = np.zeros(n)
z[0] = b2[0] / L[0, 0]
y2 = np.zeros(n)
y2[n - 1] = z[n - 1] / U[n - 1, n - 1]
for i in range(1, n):                                          # Lz = b2 (forward)
    for j in range(1, i + 1):
        s2 += L[i, j - 1] * z[j - 1]
    if L[i, i] != 0:
        z[i] = (b2[i] - s2) / L[i, i]
        s2 = 0

y2[n-1] = z[n-1] / U[n-1, n-1]
for i in range(n - 2, -1, -1):                                # Uy = z (backward)
    for j in range(i + 1, n):
        s3 += U[i, j] * y2[j]
    if U[i, i] != 0:
        y2[i] = (z[i] - s3) / U[i, i]
        s3 = 0

x2 = QQ.dot(y2)                                               # x = Qy
file = open("file.text", 'a')
file.write('\nThe System is Solved Using PAQ = LU\n')
file.write('The Answer is:\n' + str(x2))
file.close()

print(" 'All Computations Are Stored In A File'  ")
print("--------------------------------------")


import cv2
import matplotlib.pyplot  as plt
fd= cv2.CascadeClassifier(
    cv2.data.haarcascades + 'haarcascade_frontalface_default.xml'  #github file
)
sd=cv2.CascadeClassifier(cv2.data.haarcascades+'haarcascade_smile.xml')

vid=cv2.VideoCapture(0)
captured=False
vid.isOpened()
flag,img=vid.read()
from time import sleep

while not captured:
    flag,img=vid.read()
    if flag:
        seq=0
        img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #to convert in gray

        th,img_binary=cv2.threshold(img_gray,80,255,cv2.THRESH_BINARY) #to convert in binary

        x1,y1,w,h = (200,400,300,400)
        # smile=sd.detectMultiScale(img_gray,1.1,5)
        # for x1,y1,w,h in smile:
        #     img_cropped = img[y1:y1+h, x1:x1+w , :] #crops the image

        #     cv2.rectangle(
        #                 img,
        #                 pt1=[x1,y1], pt2= [x1+w, y1+h],
        #                 color=(0,0,255),
        #                 thickness=10)

        faces= fd.detectMultiScale(
            img_gray,
            scaleFactor=1.1,
            minNeighbors=5,
            minSize=(50,50)) #face detection
                                                   #scaleFactor=1.1{search in face}
                                                   #minNeighbors=5{need to process the face }
                                                   #minSize=size of widhth & height{no of pixels}

        for x1,y1,w,h in faces:
            face = img[y1:y1+h, x1:x1+w , :].copy() #crops the image
            smiles = sd.detectMultiScale(face,1.1,15,minSize=(50,50))
            print(len(smiles))

            if len(smiles)==1:
                seq+=1
                if seq==2:
                    captured=cv2.imwrite('smile.png',img)
                    break

                #xs,ys,ws,hs = (200,400,300,4)
            xs,ys,ws,hs = smiles[0]
            cv2.rectangle(
                            img,
                            pt1=(xs+x1,ys+ys), pt2= (xs+x1+ws, y1+ys+hs),
                            color=(0,255,0),
                            thickness=10)
            cv2.rectangle(
                        img,
                        pt1=(x1,y1), pt2= (x1+w, y1+h),
                        color=(0,0,255),
                        thickness=10
                        )  #higlights the particular part
            #cv2.imwrite('smile.png',img)

            cv2.imshow('Preview',img)
        key=cv2.waitKey(1)
        if key==ord(' '): #will close the window when pressed spacebar
            break
    else :
        break
    sleep(0.1) #for delay
vid.release() #turns off the camera
cv2.destroyAllWindows()
#cv2.waitKey(1)    # only for Mac Os ,not for windows.


from serial import Serial

class SerialReader:
    def __init__(self,serialport):
        self.serial = Serial(serialport,9600)

    def getData(self):
        line = str(self.serial.readline())
        res = {}
        try:
            line = line[1:len(line)]
            line = line.replace("'",'')
            line = line.replace("\\r\\n",'')
            for i in line.split(","):
                res[i.split(":")[0]] = i.split(":")[1]
            return res
        except:
            raise IOError


"""4. Преобразовать слова «разработка», «администрирование», «protocol», «standard» из строкового представления в
байтовое и выполнить обратное преобразование (используя методы encode и decode)."""

my_list = ['разработка', 'администрирование', 'protocol', 'standard']

def task_4(word):
    for i in word:
        i_bite = str.encode(i, encoding='utf-8')
        print(i_bite)
        i_decode = bytes.decode(i_bite, encoding='utf-8')
        print(i_decode, '-' * 10, sep='\n')

task_4(my_list)


""" Unit tests for service functions of consumer app. """
#pylint: disable=C0103
from django.test import TestCase

from consumer.factories.consumer_factory import CONSUMER_FACTORY
from consumer.models import Consumer, ConsumerHistoryEvent, EmailSubscription
from consumer.service import (build_consumer_count_list,
    create_subscriber_for_consumer, get_consumer_instance_type, get_site_rep,
    process_consumer_opt_out, update_default_site_consumers,
    update_subscriber_of_consumer, qry_qualified_consumers)
from geolocation.models import USZip
from market.models import Site
from subscriber.models import MobilePhone, Subscriber

class FakeRequest(object):
    """ Fake request object. """
    pass

class TestService(TestCase):
    """ Test case for service functions of consumer app. """

    fixtures = ['test_consumer', 'test_sales_rep']

    @classmethod
    def setUpClass(cls):
        """ Build fake request for testing process_consumer_opt_out. """
        super(TestService, cls).setUpClass()
        cls.request = FakeRequest()
        cls.request.META = {'REMOTE_ADDR': '127.0.0.1'}

    def common_assertions_history(self, consumer):
        """ Assert ConsumerHistoryEvent log record. """
        log_history = ConsumerHistoryEvent.objects.latest('id')
        self.assertEqual(int(log_history.event_type), 1)
        self.assertEqual(log_history.ip, '127.0.0.1')
        self.assertEqual(log_history.consumer_id, consumer.id)
        data_dict = eval(log_history.data)
        return data_dict

    def test_update_default_site_cons(self):
        """ Assert consumers on site 1 having a zip code for site 2 are moved.
        """
        self.assertEqual(Consumer.objects.filter(site=1).count(), 3)
        update_default_site_consumers()
        self.assertEqual(Consumer.objects.filter(site=1).count(), 0)

    def test_get_site_rep_default(self):
        """ Assert that if site rep does not exist for this site, it will use
        default (site 1's).
        """
        site = Site.objects.get(id=2)
        rep = get_site_rep(site)
        self.assertEqual(rep.email_domain, '10Coupons.com')
        self.assertEqual(rep.consumer_id, 300)

    def test_get_site_rep_28(self):
        """ Assert that if site rep does exist, it will be selected. This test
        is for the North Jersey market.
        """
        site = Site.objects.get(id=28)
        rep = get_site_rep(site)
        self.assertEqual(rep.email_domain, '10NorthJerseyCoupons.com')
        self.assertEqual(rep.consumer_id, 301)

    def test_single_opt_out_current(self):
        """ Assert a single consumer opt out works with subscription_list
        param in current supported format.
        """
        subscription = [5]
        consumer = CONSUMER_FACTORY.create_consumer()
        consumer.email_subscription.add(subscription[0])
        self.assertTrue(consumer.email_subscription.get(id=1))
        self.assertTrue(consumer.email_subscription.get(id=subscription[0]))
        process_consumer_opt_out(self.request, consumer, subscription)
        self.assertTrue(consumer.email_subscription.get(id=1))
        with self.assertRaises(EmailSubscription.DoesNotExist):
            subscription = consumer.email_subscription.get(id=subscription[0])
        log_history_data = self.common_assertions_history(consumer)
        self.assertEqual(log_history_data['requested_list'], subscription)
        self.assertEqual(log_history_data['unsubscribed_list'], [5, 6])

    def test_flyer_opt_out_current(self):
        """ Assert consumer opt out of flye remail works with subscription_list
        param in current supported format.
        """
        subscription = [1]
        consumer = CONSUMER_FACTORY.create_consumer()
        consumer.email_subscription.add(2, 3, 4, 5, 6)
        self.assertTrue(consumer.email_subscription.get(id=1))
        process_consumer_opt_out(self.request, consumer, subscription)
        self.assertEqual(consumer.email_subscription.count(), 0)
        log_history_data = self.common_assertions_history(consumer)
        self.assertEqual(log_history_data['requested_list'], subscription)
        self.assertEqual(log_history_data['unsubscribed_list'], ['ALL'])

    def test_multi_opt_out_current(self):
        """ Assert consumer opt out works with multiple items in the
        subscription_list param in current supported format.
        """
        subscription = [2, 5]
        consumer = CONSUMER_FACTORY.create_consumer()
        consumer.email_subscription.add(2, 5, 6)
        self.assertTrue(consumer.email_subscription.get(id=1))
        self.assertTrue(consumer.email_subscription.get(id=2))
        self.assertTrue(consumer.email_subscription.get(id=5))
        self.assertTrue(consumer.email_subscription.get(id=6))
        process_consumer_opt_out(self.request, consumer, subscription)
        self.assertTrue(consumer.email_subscription.get(id=1))
        with self.assertRaises(EmailSubscription.DoesNotExist):
            subscription = consumer.email_subscription.get(id=2)
        with self.assertRaises(EmailSubscription.DoesNotExist):
            subscription = consumer.email_subscription.get(id=5)
        with self.assertRaises(EmailSubscription.DoesNotExist):
            subscription = consumer.email_subscription.get(id=6)
        log_history_data = self.common_assertions_history(consumer)
        self.assertEqual(log_history_data['requested_list'], subscription)
        self.assertEqual(log_history_data['unsubscribed_list'], [2, 5, 6])

    def test_flyer_opt_out_deprecated(self):
        """ Assert consumer opt out of flye remail works with subscription_list
        param in current supported format.
        """
        subscription = '01343'
        consumer = CONSUMER_FACTORY.create_consumer()
        self.assertTrue(consumer.email_subscription.get(id=1))
        consumer.email_subscription.add(2)
        process_consumer_opt_out(self.request, consumer, subscription)
        self.assertEqual(consumer.email_subscription.count(), 0)
        log_history_data = self.common_assertions_history(consumer)
        self.assertEqual(log_history_data['requested_list'], [1])
        self.assertEqual(log_history_data['unsubscribed_list'], ['ALL'])

    def test_opt_out_deprecated(self):
        """ Assert a single consumer opt out works with subscription_list
        param in deprecated format (as 5 character string).
        """
        subscription = '03343'
        consumer = CONSUMER_FACTORY.create_consumer()
        consumer.email_subscription.add(3)
        self.assertTrue(consumer.email_subscription.get(id=1))
        self.assertTrue(consumer.email_subscription.get(id=3))
        process_consumer_opt_out(self.request, consumer, subscription)
        self.assertTrue(consumer.email_subscription.get(id=1))
        with self.assertRaises(EmailSubscription.DoesNotExist):
            subscription = consumer.email_subscription.get(id=3)
        log_history_data = self.common_assertions_history(consumer)
        self.assertEqual(log_history_data['requested_list'], [3])
        self.assertEqual(log_history_data['unsubscribed_list'], [3])

class TestConsumerInstance(TestCase):
    """ Test identification of Consumer instances. """
    fixtures = ['test_consumer', 'test_advertiser', 'test_ad_rep',
        'test_media_partner']

    def test_unidentifiable(self):
        """ Test when no Consumer found with email. """
        user_type, is_ad_rep = \
            get_consumer_instance_type('unidentifiable@10coupons.com')
        self.assertEqual(user_type, None)
        self.assertEqual(is_ad_rep, False)

    def test_identify_consumer(self):
        """ Test when only Consumer instance. """
        user_type, is_ad_rep = get_consumer_instance_type('101@example.com')
        self.assertEqual(user_type, 'consumer')
        self.assertEqual(is_ad_rep, False)

    def test_identify_advertiser(self):
        """ Test when Advertiser instance. """
        user_type, is_ad_rep = \
            get_consumer_instance_type('113_user@example.com')
        self.assertEqual(user_type, 'advertiser')
        self.assertEqual(is_ad_rep, False)

    def test_identify_affiliate(self):
        """ Test when Affiliate instance. """
        user_type, is_ad_rep = \
            get_consumer_instance_type('test_affiliate@example.com')
        self.assertEqual(user_type, 'affiliate_partner')
        self.assertEqual(is_ad_rep, False)

    def test_identify_media_partner(self):
        """ Test when MediaPartner instance. """
        user_type, is_ad_rep = \
            get_consumer_instance_type('test_media_group@example.com')
        self.assertEqual(user_type, 'media_group_partner')
        self.assertEqual(is_ad_rep, False)

    def test_identify_consumer_ad_rep(self):
        """ Test when AdRep Consumer instance. """
        user_type, is_ad_rep = \
            get_consumer_instance_type('test-ad-rep@example.com')
        self.assertEqual(user_type, 'consumer')
        self.assertEqual(is_ad_rep, True)

    def test_identify_adv_ad_rep(self):
        """ Test when AdRep Advertiser instance. """
        user_type, is_ad_rep = \
            get_consumer_instance_type('test-ad-rep2@example.com')
        self.assertEqual(user_type, 'advertiser')
        self.assertEqual(is_ad_rep, True)

class TestConsumerSiteCountList(TestCase):
    """ Test case for service function build_consumer_count_list. """
    fixtures = ['test_advertiser', 'test_consumer', 'test_coupon',
        'test_coupon_views', 'test_flyer']

    def setUp(self):
        """ Build comparison of current before adding a consumer. """
        super(TestConsumerSiteCountList, self).setUp()
        self.hv_list = build_consumer_count_list(2)
        self.hv_count = self.hv_list[0]['county_count']
        self.hv_zip = self.hv_list[0]['cities'][0]['zips'][0]['zip']
        self.hv_site = Site.objects.get(id=2)
        self.consumer = Consumer.objects.create_consumer(
            username='illegit_consumer@site.com',
            email='illegit_consumer@site.com',
            consumer_zip_postal=self.hv_zip,
            site = self.hv_site
            )
        self.consumer.is_email_verified = True
        self.consumer.save()

    def test_orange_county_count(self):
        """ Assert the consumer count site list is built accurately. """
        oc_count = Consumer.objects.filter(site__id=2, is_email_verified=True,
            is_emailable=True,
            email_subscription=1, consumer_zip_postal__in=
            USZip.objects.filter(us_county__name='Orange'
            ).values_list('code', flat=True)).count()
        test_list = build_consumer_count_list(2)
        # Only one county is currently configured for site 2 (Orange).
        self.assertEqual(oc_count, test_list[0]['county_count'])
        self.assertEqual('Orange', test_list[0]['county'])
        self.assertEqual('12550', test_list[0]['cities'][0]['zips'][0]['zip'])
        self.assertEqual(oc_count,
            test_list[0]['cities'][0]['zips'][0]['zip_count'])

    def test_valid_count_site(self):
        """ Assert the consumers included in these counts are on the right site.
        """
        site = Site.objects.get(id=3)
        self.consumer.site = site
        self.consumer.save()
        test_list1 = build_consumer_count_list(2)
        self.assertEqual(self.hv_list[0]['county_count'],
            test_list1[0]['county_count'])
        self.consumer.site = self.hv_site
        self.consumer.save()
        test_list2 = build_consumer_count_list(2)
        self.assertEqual(self.hv_list[0]['county_count'] + 1,
            test_list2[0]['county_count'])

    def test_valid_count_subscription(self):
        """ Assert the consumers included in these counts have an email
        subscription.
        """
        self.consumer.email_subscription = []
        self.consumer.save()
        test_list6 = build_consumer_count_list(2)
        self.assertEqual(self.hv_list[0]['county_count'],
            test_list6[0]['county_count'])
        self.consumer.email_subscription = [1]
        self.consumer.save()
        test_list7 = build_consumer_count_list(2)
        self.assertEqual(self.hv_list[0]['county_count'] + 1,
            test_list7[0]['county_count'])

class TestQualifiedConsumers(TestCase):
    """ Assert result of queryset returned by qry_qualified_consumers abides by
    rules that exclude eligilbity.
    """
    fixtures = ['test_consumer', 'test_advertiser', 'test_coupon_views',
        'test_subscriber']

    def prep_consumer(self):
        """ Prepare consumer for tests. """
        mobile_phone = MobilePhone.objects.get(mobile_phone_number='8455550000')
        mobile_phone.is_verified = True
        mobile_phone.save()
        self.good_subscriber = Subscriber.objects.get(id=2)
        self.good_consumer = Consumer.objects.get(id=115)
        self.good_consumer.is_email_verified = True
        self.good_consumer.save()

    def common_asserts(self, consumer, test_name, test_msg):
        """ Common shared assertions for this test case. """
        result = qry_qualified_consumers()
        if result.filter(id=consumer.id).exists():
            self.fail('%s: %s' % (test_name, test_msg))

    def test_consumer_is_verified(self):
        """ Assert consumer has to be verified to be qualified. """
        self.prep_consumer()
        unverified_consumer = self.good_consumer
        unverified_consumer.is_email_verified = False
        unverified_consumer.subscriber = self.good_subscriber
        unverified_consumer.save()
        self.common_asserts(unverified_consumer, 'test_consumer_is_verified',
            'Unverified consumer email is identified as qualifying')

    def test_consumer_w_subscription(self):
        """ Assert consumer has to have Email Flyer subscription to qualify. """
        self.prep_consumer()
        unsubscribed_consumer = Consumer.objects.get(id=122)
        unsubscribed_consumer.subscriber = self.good_subscriber
        unsubscribed_consumer.save()
        self.common_asserts(unsubscribed_consumer, 'test_consumer_w_subscription',
            'Consumer without subscription is identified as qualifying')

    def test_consumer_no_subscriber(self):
        """ Assert consumer must have subscriber. """
        self.prep_consumer()
        self.common_asserts(self.good_consumer, 'test_consumer_no_subscriber',
            'Consumer without subscriber is identified as qualifying')

    def test_subscriber_no_phone(self):
        """ Assert consumer must have subscriber with mobile. """
        self.prep_consumer()
        subscriber = Subscriber.objects.get(id=3)
        self.good_consumer.subscriber = subscriber
        self.good_consumer.save()
        self.common_asserts(self.good_consumer, 'test_consumer_no_subscriber',
            'Consumer with subscriber with no mobile is qualifying.')

    def test_unverified_phone(self):
        """ Assert consumer must have subscriber with verified mobile. """
        self.prep_consumer()
        subscriber = Subscriber.objects.get(id=7)
        self.good_consumer.subscriber = subscriber
        self.good_consumer.save()
        self.common_asserts(self.good_consumer, 'test_consumer_no_subscriber',
            'Consumer with subscriber with no mobile is qualifying.')

    def test_qualified_consumer(self):
        """ Assert qualified consumer is selectable. """
        self.prep_consumer()
        self.good_consumer.subscriber = self.good_subscriber
        self.good_consumer.save()
        result = qry_qualified_consumers()
        self.assertEqual(result.filter(id=self.good_consumer.id).count(), 1)

class TestCreateSubForConsumer(TestCase):
    """ Test case for service function create_subscriber_for_consumer. """
    fixtures = ['test_consumer']

    def test_consumer_has_sub_no_phone(self):
        """ Assert a consumer having a subscriber who has no phone, a phone is
        created.
        """
        site = Site.objects.get(id=2)
        consumer = Consumer.objects.get(id=105)
        self.assertEqual(create_subscriber_for_consumer(consumer, 1,
            '2225550000', '12550', site), 0)
        try:
            mobile_phone = MobilePhone.objects.get(
                mobile_phone_number='2225550000')
        except MobilePhone.DoesNotExist:
            self.fail('Mobile phone not created.')
        self.assertEqual(mobile_phone.subscriber.consumer(), consumer)

    def test_consumer_has_subscriber(self):
        """ Assert when a consumer already has a subscriber who has a phone,
        0 is returned.
        """
        site = Site.objects.get(id=2)
        consumer = Consumer.objects.get(id=105)
        MobilePhone.objects.create(subscriber_id=30, carrier_id='2',
            mobile_phone_number='2225550001')
        self.assertEqual(create_subscriber_for_consumer(consumer, 1,
            '2225550001', '12550', site), 0)

    def test_con_has_sub_diff_number(self):
        """ Assert when this number belongs to a different subscriber, 0 is
        returned.
        """
        site = Site.objects.get(id=2)
        consumer = Consumer.objects.get(id=105)
        MobilePhone.objects.create(subscriber_id=31, carrier_id='2',
            mobile_phone_number='2225550002')
        self.assertEqual(create_subscriber_for_consumer(consumer, 1,
            '2225550002', '12550', site), 1)

class TestUpdateSubscriberOfConsumer(TestCase):
    """ Test case for update_subscriber_of_consumer. """
    fixtures = ['test_consumer']

    def test_mobile_phone_in_use(self):
        """ Assert if this mobile phone is already used, 1 is returned. """
        site = Site.objects.get(id=2)
        consumer = Consumer.objects.get(id=105)
        MobilePhone.objects.create(subscriber_id=31, carrier_id='2',
            mobile_phone_number='2225550003')
        self.assertEqual(update_subscriber_of_consumer(consumer, '2',
            '2225550003', '12550', site), 1)

    def test_subscriber_no_phone(self):
        """ Assert a subscriber without a phone gets a phone. """
        site = Site.objects.get(id=2)
        consumer = Consumer.objects.get(id=105)
        self.assertEqual(update_subscriber_of_consumer(consumer, '2',
            '2225550004', '12550', site), 0)
        try:
            mobile_phone = MobilePhone.objects.get(
                mobile_phone_number='2225550004')
        except MobilePhone.DoesNotExist:
            self.fail("Mobile phone not created.")
        self.assertEqual(list(consumer.subscriber.mobile_phones.all()),
            [mobile_phone])

    def test_con_has_sub_diff_number(self):
        """ Assert a consumer updates her phone number. """
        site = Site.objects.get(id=2)
        consumer = Consumer.objects.get(id=105)
        MobilePhone.objects.create(subscriber_id=30, carrier_id='2',
            mobile_phone_number='2225550005')
        # A different phone number:
        self.assertEqual(update_subscriber_of_consumer(consumer, '2',
            '2225550006', '12550', site), 0)
        try:
            mobile_phone = MobilePhone.objects.get(
                mobile_phone_number='2225550006')
        except MobilePhone.DoesNotExist:
            self.fail('Mobile phone not created.')
        self.assertEqual(mobile_phone.subscriber.consumer(), consumer)


def _to_plot(data):
    gridstyle = {"xgrid_line_color": None}
    curve_opts = opts.Curve(  # pylint: disable=no-member
        line_width=4,
        responsive=True,
        color=get_color_cycle(),
    )
    group_by = []
    if len(data.ElementName.unique()) > 1:
        group_by.append("Element")
    if len(data.InstanceName.unique()) > 1:
        group_by.append("Instance")
    return (
        data.rename(columns={"ElementName": "Element", "InstanceName": "Instance"})
        .hvplot(x="Datetime", y="Value", by=group_by)
        .opts(
            curve_opts,
        )
        .opts(show_grid=True)
    )


#find series and sum; a/a^2, a^2/a^3, a^3/a^4....n terms
sum=0
a=int(input("enter a: "))
n=int(input("enter no. of terms: "))
for i in range(0,n):
    t=(a**i)/(a**(i+1))
    print(t, end=' ')
    sum=sum+t
print()
print("sum is",sum)


import vehicle
import train
import airplane
import unittest

class TestVehicles(unittest.TestCase):
    def test_is_add_carrige(self):
        train_1 = train.Train('V-342', 80, 8, 60, 15)
        train_1.print_info()
        train_1.add_carriage_or_reduce(+2)
        train_1.print_info()
        self.assertEqual(train_1.carriage_n,17)

    def test_is_ruduce_carrige(self):
        train_1 = train.Train('V-342', 80, 8, 60, 15)
        train_1.print_info()
        train_1.add_carriage_or_reduce(-2)
        train_1.print_info()
        self.assertEqual(train_1.carriage_n,13)

    def test_is_count_tarin_speed(self):
        train_1 = train.Train('V-342', 80, 8, 60, 15)
        train_1.print_info()
        train_1.add_carriage_or_reduce(+2)
        train_1.print_info()
        self.assertTrue(train_1.speed == 45)

    def test_baggage(self):
        airplane_1 = airplane.Airplane('Boing-747', 40, 12, 200, 300)
        airplane_1.print_info()
        self.assertEqual(airplane_1.bagage_capacity , 400)

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


"""
Animator for obspy catalogs

:author: Calum J Chamberlain
:date: 30/5/2019
:licence: LGPL v3
"""

from obspy.imaging.cm import obspy_sequential
from obspy import Catalog, UTCDateTime
import numpy as np
from future.utils import native_str
import datetime
import warnings

from matplotlib.dates import AutoDateFormatter, AutoDateLocator, date2num
from matplotlib.cm import get_cmap

import cartopy.crs as ccrs
try:
    from progressbar import ProgressBar
    HAS_PROGRESS = True
except:
    HAS_PROGRESS = False

def _get_plot_coords(catalog):
    lats, lons, mags, colors = ([], [], [], [])
    if len(catalog) == 0:
        return [None], [None], [], []
    for event in catalog:
        if not event.origins:
            msg = ("Event '%s' does not have an origin and will not be "
                   "plotted." % str(event.resource_id))
            warnings.warn(msg)
            continue
        origin = event.preferred_origin() or event.origins[0]
        lats.append(origin.latitude)
        lons.append(origin.longitude)
        try:
            magnitude = event.preferred_magnitude() or event.magnitudes[0]
            mag = magnitude.mag
        except (IndexError, AttributeError):
            mag = 0.1
        mags.append(mag)
        colors.append((origin.get('depth') or np.nan) / 1e3)
    return lats, lons, mags, colors

def _get_event_time(event):
    """
    Get the time of an event - origin preferred, then pick.

    :type event: `obspy.core.event.Event`
    :return: UTCDateTime
    """
    try:
        origin = event.preferred_origin() or event.origins[0]
        t = origin.time
    except (IndexError, AttributeError):
        warnings.warn(
            "No origin time for event, defaulting to pick time")
        try:
            t = min([pick.time for pick in event.picks])
        except ValueError:
            raise AttributeError("No time for event")
    return t

def _blank_map(lons, lats, color, projection="global",
               resolution='110m', continent_fill_color='0.8',
               water_fill_color='1.0', colormap=None, colorbar=None,
               title=None, colorbar_ticklabel_format=None,
               color_label="Depth (km)", logarithmic_color=False,
               proj_kwargs=None, figsize=(20, 20), pad=0.05, norm=None,
               fig=None, map_ax=None, cm_ax=None):
    """
    Plot a map for the region appropriate for the catalog, but do not plot the
    events themselves.

    Used to set-up a figure before animation.

    :type lons: list/tuple of floats
    :param lons: Longitudes of the data points.
    :type lats: list/tuple of floats
    :param lats: Latitudes of the data points.
    :type color: list/tuple of floats (or objects that can be
        converted to floats, like e.g.
        :class:`~obspy.core.utcdatetime.UTCDateTime`)
    :param color: Color information of the individual data points to be
        used in the specified color map (e.g. origin depths,
        origin times).
    :type projection: str, optional
    :param projection: The map projection.
        Currently supported are:

            * ``"global"`` (Will plot the whole world using
              :class:`~cartopy.crs.Mollweide`.)
            * ``"ortho"`` (Will center around the mean lat/long using
              :class:`~cartopy.crs.Orthographic`.)
            * ``"local"`` (Will plot around local events using
              :class:`~cartopy.crs.AlbersEqualArea`.)
            * Any other Cartopy :class:`~cartopy.crs.Projection`. An instance
              of this class will be created using the supplied ``proj_kwargs``.

        Defaults to "global"
    :type resolution: str, optional
    :param resolution: Resolution of the boundary database to use. Will be
        passed directly to the Cartopy module. Possible values are:

            * ``"110m"``
            * ``"50m"``
            * ``"10m"``

        Defaults to ``"110m"``. If you specify another resolutoin,
        GSHHG will be used
    :type continent_fill_color: Valid matplotlib color, optional
    :param continent_fill_color:  Color of the continents. Defaults to
        ``"0.9"`` which is a light gray.
    :type water_fill_color: Valid matplotlib color, optional
    :param water_fill_color: Color of all water bodies.
        Defaults to ``"white"``.
    :type colormap: str, any matplotlib colormap, optional
    :param colormap: The colormap for color-coding the events as provided
        in `color` kwarg.
        The event with the smallest `color` property will have the
        color of one end of the colormap and the event with the highest
        `color` property the color of the other end with all other events
        in between.    if colorbar is not None:
        show_colorbar = colorbar
    else:
        if len(lons) > 1 and hasattr(color, "__len__") and \
                not isinstance(color, (str, native_str)):
            show_colorbar = True
        else:
            show_colorbar = False
        Defaults to None which will    if colorbar is not None:
        show_colorbar = colorbar
    else:
        if len(lons) > 1 and hasattr(color, "__len__") and \
                not isinstance(color, (str, native_str)):
            show_colorbar = True
        else:
            show_colorbar = False use the default matplotlib colormap.
    :type colorbar: bool, optional    if colorbar is not None:
        show_colorbar = colorbar
    else:
        if len(lons) > 1 and hasattr(color, "__len__") and \
                not isinstance(color, (str, native_str)):
            show_colorbar = True
        else:
            show_colorbar = False
    :param colorbar: When left `Non    if colorbar is not None:
        show_colorbar = colorbar
    else:
        if len(lons) > 1 and hasattr(color, "__len__") and \
                not isinstance(color, (str, native_str)):
            show_colorbar = True
        else:
            show_colorbar = False`, a colorbar is plotted if more than one
        object is plotted. Using `True`/`False` the colorbar can be forced
        on/off.
    :type title: str
    :param title: Title above plot.
    :type colorbar_ticklabel_format: str or function or
        subclass of :class:`matplotlib.ticker.Formatter`
    :param colorbar_ticklabel_format: Format string or Formatter used to format
        colorbar tick labels.
    :type proj_kwargs: dict
    :param proj_kwargs: Keyword arguments to pass to the Cartopy
        :class:`~cartopy.ccrs.Projection`. In this dictionary, you may specify
        ``central_longitude='auto'`` or ``central_latitude='auto'`` to have
        this function calculate the latitude or longitude as it would for other
        projections. Some arguments may be ignored if you choose one of the
        built-in ``projection`` choices.
    :return: Figure
    """
    from obspy.imaging.maps import (
        _CARTOPY_FEATURES, _CARTOPY_RESOLUTIONS, mean_longitude)
    import cartopy.feature as cfeature
    import matplotlib.pyplot as plt
    from matplotlib.cm import get_cmap
    from matplotlib.colorbar import ColorbarBase
    from matplotlib.colors import Normalize, LogNorm
    from matplotlib.ticker import (
        FormatStrFormatter, Formatter, FuncFormatter, MaxNLocator)

    if isinstance(color[0], (datetime.datetime, UTCDateTime)):
        datetimeplot = True
        color = [date2num(getattr(t, 'datetime', t)) for t in color]
    else:
        datetimeplot = False

    if fig is None:
        fig = plt.figure(figsize=figsize)

    # The colorbar should only be plotted if more then one event is
    # present.
    if colorbar is not None:
        show_colorbar = colorbar
    else:
        if len(lons) > 1 and hasattr(color, "__len__") and \
                not isinstance(color, (str, native_str)):
            show_colorbar = True
        else:
            show_colorbar = False

    if projection == "local":
        ax_x0, ax_width = 0.10, 0.80
    elif projection == "global":
        ax_x0, ax_width = 0.01, 0.98
    else:
        ax_x0, ax_width = 0.05, 0.90

    proj_kwargs = proj_kwargs or {}
    if projection == 'global':
        proj_kwargs['central_longitude'] = np.mean(lons)
        proj = ccrs.Mollweide(**proj_kwargs)
    elif projection == 'ortho':
        proj_kwargs['central_latitude'] = np.mean(lats)
        proj_kwargs['central_longitude'] = mean_longitude(lons)
        proj = ccrs.Orthographic(**proj_kwargs)
    elif projection == 'local':
        if min(lons) < -150 and max(lons) > 150:
            max_lons = max(np.array(lons) % 360)
            min_lons = min(np.array(lons) % 360)
        else:
            max_lons = max(lons)
            min_lons = min(lons)
        lat_0 = max(lats) / 2. + min(lats) / 2.
        lon_0 = max_lons / 2. + min_lons / 2.
        if lon_0 > 180:
            lon_0 -= 360
        deg2m_lat = 2 * np.pi * 6371 * 1000 / 360
        deg2m_lon = deg2m_lat * np.cos(lat_0 / 180 * np.pi)
        if len(lats) > 1:
            height = (max(lats) - min(lats)) * deg2m_lat
            width = (max_lons - min_lons) * deg2m_lon
            margin = pad * (width + height)
            height += margin
            width += margin
        else:
            height = 2.0 * deg2m_lat
            width = 5.0 * deg2m_lon
        # Do intelligent aspect calculation for local projection
        # adjust to figure dimensions
        w, h = fig.get_size_inches()
        aspect = w / h
        if show_colorbar:
            aspect *= 1.2
        if width / height < aspect:
            width = height * aspect
        else:
            height = width / aspect

        proj_kwargs['central_latitude'] = lat_0
        proj_kwargs['central_longitude'] = lon_0
        proj_kwargs['standard_parallels'] = [lat_0, lat_0]
        proj = ccrs.AlbersEqualArea(**proj_kwargs)

    # User-supplied projection.
    elif isinstance(projection, type):
        if 'central_longitude' in proj_kwargs:
            if proj_kwargs['central_longitude'] == 'auto':
                proj_kwargs['central_longitude'] = mean_longitude(lons)
        if 'central_latitude' in proj_kwargs:
            if proj_kwargs['central_latitude'] == 'auto':
                proj_kwargs['central_latitude'] = np.mean(lats)
        if 'pole_longitude' in proj_kwargs:
            if proj_kwargs['pole_longitude'] == 'auto':
                proj_kwargs['pole_longitude'] = np.mean(lons)
        if 'pole_latitude' in proj_kwargs:
            if proj_kwargs['pole_latitude'] == 'auto':
                proj_kwargs['pole_latitude'] = np.mean(lats)

        proj = projection(**proj_kwargs)

    else:
        msg = "Projection '%s' not supported." % projection
        raise ValueError(msg)

    # TODO: Add option to show cumulative plot
    if show_colorbar:
        if map_ax is None:
            map_ax = fig.add_axes([ax_x0, 0.13, ax_width, 0.77],
                                  projection=proj)
        elif not hasattr(map_ax, "projection") or map_ax.projection != proj:
            geom = map_ax.get_geometry()
            # Remove and rebuild
            map_ax.remove()
            map_ax = fig.add_subplot(*geom, projection=proj)
        if cm_ax is None:
            cm_ax = fig.add_axes([ax_x0, 0.05, ax_width, 0.05])
        plt.sca(map_ax)
    else:
        ax_y0, ax_height = 0.05, 0.85
        if projection == "local":
            ax_y0 += 0.05
            ax_height -= 0.05
        if map_ax is None:
            map_ax = fig.add_axes([ax_x0, ax_y0, ax_width, ax_height],
                                  projection=proj)
        elif not hasattr(map_ax, "projection") or map_ax.projection != proj:
            geom = map_ax.get_geometry()
            # Remove and rebuild
            map_ax.remove()
            map_ax = fig.add_subplot(*geom, projection=proj)

    if projection == 'local':
        x0, y0 = proj.transform_point(lon_0, lat_0, proj.as_geodetic())
        map_ax.set_xlim(x0 - width / 2, x0 + width / 2)
        map_ax.set_ylim(y0 - height / 2, y0 + height / 2)
    # else:
        # map_ax.set_global()
    map_ax.set_extent(
        [min(lons) - .5, max(lons) + .5, min(lats) - .5, max(lats) + .5],
        crs=ccrs.PlateCarree())

    # Pick features at specified resolution.
    if resolution in ("10m", "50m", "110m"):
        # Use NaturalEarthFeature interface
        resolution = _CARTOPY_RESOLUTIONS[resolution]
        try:
            borders, land, ocean = _CARTOPY_FEATURES[resolution]
        except KeyError:
            borders = cfeature.NaturalEarthFeature(cfeature.BORDERS.category,
                                                cfeature.BORDERS.name,
                                                resolution,
                                                edgecolor='none',
                                                facecolor='none')
            land = cfeature.NaturalEarthFeature(cfeature.LAND.category,
                                                cfeature.LAND.name, resolution,
                                                edgecolor='face', facecolor='none')
            ocean = cfeature.NaturalEarthFeature(cfeature.OCEAN.category,
                                                cfeature.OCEAN.name, resolution,
                                                edgecolor='face',
                                                facecolor='none')
            _CARTOPY_FEATURES[resolution] = (borders, land, ocean)

        # Draw coast lines, country boundaries, fill continents.
        map_ax.set_facecolor(water_fill_color)
        map_ax.add_feature(ocean, facecolor=water_fill_color, rasterized=True)
        map_ax.add_feature(land, facecolor=continent_fill_color, rasterized=True)
        map_ax.add_feature(borders, edgecolor='0.75', rasterized=True)
        map_ax.coastlines(resolution=resolution, color='0.4', rasterized=True)
    else:
        # Use the GSHHG interface
        coast = cfeature.GSHHSFeature(
            scale=resolution, levels=[1], facecolor=continent_fill_color,
            edgecolor="0.4")
        map_ax.set_facecolor(water_fill_color)
        map_ax.add_feature(coast, rasterized=True)

    # Draw grid lines - TODO: draw_labels=True doesn't work yet.
    if projection == 'local':
        map_ax.gridlines()
    else:
        # Draw lat/lon grid lines every 30 degrees.
        map_ax.gridlines(xlocs=range(-180, 181, 30), ylocs=range(-90, 91, 30))

    # scatter = map_ax.scatter(lons, lats, marker=marker, s=size, c=color,
    #                          zorder=10, cmap=colormap,
    #                          transform=ccrs.Geodetic())
    if norm is None:
        if logarithmic_color:
            norm = LogNorm(vmin=min(color), vmax=max(color))
        else:
            norm = Normalize(vmin=min(color), vmax=max(color))

    if title:
        plt.suptitle(title)

    # Only show the colorbar for more than one event.
    if show_colorbar:
        if colorbar_ticklabel_format is not None:
            if isinstance(colorbar_ticklabel_format, (str, native_str)):
                formatter = FormatStrFormatter(colorbar_ticklabel_format)
            elif hasattr(colorbar_ticklabel_format, '__call__'):
                formatter = FuncFormatter(colorbar_ticklabel_format)
            elif isinstance(colorbar_ticklabel_format, Formatter):
                formatter = colorbar_ticklabel_format
            locator = MaxNLocator(5)
        else:
            if datetimeplot:
                locator = AutoDateLocator()
                formatter = AutoDateFormatter(locator)
                # Compat with old matplotlib versions.
                if hasattr(formatter, "scaled"):
                    formatter.scaled[1 / (24. * 60.)] = '%H:%M:%S'
            else:
                locator = None
                formatter = None
        cmap = get_cmap(name=colormap)
        # Add arrows to cbar to indicate out of range data
        extend = "neither"
        if norm.vmax and norm.vmax < max(color):
            extend = "max"
        if norm.vmin and norm.vmin > min(color):
            if extend == "max":
                extend = "both"
            else:
                extend = "min"
        cb = ColorbarBase(
            cm_ax, norm=norm, cmap=cmap, orientation='horizontal',
            ticks=locator, format=formatter, extend=extend)
        cb.set_label(color_label)
        # Compat with old matplotlib versions.
        if hasattr(cb, "update_ticks"):
            cb.update_ticks()
    if show_colorbar:
        return fig, map_ax, cm_ax, cb
    return fig, map_ax

class AnimatedCatalog(Catalog):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def time_sort(self, *args, **kwargs):
        """
        Sort the catalog by time - origin-time preferred, but if not found,
        pick time will be used
        """
        _times = []
        for event in self.events:
            t = _get_event_time(event=event)
            _times.append((t, event))
        _times.sort(key=lambda _t: _t[0], *args, **kwargs)
        _, self.events = zip(*_times)
        return self

    def animate(self, projection='global', resolution='l',
                continent_fill_color='0.9', water_fill_color='1.0',
                colormap=None, show=True, title=None, time_step=86400,
                decay=10, interval=10, figsize=(15, 15), fig=None, **kwargs):
        """
        Animate the catalog in time.

        :type time_step: float
        :param time_step: Frame size in seconds.
        :type decay: int
        :param decay:
            How long to keep old events on the plot in frames - will fade out
            (decrease alpha) linearly through this period.
        :type interval: int
        :param interval: Time between frames (ms)

        :return:
        """
        import matplotlib.pyplot as plt
        from matplotlib.animation import FuncAnimation
        from matplotlib.colors import Normalize
        from collections import deque

        """################## Set up catalog chunks #######################"""
        self.time_sort()
        sub_catalogs, chunk_ends = ([], [])
        catalog_start = _get_event_time(event=self.events[0])
        catalog_end = _get_event_time(event=self.events[-1])
        chunk_start = catalog_start
        while chunk_start < catalog_end:
            chunk_end = chunk_start + time_step
            sub_catalog = Catalog([
                e for e in self.events
                if chunk_start <= _get_event_time(e) < chunk_end])
            sub_catalogs.append(sub_catalog)
            chunk_ends.append(chunk_end)
            chunk_start += time_step
        catalog_deck = deque([Catalog() for _ in range(decay)], maxlen=decay)
        alphas = np.linspace(0., 1., decay)

        frames = int(round(
            ((catalog_end - catalog_start) / time_step) + decay / 2, 0))

        """#################### Set up the empty figure ####################"""
        # lat/lon coordinates, magnitudes, dates
        lats, lons, mags, colors = _get_plot_coords(self)

        # Create the colormap for date based plotting.
        if colormap is None:
            colormap = obspy_sequential
        elif isinstance(colormap, str):
            colormap = get_cmap(colormap)
        norm = Normalize(vmin=min(colors), vmax=max(colors))

        if title is None:
            title = "Animated Catalog"

        min_size = 0.1
        max_size = 20
        min_size_ = min(mags) - 1
        max_size_ = max(mags) + 1

        if fig is None:
            fig, map_ax, _, _ = _blank_map(
                lons, lats, colors, projection=projection,
                resolution=resolution,
                continent_fill_color=continent_fill_color,
                water_fill_color=water_fill_color, colormap=colormap,
                title=title, color_label="Depth (km)", figsize=figsize)
        else:
            map_ax = fig.gca()

        """ ############# Set up the initial scatters ##################### """
        scatters = []
        for _, alpha in zip(catalog_deck, alphas):
            scatters.append(map_ax.scatter(
                [], [], marker="o", s=[], c=[], zorder=10,
                cmap=colormap, transform=ccrs.PlateCarree(), alpha=alpha))
        frame_time = catalog_start - interval
        timestamp = map_ax.text(
            0.05, 0.05, frame_time.strftime("%Y/%m/%d %H:%M:%S.%d"),
            horizontalalignment="left", verticalalignment="bottom",
            transform=map_ax.transAxes)

        if HAS_PROGRESS:
            bar = ProgressBar(max_value=frames)
        """ ####################### Animation function #####################"""
        def update(frame):
            if len(sub_catalogs) > 0:
                catalog_deck.append(sub_catalogs.pop(0))
            else:
                catalog_deck.append(Catalog())

            for i, cat in enumerate(catalog_deck):
                lats, lons, mags, colors = _get_plot_coords(cat)
                frac = [(0.2 + (_i - min_size_)) / (max_size_ - min_size_)
                        for _i in mags]
                size_plot = [(_i * (max_size - min_size)) ** 2 for _i in frac]
                # lons, lats needs to be transformed
                scatters[i].set_offsets(list(zip(lons, lats)))
                # Colors needs to be sequence of rgba tuples
                scatters[i].set_color(colormap(norm(colors), alphas[i]))
                scatters[i].set_sizes(size_plot)
            frame_time = catalog_start + (frame * time_step)
            timestamp.set_text(frame_time.strftime("%Y/%m/%d %H:%M:%S.%d"))
            if HAS_PROGRESS:
                bar.update(frame)
            else:
                print(f"\r{frame}")
            artists = [timestamp, *scatters]
            return artists

        anim = FuncAnimation(
            fig, update, frames=frames, interval=interval, repeat=False,
            blit=True)
        if HAS_PROGRESS:
            bar.finish()

        if show:
            plt.show()
        return anim

if __name__ == '__main__':
    from obspy.clients.fdsn import Client
    from matplotlib import animation

    client = Client("GEONET")
    cat = client.get_events(
        starttime=UTCDateTime(2019, 1, 1), endtime=UTCDateTime(2019, 1, 10),
        maxdepth=120, maxlatitude=-32., minlatitude=-49, minlongitude=164.2,
        maxlongitude=179.)
    print("Downloaded catalog of {0} events".format(len(cat)))
    ani_cat = AnimatedCatalog(cat)
    step = 1800
    fade_out = 3 * 86400
    decay = int(round(fade_out / step))
    fig = ani_cat.animate(
        projection="local", title="GeoNet Catalog", show=False, time_step=step,
        decay=decay, resolution="h")

    Writer = animation.writers['ffmpeg']
    writer = Writer(fps=45, metadata=dict(artist="Me"), bitrate=1800)

    fig.save("Test_animation.mp4", writer=writer)


# -*- coding: utf-8 -*-
"""
Created on Fri Mar 11 15:59:35 2016

@author: RJovelin
"""

# use this script to make a box plot figure comparing read depth betweem
# heteroplasmic and invariant positions either for WGS or RNAseq for a given cancer

# usage: PlotreadDepthVariablePositions.py [options]
# - inputfile: json file with dict {participant: [[read_depth_snps], [read_depth_not_variable]]}
# - [WGS/RNAseq]: datatype
# - outputfile: figure file

import os
import sys
import numpy as np
from scipy import stats
import json
import matplotlib.pyplot as plt

# get json file with read depth
datafile = sys.argv[1]
# get data type
data_type = sys.argv[2]
# get the outputfile name
outputfile = sys.argv[3]

# get the tumor type from the datafile
tumor_type = datafile[:datafile.index('_')]

# open file for reading
infile = open(datafile, 'r')
# load json dict {participant: [[read_depth_snps], [read_depth_not_variable]]}
ReadDepth = json.load(infile)
# close file
infile.close()

# create  a data list [[read_depth_snps], [read_depth_not_variable]]
AllData = [[], []]
# loop over dict
for participant in ReadDepth:
    # dump read depth in each inner list
    AllData[0].extend(ReadDepth[participant][0])
    AllData[1].extend(ReadDepth[participant][1])

# make a box plot figure comparing read depth betweem variable and non-variable positions

# make a list of position types
names = ['Variable', 'Conserved']

# create figure
#fig = plt.figure(1, figsize = (4.3,2.56))
fig = plt.figure(1, figsize = (2.5, 3))

# add a plot to figure (1 row, 1 column, 1 plot)
ax = fig.add_subplot(1, 1, 1)

# write label for y axis
ytext = ax.set_ylabel('Read depth', color = 'black', size = 10, ha = 'center', fontname = 'Arial', family = 'sans-serif')
xtext = ax.set_xlabel('MT sites', color = 'black', size = 10, ha = 'center', fontname = 'Arial', family = 'sans-serif')

# add labels to x-ticks, rotate and align right, set size to 14
ax.set_xticklabels(names, ha = 'center', size = 10, fontname = 'Arial', family = 'sans-serif')

# add a light grey horizontal grid to the plot, semi-transparent,
ax.yaxis.grid(True, linestyle='-', which='major', color='lightgrey', alpha=0.5)
# hide these grids behind plot objects
ax.set_axisbelow(True)

# remove top axes and right axes ticks
ax.get_xaxis().tick_bottom()
ax.get_yaxis().tick_left()

# use a boxplot
bp = ax.boxplot(AllData, showmeans = True, showfliers = False, widths = 0.7, labels = names, patch_artist = True)

# color WGS boxes in grey
i = 0
# change box, whisker color to black
for box in bp['boxes']:
    # change line color
    box.set(color = 'black')
    if i % 2 == 0:
        # SNPs data, color box in grey
        box.set(facecolor = [0.518, 0.439, 0.804])
    else:
        box.set(facecolor = [0.808, 0.765, 0.9])
    i += 1

# change whisker color ro black
for wk in bp['whiskers']:
    wk.set(color = 'black', linestyle = '-')

# change color of the caps
for cap in bp['caps']:
    cap.set(color = 'black')

# change the color and line width of the medians
for median in bp['medians']:
    median.set(color = 'black')

# change the mean marker and marker
for mean in bp['means']:
    mean.set(marker = 'o', markeredgecolor = 'black', markerfacecolor = 'black', markersize = 5)

# do not show lines around figure
ax.spines["top"].set_visible(False)
ax.spines["bottom"].set_visible(False)
ax.spines["right"].set_visible(False)
ax.spines["left"].set_visible(False)

# create a list with range of x-axis values
xvals = [i + 0.5 for i in range(len(names) + 1)]
# Set a buffer around the edge of the x-axis
plt.xlim([min(xvals)- 0.5, max(xvals)+ 0.5])

# do not show ticks
plt.tick_params(
    axis='y',       # changes apply to the x-axis and y-axis (other option : x, y)
    which='both',      # both major and minor ticks are affected
    bottom='off',      # ticks along the bottom edge are off
    top='off',         # ticks along the top edge are off
    right = 'off',
    left = 'off',
    labelbottom='off', # labels along the bottom edge are off
    colors = 'black',
    labelsize = 10)

# do not show ticks
plt.tick_params(
    axis='x',       # changes apply to the x-axis and y-axis (other option : x, y)
    which='both',      # both major and minor ticks are affected
    bottom='off',      # ticks along the bottom edge are off
    top='off',         # ticks along the top edge are off
    right = 'off',
    left = 'off',
    labelbottom='on', # labels along the bottom edge are on
    colors = 'black',
    labelsize = 10,
    direction = 'out') # ticks are outside the frame when bottom = 'on'

# Set the tick labels font name
for label in ax.get_yticklabels():
    label.set_fontname('Arial')

## note some ways to modify label font size and color of the ticks
#for label in ax.get_yticklabels():
#    label.set_color('black')
#    label.set_fontsize(10)

# add title
plt.title('Read depth in {0} for {1} data\n'.format(tumor_type, data_type), size = 12, fontname = 'Arial')

# annotate figure to add significance

# get the P value of Wilcoxon rank sum test
Pval = stats.ranksums(AllData[0], AllData[1])[1]
# get stars for significance
if Pval > 0.05:
    P = 'N.S.'
elif Pval < 0.05 and Pval > 0.01:
    P = '*'
elif Pval < 0.01 and Pval > 0.001:
    P = '**'
elif Pval < 0.001:
    P = '***'

# get the x and y coordinates
yvalues = []
yvalues.extend(AllData[0])
yvalues.extend(AllData[1])
# get max and min y values
y_min, y_max = min(yvalues), max(yvalues)

# add bracket
ax.annotate("", xy=(1, y_max), xycoords='data', xytext=(2, y_max),
            textcoords='data', arrowprops=dict(arrowstyle="-", ec='#aaaaaa',
            connectionstyle="bar,fraction=0.1"))
# add stars for significance
ax.text(1.5, y_max + abs(y_max - y_min)*0.05, P, horizontalalignment='center',
       verticalalignment='center', color = 'grey', fontname = 'Arial')

# add jittered data points to box plots (when data points are not too numerous)
# set x up coordinates
#a = np.random.uniform(-0.2, 0.2, len(AllData[0])) + 1
#b = np.random.uniform(-0.2, 0.2, len(AllData[1])) + 2
#plt.plot(a, AllData[0], 'o', markersize = 4, markeredgecolor='blue', markeredgewidth = 1.5, color = 'blue', alpha = 0.3)
#plt.plot(b, AllData[1], 'o', markersize = 4, markeredgecolor='blue', markeredgewidth = 1.5, color = 'blue', alpha = 0.3)

# save figure
fig.savefig(outputfile, bbox_inches = 'tight')


import os, socket, sys, json
from azure.iot.device import IoTHubDeviceClient, Message, MethodResponse
conn_str = os.getenv("conn_str")
osname = ""

if sys.platform == "linux":
    osname = str(os.uname().release + " " + os.uname().version + " " + os.uname().machine)
else:
    osname = str("Windows build " + str(sys.getwindowsversion().build) + " " + os.environ["PROCESSOR_IDENTIFIER"])

if conn_str == None:
    print("Please set the enviornment variable conn_str to the value of a device connection string")
    print("    example: export conn_str=\"HostName=ksaye.azure-devices.net;DeviceId=python;SharedAccessKey=4sDfmCBS1MnfVsQxUv/rEksRlzOctcOU=\"")
    print("exiting now")
    quit()
conn_str = conn_str.replace("\"","")
print("Connection String: " + conn_str)
print()

# reference: https://github.com/Azure/azure-iot-sdk-python/blob/main/samples/sync-samples/receive_direct_method.py
def method_request_handler(method_request):
    # Determine how to respond to the method request based on the method name
    if method_request.name == "method1":
        payload = {"result": True, "data": "some data"}  # set response payload
        status = 200  # set return status code
        print("executed method1")
    else:
        payload = {"result": False, "data": "unknown method"}  # set response payload
        status = 400  # set return status code
        print("executed unknown method: " + method_request.name)

    # Send the response
    method_response = MethodResponse.create_from_method_request(method_request, status, payload)
    device_client.send_method_response(method_response)

# reference: https://github.com/Azure/azure-iot-sdk-python/blob/main/samples/sync-samples/receive_message.py
def message_handler(message):
    print("the data in the message received was ")
    print(message.data)
    print("custom properties are")
    print(message.custom_properties)

# reference: https://github.com/Azure/azure-iot-sdk-python/blob/main/samples/sync-samples/receive_twin_desired_properties_patch.py
def twin_patch_handler(patch):
    print("the data in the desired properties patch was: {}".format(patch))

device_client = IoTHubDeviceClient.create_from_connection_string(conn_str)
device_client.connect()
device_client.on_message_received = message_handler
device_client.on_method_request_received = method_request_handler
device_client.on_twin_desired_properties_patch_received = twin_patch_handler

# get the initial twin, reference: https://github.com/Azure/azure-iot-sdk-python/blob/main/samples/sync-samples/get_twin.py
twin = device_client.get_twin()
print("Initial twin document received:")
print("    {}".format(twin))
print()

# setting a reported twin, reference: https://github.com/Azure/azure-iot-sdk-python/blob/main/samples/sync-samples/update_twin_reported_properties.py
reported_properties = {"OS": osname, "CurrentUser": str(os.environ["LOGNAME"]), "IP": str(socket.gethostbyname(socket.gethostname()))}

print("Sending reported twin properties:")
print("    {}".format(reported_properties))
print()
device_client.patch_twin_reported_properties(reported_properties)

#finally sending a message with properties and encoding
iotmessage = Message(json.dumps({"Message": "Hello World"}))
iotmessage.custom_properties["alert"] = False
iotmessage.content_encoding = "utf-8"
iotmessage.content_type = "application/json"
device_client.send_message(iotmessage)

input("Message " + str(iotmessage) + " and twin sent, waiting to reveive messages/command/twins, Press any key to quit\n")


import argparse

import torch.optim.lr_scheduler
import torchvision.transforms as transforms
import wandb

from torch.optim import SGD
from torch.utils.data import Subset
from tqdm import tqdm
import torch.nn as nn

from datasets.dataloader_animal10n import animal_dataset
from torchvision.models import vgg19_bn
from utils import *

parser = argparse.ArgumentParser('Train with ANIMAL-10N dataset')
parser.add_argument('--dataset_path', default='~/ANIMAL-10N', help='dataset path')

# model settings
parser.add_argument('--lambda_fc', default=1.0, type=float, help='weight of feature consistency loss (default: 1.0)')
parser.add_argument('--theta_s', default=1.0, type=float, help='threshold for voted correct samples (default: 1.0)')
parser.add_argument('--theta_r', default=0.95, type=float, help='threshold for relabel samples (default: 0.95)')
parser.add_argument('--k', default=200, type=int, help='neighbors for soft-voting (default: 200)')

# train settings
parser.add_argument('--epochs', default=150, type=int, metavar='N', help='number of total epochs to run (default: 200)')
parser.add_argument('--batch_size', default=128, type=int, help='mini-batch size (default: 128)')
parser.add_argument('--lr', default=0.02, type=float, help='initial learning rate (default: 0.02)')
parser.add_argument('--momentum', default=0.9, type=float, metavar='M', help='momentum of SGD solver (default: 0.9)')
parser.add_argument('--weight_decay', default=5e-4, type=float, help='weight decay (default: 5e-4)')
parser.add_argument('--seed', default=3047, type=int, help='seed for initializing training. (default: 3047)')
parser.add_argument('--gpuid', default='0', type=str, help='Selected GPU (default: "0")')
parser.add_argument('--entity', type=str, help='Wandb user entity')
parser.add_argument('--run_path', type=str, help='run path containing all results')

def train(labeled_trainloader, modified_label, all_trainloader, encoder, classifier, proj_head, pred_head, optimizer, epoch, args):
    encoder.train()
    classifier.train()
    proj_head.train()
    pred_head.train()
    xlosses = AverageMeter('xloss')
    ulosses = AverageMeter('uloss')
    labeled_train_iter = iter(labeled_trainloader)
    all_bar = tqdm(all_trainloader)
    for batch_idx, ([inputs_u1, inputs_u2],  _, _) in enumerate(all_bar):
        try:
            [inputs_x1, inputs_x2], labels_x, index = labeled_train_iter.next()
        except:
            labeled_train_iter = iter(labeled_trainloader)
            [inputs_x1, inputs_x2], labels_x, index = labeled_train_iter.next()

        # cross-entropy training with mixup
        batch_size = inputs_x1.size(0)
        inputs_x1, inputs_x2 = inputs_x1.cuda(), inputs_x2.cuda()
        labels_x = modified_label[index]
        targets_x = torch.zeros(batch_size, args.num_classes, device=inputs_x1.device).scatter_(1, labels_x.view(-1, 1), 1)
        l = np.random.beta(0.5, 0.5)
        l = max(l, 1 - l)
        all_inputs_x = torch.cat([inputs_x1, inputs_x2], dim=0)
        all_targets_x = torch.cat([targets_x, targets_x], dim=0)
        idx = torch.randperm(all_inputs_x.size()[0])
        input_a, input_b = all_inputs_x, all_inputs_x[idx]
        target_a, target_b = all_targets_x, all_targets_x[idx]
        mixed_input = l * input_a + (1 - l) * input_b
        mixed_target = l * target_a + (1 - l) * target_b

        logits = classifier(encoder(mixed_input))
        Lce = -torch.mean(torch.sum(F.log_softmax(logits, dim=1) * mixed_target, dim=1))

        # optional feature-consistency
        inputs_u1, inputs_u2 = inputs_u1.cuda(), inputs_u2.cuda()

        feats_u1 = encoder(inputs_u1)
        feats_u2 = encoder(inputs_u2)
        f, h = proj_head, pred_head

        z1, z2 = f(feats_u1), f(feats_u2)
        p1, p2 = h(z1), h(z2)
        Lfc = D(p2, z1)
        loss = Lce + args.lambda_fc * Lfc
        xlosses.update(Lce.item())
        ulosses.update(Lfc.item())
        all_bar.set_description(
            f'Train epoch {epoch} LR:{optimizer.param_groups[0]["lr"]} Labeled loss: {xlosses.avg:.4f} Unlabeled loss: {ulosses.avg:.4f}')

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
    logger.log({'ce loss': xlosses.avg, 'fc loss': ulosses.avg})

def test(testloader, encoder, classifier, epoch):
    encoder.eval()
    classifier.eval()
    accuracy = AverageMeter('accuracy')
    data_bar = tqdm(testloader)
    with torch.no_grad():
        for i, (data, label, _) in enumerate(data_bar):
            data, label = data.cuda(), label.cuda()
            feat = encoder(data)
            res = classifier(feat)
            pred = torch.argmax(res, dim=1)
            acc = torch.sum(pred == label) / float(data.size(0))
            accuracy.update(acc.item(), data.size(0))
            data_bar.set_description(f'Test epoch {epoch}: Accuracy#{accuracy.avg:.4f}')
    logger.log({'acc': accuracy.avg})
    return accuracy.avg

def evaluate(dataloader, encoder, classifier, args, noisy_label):
    encoder.eval()
    classifier.eval()
    feature_bank = []
    prediction = []

    ################################### feature extraction ###################################
    with torch.no_grad():
        # generate feature bank
        for (data, target, index) in tqdm(dataloader, desc='Feature extracting'):
            data = data.cuda()
            feature = encoder(data)
            feature_bank.append(feature)
            res = classifier(feature)
            prediction.append(res)
        feature_bank = F.normalize(torch.cat(feature_bank, dim=0), dim=1)

        ################################### sample relabelling ###################################
        prediction_cls = torch.softmax(torch.cat(prediction, dim=0), dim=1)
        his_score, his_label = prediction_cls.max(1)

        print(f'Prediction track: mean: {his_score.mean()} max: {his_score.max()} min: {his_score.min()}')
        conf_id = torch.where(his_score > args.theta_r)[0]
        modified_label = torch.clone(noisy_label).detach()
        modified_label[conf_id] = his_label[conf_id]

        ################################### sample selection ###################################
        prediction_knn = weighted_knn(feature_bank, feature_bank, modified_label, args.num_classes, args.k, 10)  # temperature in weighted KNN
        vote_y = torch.gather(prediction_knn, 1, modified_label.view(-1, 1)).squeeze()
        vote_max = prediction_knn.max(dim=1)[0]
        right_score = vote_y / vote_max
        clean_id = torch.where(right_score >= args.theta_s)[0]
        noisy_id = torch.where(right_score < args.theta_s)[0]

    return clean_id, noisy_id, modified_label

def main():
    args = parser.parse_args()
    seed_everything(args.seed)
    if args.run_path is None:
        args.run_path = f'Dataset(animal10n_Model({args.theta_r}_{args.theta_s})'

    os.environ['CUDA_VISIBLE_DEVICES'] = args.gpuid
    global logger
    logger = wandb.init(project='animal10n', entity=args.entity, name=args.run_path)
    logger.config.update(args)

    if not os.path.isdir(f'animal10n'):
        os.mkdir(f'animal10n')
    if not os.path.isdir(f'animal10n/{args.run_path}'):
        os.mkdir(f'animal10n/{args.run_path}')

    ############################# Dataset initialization ##############################################
    args.num_classes = 10
    args.image_size = 64

    # data loading
    weak_transform = transforms.Compose([
        transforms.RandomCrop(args.image_size, padding=8),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor()])
    none_transform = transforms.Compose([transforms.ToTensor()])  # no augmentation
    strong_transform = transforms.Compose([transforms.RandomCrop(args.image_size, padding=8),
                                           transforms.RandomHorizontalFlip(),
                                           RandAugment(),
                                           transforms.ToTensor()])

    # eval data served as soft-voting pool
    train_data = animal_dataset(root=args.dataset_path, transform=KCropsTransform(strong_transform, 2), mode='train')
    eval_data = animal_dataset(root=args.dataset_path, transform=weak_transform, mode='train')
    test_data = animal_dataset(root=args.dataset_path, transform=none_transform, mode='test')
    all_data = animal_dataset(root=args.dataset_path, transform=MixTransform(strong_transform, weak_transform, 1), mode='train')

    # noisy labels
    noisy_label = torch.tensor(eval_data.targets).cuda()

    test_loader = torch.utils.data.DataLoader(test_data, batch_size=args.batch_size, shuffle=False, num_workers=4, pin_memory=True)
    eval_loader = torch.utils.data.DataLoader(eval_data, batch_size=args.batch_size, shuffle=False, num_workers=4, pin_memory=True)
    all_loader = torch.utils.data.DataLoader(all_data, batch_size=args.batch_size, shuffle=True, num_workers=4, pin_memory=True)

    ################################ Model initialization ###########################################
    encoder = vgg19_bn(pretrained=False)
    encoder.classifier = nn.Sequential(
        nn.Linear(512 * 7 * 7, 4096),
        nn.ReLU(True),
        nn.Dropout(p=0.2),
        nn.Linear(4096, 4096),
        nn.ReLU(True),
        nn.Dropout(p=0.2),
    )

    def init_weights(m):
        if type(m) == nn.Linear:
            nn.init.normal_(m.weight, 0, 0.005)
            nn.init.constant_(m.bias, 0)

    encoder.classifier.apply(init_weights)
    classifier = nn.Linear(4096, args.num_classes)
    proj_head = torch.nn.Sequential(torch.nn.Linear(4096, 256),
                                    torch.nn.BatchNorm1d(256),
                                    torch.nn.ReLU(),
                                    torch.nn.Linear(256, 128))
    pred_head = torch.nn.Sequential(torch.nn.Linear(128, 256),
                                    torch.nn.BatchNorm1d(256),
                                    torch.nn.ReLU(),
                                    torch.nn.Linear(256, 128))
    classifier.apply(init_weights)

    encoder.cuda()
    classifier.cuda()
    proj_head.cuda()
    pred_head.cuda()

    #################################### Training initialization #######################################
    optimizer = SGD([{'params': encoder.parameters()}, {'params': classifier.parameters()}, {'params': proj_head.parameters()}, {'params': pred_head.parameters()}],
                    lr=args.lr, weight_decay=args.weight_decay, momentum=args.momentum)
    scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones=[50, 100], gamma=0.1)

    acc_logs = open(f'animal10n/{args.run_path}/acc.txt', 'w')
    save_config(args, f'animal10n/{args.run_path}')
    print('Train args: \n', args)
    best_acc = 0

    ################################ Training loop ###########################################
    for i in range(args.epochs):
        clean_id, noisy_id, modified_label = evaluate(eval_loader, encoder, classifier, args, noisy_label)

        clean_subset = Subset(train_data, clean_id.cpu())
        sampler = ClassBalancedSampler(labels=modified_label[clean_id], num_classes=args.num_classes)
        labeled_loader = torch.utils.data.DataLoader(clean_subset, batch_size=args.batch_size, sampler=sampler, num_workers=4, drop_last=True)

        train(labeled_loader, modified_label, all_loader, encoder, classifier, proj_head, pred_head, optimizer, i, args)

        cur_acc = test(test_loader, encoder, classifier, i)
        scheduler.step()
        if cur_acc > best_acc:
            best_acc = cur_acc
            save_checkpoint({
                'cur_epoch': i,
                'classifier': classifier.state_dict(),
                'encoder': encoder.state_dict(),
                'proj_head': proj_head.state_dict(),
                'pred_head': pred_head.state_dict(),
                'optimizer': optimizer.state_dict(),
            }, filename=f'animal10n/{args.run_path}/best_acc.pth.tar')
        acc_logs.write(f'Epoch [{i}/{args.epochs}]: Best accuracy@{best_acc}! Current accuracy@{cur_acc} \n')
        acc_logs.flush()
        print(f'Epoch [{i}/{args.epochs}]: Best accuracy@{best_acc}! Current accuracy@{cur_acc} \n')
    save_checkpoint({
        'cur_epoch': i,
        'classifier': classifier.state_dict(),
        'encoder': encoder.state_dict(),
        'proj_head': proj_head.state_dict(),
        'pred_head': pred_head.state_dict(),
        'optimizer': optimizer.state_dict(),
    }, filename=f'animal10n/{args.run_path}/last.pth.tar')

if __name__ == '__main__':
    main()


'''
N과 M (1)
https://www.acmicpc.net/problem/15649
'''

# 백트래킹 입문 문제 1

import sys
input = sys.stdin.readline

def btk():
    if len(s) == m:
        print(' '.join(map(str, s)))
        return

    for i in range(1, n+1):
        if i in s:
            continue
        s.append(i)
        btk()
        s.pop()

n, m = map(int, input().split())
s = []
btk()

'''

다른 풀이 - itertools의 permutations 함수 사용(파이썬만 가능)

import sys, itertools
input = sys.stdin.readline

n, m = map(int, input().split())
ary = [i for i in range(1, n+1)]

c = itertools.permutations(ary, m)

for i in c:
    for j in i:
        print(j, end=" ")
    print()

## combinations : 중복 가능

'''

단계별로 풀어보기/백트래킹/15649.py


# For strings S and T, we say "T divides S" if and only if S = T + ... + T  (T concatenated with itself 1 or more times)
#
# Return the largest string X such that X divides str1 and X divides str2.
#
# Example 1:
#
# Input: str1 = "ABCABC", str2 = "ABC"
# Output: "ABC"
# Example 2:
#
# Input: str1 = "ABABAB", str2 = "ABAB"
# Output: "AB"
# Example 3:
#
# Input: str1 = "LEET", str2 = "CODE"
# Output: ""
#
#
# Note:
#
# 1 <= str1.length <= 1000
# 1 <= str2.length <= 1000
# str1[i] and str2[i] are English uppercase letters.

# from collections import Counter
#
# def gcdOfStrings(str1, str2):
#     l1, l2 = len(str1), len(str2)
#     if l2 > l1:
#         gcdOfStrings(str2, str1)
#
#     if l1 % l2 == 0:
#         count = l1 / l2
#         final_str = ""
#
#         while count:
#             final_str += str2
#             count -= 1
#
#         if final_str == str1:
#             return str2
#
#     if not set(Counter(str2).keys()).issubset(Counter(str1).keys()):
#         return ""
#     elif str1 not in str2 and str2 not in str1:
#         return ""

def gcdOfStrings(str1, str2):
    # if the two strings are equal (base case)
    # return the first string
    # otherwise return ''
    if len(str1) == len(str2):
        return str1 if str1==str2 else ''
    else:
        if len(str1) < len(str2):
            str1,str2 = str2,str1
        if str1[:len(str2)] == str2:
            return gcdOfStrings(str1[len(str2):],str2)
        else:
            return ''

# since ABAB and ABAB match
# would call gcd on "AB" and "ABAB"
# which would then call gcd on "AB", "AB"
# which would return "AB"
gcdOfStrings("ABABAB", "ABAB")

#
# str1 = "ABCABC"
# str2 = "ABC"
# print (gcdOfStrings(str1, str2))
#
# str1 = "ABABAB"
# str2 = "ABAB"
# print (gcdOfStrings(str1, str2))
#
# str1 = "LEET"
# str2 = "CODE"
# print (gcdOfStrings(str1, str2))


import os

from .App import start

AppId="dev.salaniLeo.forecast"
app_type = None
appimage = False

if 'FLATPAK_SANDBOX_DIR' in os.environ:
    flatpak = True
    app_type = 'flatpak'

if 'IS_APP_APPIMAGE' in os.environ:
    appimage = True
    app_type = 'appimage'

if 'IS_DEBIAN' in os.environ:
    appimage = True
    app_type = 'debian'

class main():
    app = start(AppId, app_type)


import db

class Versioner:
    def __init__(self,kind,after=None):
        self.versions = []
        self.name = kind + 'Version';
        self.after = after
    def setup(self):
        #print(self.name)
        try:
            db.execute("CREATE TABLE "+self.name+" (latest int)")
            db.execute("INSERT INTO "+self.name+" (latest) VALUES (0)")
        except db.ProgrammingError: pass
        self.versions.sort(key=lambda pair: pair[0])
        version = db.execute("SELECT latest FROM "+self.name)
        if version:
            version = version[0][0]
        else:
            version = 0

        if self.after:
            after = db.execute('SELECT latest FROM'+self.after)
            if after:
                after = after[0][0]
            else:
                after = 0
        else:
            after = 0

        for testversion,setup in self.versions:
            #print(testversion,'>',version)
            if testversion > version:
                version = testversion
                setup()
                db.execute("UPDATE "+self.name+" SET latest = $1",(version,))

    def __call__(self,version=0):
        def decorator(go):
            self.versions.append((version,go))
        return decorator


import re

from django import forms
from django.contrib import admin
from django.contrib.flatpages.admin import FlatPageAdmin
from django.contrib.flatpages.models import FlatPage
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
from django.db.models import Count, Sum
from django.db.models import F
from django.utils.html import mark_safe
from django.urls import reverse

from filebrowser.settings import ADMIN_VERSIONS, VERSIONS
from letters.admin import LetterInline
from payment.admin import CommissionInline, InvoiceInline
from republisher.admin import RepublisherInline
from socialmedia.admin import TweetInline
from socialmedia.common import SCHEDULE_RESULTS

from . import models, utils

# Used to select sizes of images
IMAGE_SIZE_CHOICES = [(item, VERSIONS[item]['verbose_name'],)
                      for item in ADMIN_VERSIONS]
IMAGE_SIZE_CHOICES.append(('LEAVE', 'LEAVE',))

# Regular expression to replace TinyMCE's pesky insertion of width
# and height attributes into images.

blankpara_regex = re.compile(r'
]*?>\s*?
|
]*?>\s*? \s*?
')

img_regex = re.compile(r'()')

figure_regex = re.compile(r'(
)(.*?)()(.*?)(
)(.*?)\r\n(
(.*?)(
)')

class CorrectionInline(admin.StackedInline):
    model = models.Correction
    extra = 0

class ArticleForm(forms.ModelForm):
    summary_image_size = forms.ChoiceField(choices=IMAGE_SIZE_CHOICES,
                                           initial="medium")
    # primary_image_size = forms.ChoiceField(choices=IMAGE_SIZE_CHOICES,
    #                                       initial="extra_large")

    '''Remove height and width from TinyMCE image insertions.
    '''

    def clean_main_topic(self):
        if self.cleaned_data["main_topic"] == "(None)":
            self.cleaned_data["main_topic"] = None
        return self.cleaned_data["main_topic"]

    def clean(self, *args, **kwargs):

        if self.instance.pk:
            if self.instance.version > self.cleaned_data["version"]:
                raise ValidationError(utils.get_edit_lock_msg(
                    self.instance.user))

        if self.cleaned_data["main_topic"]:
            self.cleaned_data["topics"] = self.cleaned_data["topics"] | \
                    models.Topic.objects.filter(
                        name=self.cleaned_data["main_topic"])

        # Transform the body to fix Wysiwyg editor limitations

        if self.cleaned_data["use_editor"]:
            body = self.cleaned_data["body"]
            self.cleaned_data["body"] = utils.replaceBadHtmlWithGood(body)

        super(ArticleForm, self).clean(*args, **kwargs)

class ArticleAdmin(admin.ModelAdmin):
    form = ArticleForm
    list_display = ('new_edit', 'old_edit', 'created',
                    'modified', 'published',
                    'is_published', 'cached_byline_no_links',
                    'category', )
    prepopulated_fields = {"slug": ("title", )}
    search_fields = ['title', 'cached_byline_no_links', ]
    date_hierarchy = 'modified'
    ordering = ['-modified', ]
    list_filter = ['published', 'category', 'region', 'topics']
    raw_id_fields = ('author_01', 'author_02', 'author_03',
                     'author_04', 'author_05',
                     'topics', 'main_topic', )
    autocomplete_lookup_fields = {
        'fk': ['author_01', 'author_02', 'author_03',
               'author_04', 'author_05', 'main_topic', ],
        'm2m': ['topics', ]
    }

    readonly_fields = ('cached_byline_no_links',
                       'cached_summary_text',
                       'user', 'modified', )

    fieldsets = (
        ('Identifying Information', {
            'classes': ('wide',),
            'fields': ('title', 'subtitle',
                       'cached_byline_no_links',
                       'author_01',)
        }),
        ('Additional authors', {
            'classes': ('wide grp-collapse grp-closed',),
            'fields': ('author_02', 'author_03', 'author_04',
                       'author_05',
                       ('byline', 'byline_style', ),
                       'editor_feedback')
        }),
        ('Content', {
            'classes': ('wide',),
            'fields': ('body', )
        }),
        ('Publish', {
            'fields': ('category', 'topics', 'main_topic',
                       'region', ('recommended',  'undistracted_layout', ),
                       'slug', 'published', ),
        }),
        ('Summary Image and text', {
            'classes': ('grp-collapse grp-closed',),
            'fields': (
                'summary_image', 'summary_image_size',
                'summary_image_alt', 'cached_summary_text',
                'summary_text', 'summary_template',),
        }),
        ('Advanced', {
            'classes': ('grp-collapse grp-closed',),
            'fields': ('copyright', 'include_in_rss',
                       ('letters_on', 'comments_on', 'collapse_comments', ),
                       'stickiness', 'exclude_from_list_views',
                       'use_editor',
                       ('template', 'template_process', ),
                       'additional_head_scripts', 'additional_body_scripts',
                       'activate_slideshow',
                       ('last_tweeted', 'notified_authors',),
                       ('author_payment', 'override_commissions_system',
                        'commissions_processed',),
                       ('suppress_ads', 'promote_article',
                        'encourage_republish',),
                       ('user', 'modified', 'version'),
                       ('secret_link', 'secret_link_view',))
        })
    )

    inlines = [
        TweetInline, RepublisherInline, CorrectionInline,
        LetterInline, # CommissionInline,
    ]

    @admin.display(description='new_edit')
    def new_edit(self, obj):
        return mark_safe('%s' %
                         (obj.get_absolute_url(),
                          obj.title))
    new_edit.allow_tags = True
    new_edit.short_description = "New editor"

    @admin.display(description='old_edit')
    def old_edit(self, obj):
        return mark_safe(
            '%s' %
            (reverse('admin:newsroom_article_change',
                     args=[obj.pk]),
            'Old edit'))
    old_edit.allow_tags = True
    old_edit.short_description = "Old editor"

    def __init__(self,*args,**kwargs):
        super().__init__(*args, **kwargs)
        # self.list_display_links = (None, )

    def changelist_view(self, request, extra_context=None):
        extra_context = extra_context or {}
        return super(ArticleAdmin, self).\
            changelist_view(request, extra_context=extra_context)

    def save_model(self, request, obj, form, change):
        obj.user = request.user
        obj.save()

    class Media:
        css = {'all': ('/static/newsroom/css/admin_enhance.css', )}
        js = [
            '//cdn.ckeditor.com/4.14.0/standard-all/ckeditor.js',
            '/static/newsroom/js/ck_styles.js?v=20220203',
            '/static/newsroom/js/ck_init_admin.js?v=20220203',
            '/static/newsroom/js/statistics.js?v=20220203',
            '/static/newsroom/js/admin_enhance.js?v=20220203',
            '/static/socialmedia/js/tweets.js?v=20220203',
        ]

class CategoryAdmin(admin.ModelAdmin):
    prepopulated_fields = {"slug": ("name", )}

class RegionAdmin(admin.ModelAdmin):
    prepopulated_fields = {"slug": ("name", )}

class TopicAdmin(admin.ModelAdmin):
    search_fields = ['name', 'slug', ]
    list_display = ('name', 'num_articles', 'num_qanda' )
    prepopulated_fields = {"slug": ("name", )}

    def get_queryset(self, request):
        queryset = super().get_queryset(request)
        queryset = queryset.annotate(
            num_articles=Count('article', distinct=True),
            num_qanda=Count('qanda', distinct=True)
        )
        return queryset

    def num_articles(self, obj):
        return obj.num_articles

    num_articles.admin_order_field = 'num_articles'

    def num_qanda(self, obj):
        return obj.num_qanda

    num_qanda.admin_order_field = 'num_qanda'

    def total(self, obj):
        return obj.total

    total.admin_order_field = 'total'

admin.site.register(models.Article, ArticleAdmin)
admin.site.register(models.UserEdit)
admin.site.register(models.Category, CategoryAdmin)
admin.site.register(models.Region, RegionAdmin)
admin.site.register(models.Topic, TopicAdmin)

class AuthorForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(AuthorForm, self).__init__(*args, **kwargs)
        self.fields['email'].required = True

class AuthorAdmin(admin.ModelAdmin):
    form = AuthorForm
    list_display = ('last_name', 'first_names', 'created',
                    'email', 'freelancer', 'level', )
    list_editable = ('email', 'freelancer','level', )
    search_fields = ['last_name', 'first_names', ]
    # inlines = [
    #    InvoiceInline,
    # ]
    raw_id_fields = ('user', )
    autocomplete_lookup_fields = {
        'fk': ['user',],
    }

class CorrectionAdmin(admin.ModelAdmin):
    list_display = ('article', 'update_type', 'created', 'modified',)
    list_editable = ('update_type', )
    list_filter = ['update_type', ]
    ordering = ['-modified', ]
    search_fields = ['text', 'article__title', ]
    raw_id_fields = ('article',)
    autocomplete_lookup_fields = {
        'fk': ['article',],
    }

class WetellAdmin(admin.ModelAdmin):
    list_display = ['pk', 'service', 'published',
                    'created', 'modified']
    ordering = ['-modified']
    search_fields = ['data']

admin.site.register(models.Author, AuthorAdmin)
admin.site.register(models.MostPopular)
admin.site.register(models.Correction, CorrectionAdmin)
admin.site.register(models.WetellBulletin, WetellAdmin)

# Define a new FlatPageAdmin
class FlatPageAdmin(FlatPageAdmin):
    fieldsets = (
        (None, {'fields': ('url', 'title', 'content', 'sites')}),
        (_('Advanced options'), {
            'classes': ('collapse', ),
            'fields': (
                'registration_required',
                'template_name',
            ),
        }),
    )

    class Media:
        css = {'all': ('/static/newsroom/css/admin_enhance.css', )}
        js = [
            '//cdn.ckeditor.com/4.14.0/standard-all/ckeditor.js',
            '/static/newsroom/js/ck_styles.js',
            '/static/newsroom/js/ck_init_admin.js',
        ]

# Re-register FlatPageAdmin
admin.site.unregister(FlatPage)
admin.site.register(FlatPage, FlatPageAdmin)