import torch
from torch import nn

class Conv2d(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size, stride, has_relu=True):
        super().__init__()

        self.net = nn.Sequential(nn.ReflectionPad2d(kernel_size//2),
                                 nn.Conv2d(in_channels, out_channels, kernel_size, stride),
                                 nn.InstanceNorm2d(out_channels, affine=True))

        self.relu = nn.ReLU() if has_relu else None

    def forward(self, x):
        x = self.net(x)

        if self.relu:
            x = self.relu(x)

        return x

class Residual(nn.Module):
    def __init__(self, in_channels, out_channels):
        super().__init__()

        i = in_channels
        o = out_channels

        self.net = nn.Sequential(nn.Conv2d(i, o, 3, 1, 1),
                                 nn.InstanceNorm2d(o, affine=True),
                                 nn.ReLU(),
                                 nn.Conv2d(o, o, 3, 1, 1),
                                 nn.InstanceNorm2d(o, affine=True))

    def forward(self, x):
        return self.net(x) + x

class Deconv2d(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size, scale_factor, has_relu=True):
        super().__init__()

        self.net = nn.Sequential(nn.Upsample(scale_factor=scale_factor),
                                 nn.ReflectionPad2d(kernel_size // 2),
                                 nn.Conv2d(in_channels, out_channels, kernel_size),
                                 nn.InstanceNorm2d(out_channels, affine=True))

        self.relu = nn.ReLU() if has_relu else None

    def forward(self, x):
        x = self.net(x)

        if self.relu:
            x = self.relu(x)

        return x

# https://cs.stanford.edu/people/jcjohns/papers/fast-style/fast-style-supp.pdf
class StyleTransfer(nn.Module):
    name = 'style_transfer'

    def __init__(self):
        super().__init__()

        # to fit output in range(0, 1) Sigmoid is used instead of Tanh
        self.net = nn.Sequential(Conv2d(3, 32, 9, 1),
                                 Conv2d(32, 64, 3, 2),
                                 Conv2d(64, 128, 3, 2),

                                 Residual(128, 128),
                                 Residual(128, 128),
                                 Residual(128, 128),
                                 Residual(128, 128),
                                 Residual(128, 128),

                                 Deconv2d(128, 64, 3, 2.),
                                 Deconv2d(64, 32, 3, 2.),
                                 Conv2d(32, 3, 9, 1, False),

                                 nn.Sigmoid())

    def forward(self, x):
        return self.net(x)


from flask import Flask, render_template, request, jsonify  # เพิ่ม jsonify
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing import image
import numpy as np
import cv2

app = Flask(__name__)

@app.route('/')
def home():
   return render_template('index.html')

@app.route('/about')
def about():
   return render_template('about.html')

# Load the pomelo detection model
model = load_model('pomelo.h5', compile=True)

# Define a function to preprocess the image
def preprocess_image(image_path):
    img = image.load_img(image_path, target_size=(224, 224))  # Resize to (224, 224)
    img = image.img_to_array(img)
    img = img / 255.0
    img = np.expand_dims(img, axis=0)
    return img

# Define a function to predict emotion
def predict_emotion(image_path):
    img = preprocess_image(image_path)
    result = model.predict(img)
    emotion_labels = ['Good','Normal','Bad']
    emotion = emotion_labels[np.argmax(result)]
    return emotion

@app.route('/detect_org', methods=['POST'])
def detect_org():
    if 'image' in request.files:
        uploaded_image = request.files['image']
        if uploaded_image.filename != '':
            image_path = 'static/uploaded_image.png'
            uploaded_image.save(image_path)
            emotion = predict_emotion(image_path)

            if emotion == "Good":
                return render_template('good.html', image=image_path)
            elif emotion == "Normal":
                return render_template('normal.html', image=image_path)
            elif emotion == "Bad":
                 return render_template('bad.html', image=image_path)
            else:
                # หากไม่ใช่  ให้กลับไปที่หน้าหลัก
                return render_template('index.html', result=emotion, image=image_path)
    return render_template('index.html')

if __name__ == '__main__':
   app.run(host="0.0.0.0", port=5000, debug=True)


from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

from .models import PVPGameStats, PVCGameStats
from user_profile.models import User
from .serializers import PVPGameStatsSerializer, PVCGameStatsSerializer

GAME_REWARD_POINTS_AMOUNT = 1
GAME_PENALTY_POINTS_AMOUNT = -1
GAME_TIE_POINTS_AMOUNT = 0

class PVPGameStatsView(APIView):

    def post(self, request, *args, **kwargs):
        winner_wallet_address = request.data.get('winner_wallet_address')
        loser_wallet_address = request.data.get('loser_wallet_address')

        winner = User.objects.get(wallet_address=winner_wallet_address)
        loser = User.objects.get(wallet_address=loser_wallet_address)

        winner.add_points(GAME_REWARD_POINTS_AMOUNT)
        loser.add_points(GAME_PENALTY_POINTS_AMOUNT)

        winner.save()
        loser.save()

        game_stats = PVPGameStats.objects.create()
        game_stats.winner.add(winner)
        game_stats.loser.add(loser)

        serializer = PVPGameStatsSerializer(game_stats)

        return Response(serializer.data, status=status.HTTP_201_CREATED)

class PVCGameStatsView(APIView):

    def post(self, request, *args, **kwargs):
        player_wallet_address = request.data.get('player_wallet_address')
        is_winner = request.data.get('is_winner')

        player = User.objects.get(wallet_address=player_wallet_address)

        if is_winner == 'True':
            player.add_points(GAME_REWARD_POINTS_AMOUNT)
        elif is_winner == 'False':
            player.add_points(GAME_PENALTY_POINTS_AMOUNT)
        else:
            player.add_points(GAME_TIE_POINTS_AMOUNT)

        player.save()

        game_stats = PVCGameStats.objects.create(is_winner=is_winner)
        game_stats.player.add(player)

        serializer = PVCGameStatsSerializer(game_stats)

        return Response(serializer.data, status=status.HTTP_201_CREATED)


# # Implementing CLSM

# ## Purpose
# The purpose of this notebook is to implement Microsoft's [Convolutional Latent Semantic Model](http://www.iro.umontreal.ca/~lisa/pointeurs/ir0895-he-2.pdf) on our dataset.
#
# ## Inputs
# - This notebook requires *wiki-pages* from the FEVER dataset as an input.

# ## Preprocessing Data

import pickle
from multiprocessing import cpu_count
import os

import joblib
import nltk
import time
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision.datasets as dsets
import torchvision.transforms as transforms
from joblib import Parallel, delayed
from logger import Logger
from hyperdash import Experiment, monitor
from scipy import sparse
from sys import argv
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
from sklearn.metrics import classification_report, accuracy_score
from torch.autograd import Variable
from torch.utils.data import DataLoader
from tqdm import tqdm, tqdm_notebook

import cdssm
import pytorch_data_loader
import argparse
import utils

torch.backends.cudnn.benchmark=True
nltk.data.path.append('/usr/users/mnadeem/nltk_data/')

def parse_args():
    parser = argparse.ArgumentParser(description='Learning the optimal convolution for network.')
    parser.add_argument("--batch-size", type=int, help="Number of queries per batch.", default=1)
    parser.add_argument("--data-sampling", type=int, help="Number of examples per query.", default=8)
    parser.add_argument("--learning-rate", type=float, help="Learning rate for model.", default=1e-3)
    parser.add_argument("--epochs", type=int, help="Number of epochs to learn for.", default=3)
    parser.add_argument("--data", help="Training dataset to load file from.", default="shared_task_dev.pkl")
    parser.add_argument("--model", help="Model to evaluate.")
    parser.add_argument("--sparse-evidences", default=False, action="store_true")
    return parser.parse_args()

@monitor("CLSM Test")
def run():
    BATCH_SIZE = args.batch_size
    LEARNING_RATE = args.learning_rate
    DATA_SAMPLING = args.data_sampling
    NUM_EPOCHS = args.epochs
    MODEL = args.model

    use_cuda = torch.cuda.is_available()
    device = torch.device("cuda" if use_cuda else "cpu")

    logger = Logger('./logs/{}'.format(time.localtime()))

    print("Created model...")
    model = cdssm.CDSSM()
    model = model.cuda()
    model = model.to(device)
    if torch.cuda.device_count() > 0:
      print("Let's use", torch.cuda.device_count(), "GPU(s)!")
      model = nn.DataParallel(model)
    model.load_state_dict(torch.load(MODEL))

    print("Created dataset...")
    dataset = pytorch_data_loader.WikiDataset(test, claims_dict, data_sampling=DATA_SAMPLING, testFile="shared_task_dev.jsonl")
    dataloader = DataLoader(dataset, batch_size=BATCH_SIZE, num_workers=3, shuffle=True, collate_fn=pytorch_data_loader.PadCollate())

    OUTPUT_FREQ = int((len(dataset)/BATCH_SIZE)*0.02)
    criterion = torch.nn.BCEWithLogitsLoss()

    parameters = {"batch size": BATCH_SIZE, "loss": criterion.__class__.__name__, "data batch size": DATA_SAMPLING, "data": args.data}
    exp_params = {}
    exp = Experiment("CLSM V2")
    for key, value in parameters.items():
       exp_params[key] = exp.param(key, value)

    true = []
    pred = []
    print("Evaluating...")
    model.eval()
    test_running_accuracy = 0.0
    test_running_loss = 0.0
    num_batches = 0
    for batch_num, inputs in enumerate(dataloader):
        num_batches += 1
        claims_tensors, claims_text, evidences_tensors, evidences_text, labels = inputs

        y_pred = model(claims, evidences)

        y = (labels).float()
        y_pred = y_pred.squeeze()
        y = y.squeeze()
        y = y.view(-1)
        y_pred = y_pred.view(-1)
        bin_acc = torch.sigmoid(y_pred).round()

        loss = criterion(y_pred, y)

        true.extend(y.tolist())
        pred.extend(bin_acc.tolist())

        accuracy = (y==bin_acc).float().mean()
        test_running_accuracy += accuracy.item()
        test_running_loss += loss.item()

        if batch_num % OUTPUT_FREQ==0 and batch_num>0:
            print("[{}]: {}".format(batch_num, test_running_accuracy / OUTPUT_FREQ))

            # 1. Log scalar values (scalar summary)
            info = { 'test_loss': test_running_loss/OUTPUT_FREQ, 'test_accuracy': test_running_accuracy/OUTPUT_FREQ }

            for tag, value in info.items():
                exp.metric(tag, value, log=False)
                # logger.scalar_summary(tag, value, batch_num+1)

            # 2. Log values and gradients of the parameters (histogram summary)
            for tag, value in model.named_parameters():
                tag = tag.replace('.', '/')
                # logger.histo_summary(tag, value.data.cpu().numpy(), batch_num+1)

            test_running_loss = 0.0
            test_running_accuracy = 0.0

    print(true[0], pred[0])
    true = np.array(true).astype("int")
    pred = np.array(pred).astype("int")
    final_accuracy = accuracy_score(true, pred)
    print("Final accuracy: {}".format(final_accuracy))
    print(classification_report(true, pred))
    filename = "predicted_labels"
    for key, value in parameters.items():
        filename += "_{}-{}".format(key.replace(" ", "_"), value)

    joblib.dump({"true": true, "pred": pred}, filename)

if __name__=="__main__":
    args = parse_args()

    print("Loading {}".format(args.data))
    test = joblib.load(args.data)

    try:
        claims_dict
    except:
        print("Loading validation claims data...")
        claims_dict = joblib.load("claims_dict.pkl")

    torch.multiprocessing.set_start_method("spawn", force=True)
    run()


from aocd import lines
from day1 import delimit
from itertools import zip_longest, chain
import functools
from math import prod

def parse(lines):
    return [(eval(left), eval(right)) for left, right in delimit(lines)]

def compare(left, right, level=0, p=False):
    if left == right:
        return 0

    def _compare(left, right, level=0, p=False):
        if p:
            print(f"{'  ' * level}- Compare {left} vs {right}")
        if left is None:
            return (True, True)
        elif right is None:
            return (False, False)
        elif type(left) == int and type(right) == int:
            return (right is not None and left <= right, left < right)
        elif type(left) == list and type(right) == list:
            for l, r in zip_longest(left, right):
                correct, short_circuit = _compare(l, r, level=level + 1, p=p)
                if correct and short_circuit:
                    return (True, True)
                if not correct:
                    return (False, False)
            return (True, False)
        elif type(left) == int and type(right) == list:
            if p:
                print(
                    f"{'  ' * level}- Mixed types; convert {left} to list and try again"
                )
            return _compare([left], right, level=level, p=p)
        elif type(left) == list and type(right) == int:
            if p:
                print(
                    f"{'  ' * level}- Mixed types; convert {right} to list and try again"
                )
            return _compare(left, [right], level=level, p=p)
        else:
            return (False, False)

    return 1 if _compare(left, right, level=level, p=p)[0] else -1

def part_1(groups, p=False):
    solution = 0
    for i, group in enumerate(groups):
        if p:
            print(f"== Pair {i+1} ==")
        result = compare(*group, p=p)
        if p:
            print(result)
        solution += i + 1 if result == 1 else 0
    return solution

def part_2(groups):
    decoder_packets = [[[2]], [[6]]]
    packets = list(chain(*groups)) + decoder_packets
    packets.sort(key=functools.cmp_to_key(compare), reverse=True)
    return prod(
        [i + 1 for i, packet in enumerate(packets) if packet in decoder_packets]
    )

def main():
    groups = parse(lines)
    p = False
    print("Part 1:", part_1(groups, p=p))
    print("Part 2:", part_2(groups))

if __name__ == "__main__":
    main()


'''
Name: Prithvi Raj Singh
Assignment 3: Linear Regression problem Part2.
Printing the optimal weight of 3 variable datas using formula7 .
**Note: Please use the attached .csv file (twoVarBPdata.csv) for the program to produce desired output.
This produces the 3d plot of the given data which is optional and not optimized.
The data given by Dr. Maida was slightly reformatted for the program to read all the rows and columns of the data
'''

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from mpl_toolkits import mplot3d

data_frame = pd.read_csv("twoVarBPdata.csv", skiprows=None)
data_frame.head()
data_frame.tail()
data_set2 = data_frame.values
data_set2 = np.insert(data_set2, 1, 1, axis=1)

x = data_set2[0:17, 1:4]
print("\nThe value of x is the collection of matrix of Age and Weight. It is used for optimal value calculation")
print(x)
y = data_set2[:, 4]
print("\n This will print out y, the matrix value of SBP")
print(y)
x_transpose = np.transpose(x)
W = np.matmul(np.matmul(np.linalg.inv(np.matmul(x_transpose,x)), x_transpose), y)
print("The optimal weight is:\n", W)

'''
The below code for the plotting is optional for this part of assignment3. Dr. Maida asked us to just print out the optimal
weight for this.
'''
fig = plt.figure()
ax= plt.axes(projection='3d')
zline = np.linspace(30,120,100)
xline = np.linspace(20,80,100)
yline = W[1]*xline + W[0]+W[2]*zline
ax.plot3D(xline, yline, zline, 'red')
ax.plot(xline,yline,zline, 'red')


from typing import Optional

from sqlalchemy.orm import Session

from app import crud, models, schemas
from app.tests.utils.design import create_random_design
from app.tests.utils.user import create_random_user
from app.tests.utils.utils import random_float, random_integer, random_lower_string

def create_random_synth(
    db: Session, *, owner_id: Optional[int] = None, design_id: Optional[int] = None
) -> models.Synth:
    if owner_id is None:
        user = create_random_user(db)
        owner_id = user.id
    if design_id is None:
        design = create_random_design(db, owner_id=owner_id)
        design_id = design.id
    j5_synth_id = random_integer()
    name = random_lower_string()
    length = random_integer()
    cost = random_float()
    sequence = random_lower_string()
    synth_in = schemas.SynthCreate(
        j5_synth_id=j5_synth_id,
        name=name,
        length=length,
        cost=cost,
        sequence=sequence,
    )
    return crud.synth.create(
        db=db,
        obj_in=synth_in,
        owner_id=owner_id,
        design_id=design_id,
    )


from PIL import Image
from pyboy import PyBoy, WindowEvent
import schedule
from argparse import ArgumentParser
from io import BytesIO
import time
from typing import List
import twitter_plays_pyboy
import tpp_twitter as twitter

parser = ArgumentParser(
    prog="Twitter Plays Game Boy",
    description="A clone of Constantin Liétard's 'Twitter Plays Pokémon' (https://nitter.net/screenshakes/status/1347589296593788933). Powered by PyBoy (https://github.com/Baekalfen/PyBoy)."
)
parser.add_argument('filename', help="Location of ROM.")
parser.add_argument('-g', '--game', help="Game class used. If you're unsure what to use, pick `BaseGame`.", default="BaseGame", choices=twitter_plays_pyboy.games.__all__)
parser.add_argument('-V', '--version', action='version', version='%(prog)s ' + twitter_plays_pyboy.__version__)

args = parser.parse_args()

engine = getattr(twitter_plays_pyboy.games, args.game)

# Initialize emulator
emu = PyBoy(args.filename, window_type="headless", debug=False, game_wrapper=True)
emu.set_emulation_speed(0)

game = engine(emu)

def job():
    for status in twitter.get_replies_from_latest():
        button = status.text.split(" | ", 1)[0]
        inputs = twitter_plays_pyboy.constants.BUTTON_INPUTS.get(button, [])
        if not inputs:
            continue
        press, release = inputs
        game.input(press, release)
    else:
        inputs = twitter_plays_pyboy.constants.BUTTON_INPUTS['pass']
        press, release = inputs
        game.input(press, release)

    with game.screenshot() as screenshot:
        screenshot_bin = BytesIO()
        screenshot.save(screenshot_bin, "JPEG")

    twitter.update(screenshot_bin, BytesIO(screenshot_bin.getvalue()), text="", bio=game.bio())

schedule.every(30).seconds.do(job)

while True:
    try:
        schedule.run_pending()
        time.sleep(1)
    except KeyboardInterrupt:
        game.emu.stop()
        exit(0)


import keras
import tensorflow as tf
from model import Deeplabv3

class Deeplabv3Model(keras.Model):
    def __init__(self):
        super(Deeplabv3Model, self).__init__()
        # self.input_shape = (1, 512, 512, 3)
        # self.input_l = Input(batch_shape=(BATCH_SIZE, 224, 224, 3))  # let us say this new InputLayer
        self.base_model = Deeplabv3()

    def call(self, inputs):
        # print("inputs", inputs)
        img_final = tf.cast(inputs, tf.float32) / 127.5

        inputs = img_final - 1.
        # inputs.resize((512, 512, 3))

        ## ConcateLayer
        return self.base_model(inputs)


#import the libraries
import warnings
warnings.filterwarnings('ignore')
import numpy as np
import pandas as pd

#load data
advertising = pd.read_csv("advertising.csv")
advertising.head()

#print shape
advertising.shape

#print the dataset information
advertising.info()

#describe the dataset
advertising.describe()

#Visualizing the data
import matplotlib.pyplot as plt
import seaborn as sns

#pair plot
sns.pairplot(advertising, x_vars=['TV', 'Newspaper', 'Radio'], y_vars='Sales', size=4, aspect=1, kind='scatter')
plt.show()

#correlation heatmap
sns.heatmap(advertising.corr(), cmap='YlGnBu', annot=True)
plt.show()

#Performing Simple Linear Regression
X = advertising['TV']
y = advertising['Sales']

#split the data
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size = 0.7, test_size = 0.3, random_state = 100)

#check the train data
X_train.head()
y_train.head()

#Build a Linear Model
import statsmodels.api as sm

X_train_sm = sm.add_constant(X_train)
lr = sm.OLS(y_train, X_train_sm).fit()
lr.params

#print the linear regression summary
print(lr.summary())

#visualize the fitted line
plt.scatter(X_train, y_train)
plt.plot(X_train, 6.948 + 0.054*X_train, 'r')
plt.show()

#Residual analysis
y_train_pred = lr.predict(X_train_sm)
res = (y_train - y_train_pred)

fig = plt.figure()
sns.distplot(res, bins = 15)
fig.suptitle('Error Terms', fontsize = 15)                  # Plot heading
plt.xlabel('y_train - y_train_pred', fontsize = 15)         # X-label
plt.show()

#check the residual plots
plt.scatter(X_train,res)

#Prediction on Test Set
# Add a constant to X_test
X_test_sm = sm.add_constant(X_test)

# Predict the y values corresponding to X_test_sm
y_pred = lr.predict(X_test_sm)
y_pred.head()

#Check the fitness metrics
from sklearn.metrics import mean_squared_error
from sklearn.metrics import r2_score

#Returns the mean squared error; we'll take a square root
np.sqrt(mean_squared_error(y_test, y_pred))
r_squared = r2_score(y_test, y_pred)
r_squared

plt.scatter(X_test, y_test)
plt.plot(X_test, 6.948 + 0.054 * X_test, 'r')
plt.show()

from sklearn.model_selection import train_test_split
X_train_lm, X_test_lm, y_train_lm, y_test_lm = train_test_split(X, y, train_size = 0.7, test_size = 0.3, random_state = 100)
X_train_lm.shape

print(X_train.head())
print(X_train_lm[:5,])

X_train_lm = X_train_lm.reshape(-1,1)
X_test_lm = X_test_lm.reshape(-1,1)

print(X_train_lm[:5,])

print(X_train_lm.shape)
print(y_train_lm.shape)
print(X_test_lm.shape)
print(y_test_lm.shape)

from sklearn.linear_model import LinearRegression

# Representing LinearRegression as lr(Creating LinearRegression Object)
lm = LinearRegression()

# Fit the model using lr.fit()
lm.fit(X_train_lm, y_train_lm)

print(lm.intercept_)
print(lm.coef_)

corrs = np.corrcoef(X_train, y_train)
print(corrs)

corrs[0,1] ** 2

############ Scaling the variables ##############
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size = 0.7, test_size = 0.3, random_state = 100)

from sklearn.preprocessing import StandardScaler, MinMaxScaler

# One aspect that you need to take care of is that the 'fit_transform' can be performed on 2D arrays only. So you need to
# reshape your 'X_train_scaled' and 'y_trained_scaled' data in order to perform the standardisation.
X_train_scaled = X_train.reshape(-1,1)
y_train_scaled = y_train.reshape(-1,1)

X_train_scaled.shape

# Create a scaler object using StandardScaler()
scaler = StandardScaler()
#'Fit' and transform the train set; and transform using the fit on the test set later
X_train_scaled = scaler.fit_transform(X_train_scaled)
y_train_scaled = scaler.fit_transform(y_train_scaled)

print("mean and sd for X_train_scaled:", np.mean(X_train_scaled), np.std(X_train_scaled))
print("mean and sd for y_train_scaled:", np.mean(y_train_scaled), np.std(y_train_scaled))

# Let's fit the regression line following exactly the same steps as done before
X_train_scaled = sm.add_constant(X_train_scaled)

lr_scaled = sm.OLS(y_train_scaled, X_train_scaled).fit()

# Check the parameters
lr_scaled.params

print(lr_scaled.summary())


import cv2

# Loading Image
image = cv2.imread('lena.jpg')
# Converting Image to Blurry Image(always use odd numbers in second () of Gaussian Blur)
image_blur1 = cv2.GaussianBlur(image, (9, 9), 0)
image_blur2 = cv2.GaussianBlur(image, (1, 23), 0)
image_blur3 = cv2.GaussianBlur(image, (23, 1), 0)
# Displaying Original and Blurred Image
cv2.imshow('Original Coloured Image', image)
cv2.imshow('Blurred Image1', image_blur1)
cv2.imshow('Blurred Image2', image_blur2)
cv2.imshow('Blurred Image3', image_blur3)
cv2.waitKey(0)


import os
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
# from email import MIMEImage
from email.mime.base import MIMEBase
from email.mime.application import MIMEApplication
# from email import Encoders

def mail(to,attach):
    # allow either one recipient as string, or multiple as list
    if not isinstance(to,list):
        to = [to]
    # allow either one attachment as string, or multiple as list
    if not isinstance(attach,list):
        attach = [attach]

    gmail_user='*****@aristopharma.com'
    gmail_pwd = "*********"
    msg = MIMEMultipart()
    msg['From'] = gmail_user
    msg['To'] = ", ".join(to)
    msg['Subject'] = "Hi mozur vai ! any attachment there "
    body_text="Mail automation for target sheets"
    msg.attach(MIMEText(body_text,'plain'))

    #get all the attachments
    for file in attach:
        with open(file, "rb") as f:
            #attach = email.mime.application.MIMEApplication(f.read(),_subtype="pdf")
            part = MIMEApplication(f.read(),_subtype="pdf")

        # part = MIMEBase('application', 'octet-stream')
        # part.set_payload(open(file, 'rb').read())
        # Encoders.encode_base64(part)
            part.add_header('Content-Disposition', 'attachment; filename= %s' % file)
            msg.attach(part)

    mailServer = smtplib.SMTP("smtp.aristopharma.com", 587)
    # mailServer.ehlo()
    mailServer.starttls()
    # mailServer.ehlo()
    mailServer.login(gmail_user, gmail_pwd)
    text = msg.as_string().encode('ascii', 'ignore')

    mailServer.sendmail(gmail_user, to, text)
    # Should be mailServer.quit(), but that crashes...
    mailServer.close()

# dicm={1310:'monzur.it@aristopharma.com',1311:'almamun.it@aristopharma.com'}

# # M=['monzur.it@aristopharma.com','almamun.it@aristopharma.com']
dicm={
1310:'***@aristopharma.com',

}

dir = input("Enter attachment Directory : ")
os.chdir(dir)
a = os.listdir()
arr=[]

for x in dicm.keys():
    for y in a:
        print(x)
        name,e = y.split('.')
        print(name[:4])
        if x == int(name[:4]):
            arr.append(y)
    if arr:
        mail(dicm[x],arr)
        arr=[]
    else:
        print(str(x)+"-This depot has no file in Directory")

# for x in dicm:

#     a = os.listdir()

#     mail(M,arr)


from django.apps import AppConfig
from watson import search as watson

class MembersConfig(AppConfig):
    name = 'members'

    def ready(self):
        team = self.get_model("Team")
        watson.register(team)
        member = self.get_model("Member")
        watson.register(member)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Oct 23 16:12:28 2020

@author: cuilab
"""

from tridesclous import DataIO
import quantities as pq
import numpy as np
from tqdm import tqdm
from MongoNeo.user_layer.dict_to_neo import templat_neo
from .BaseSorter2Dict import BaseSorter2Dict

def set_spike_segment(dataio_br, Chn, SpikeDict, RecordingParam, dataio_dir):
    #%% align segments spike data
    memmap = dataio_br.get_spikes(chan_grp=Chn,seg_num = 0)
    spike_time = memmap['index'].copy()
    cluster_label = memmap['cluster_label'].copy()
    #print('cluster:',cluster_num)
    cluster_num = list(dataio_br.load_catalogue(chan_grp=Chn)['cluster_labels'])
    processed_signals = dataio_br.arrays[Chn][0].get('processed_signals')

    #%% set spiketrains list
    for clu in cluster_num:
        unit = {'spk':{}}
        unit['spk'] = templat_neo['spk'].copy()

        spike_index = spike_time[cluster_label==clu]
        if len(spike_index)==0:
            continue
        Select = (spike_index<(len(processed_signals)-32)) * (spike_index>16)
        spike_index = spike_index[Select]

        cluster_spike_times = (spike_index/dataio_br.sample_rate)*pq.s

        #QuatoIndex = int(processed_signals.shape[0]/4)
        peak_amplitude = processed_signals[spike_index]
        mad = np.median(np.abs(processed_signals-np.median(processed_signals)))
        snr = np.mean(np.abs(peak_amplitude))/(mad*1.4826)
        spike_description = {'Clu':str(clu),
                             'snr':snr,
                             'Chn':Chn,
                             'mean_waveform':np.array([processed_signals[(index-16):(index+32)]\
                                               for index in spike_index]).squeeze().mean(0)}

        if isinstance(RecordingParam,dict):
            spike_description.update(RecordingParam[Chn])

        if str(spike_description['Chn']) not in SpikeDict:
            SpikeDict[str(spike_description['Chn'])] = {}

        if str(spike_description['Clu']) not in SpikeDict[str(spike_description['Chn'])]:
            SpikeDict[str(spike_description['Chn'])][str(spike_description['Clu'])] = {}

        unit['spk']['times'] = cluster_spike_times
        unit['spk']['t_stop'] = cluster_spike_times[-1]
        unit['spk']['sampling_rate'] = dataio_br.sample_rate*pq.Hz
        unit['spk']['t_start'] = 0*cluster_spike_times.units
        unit['spk']['description'] = spike_description
        SpikeDict[str(spike_description['Chn'])][str(spike_description['Clu'])] = unit

    dataio_br.arrays[Chn][0].detach_array('spikes')
    dataio_br.arrays[Chn][0].detach_array('processed_signals')

class tdcSorter2Dict(BaseSorter2Dict):
    def _ParseSorterResults(self, sorter_dir):
        self._dataio_br = DataIO(dirname=sorter_dir)
        self._sorter_dir = sorter_dir

    def _ExtractMeanWaveform(self):
        pass

    @classmethod
    def Sorter2Dict(cls, sorter_dir, wavedict = {},
                    RecordingParam = None,sampling_rate = 30000*pq.Hz,**waveform_args):
        self = cls()
        self._ParseSorterResults(sorter_dir)

        SpikeDict = {}
        SpikeDict['name'] = 'tdc_spike_train'
        dataio_br = DataIO(dirname=sorter_dir)
        for Chn in tqdm(self._dataio_br.channel_groups.keys()):
            set_spike_segment(dataio_br, Chn, SpikeDict, wavedict, RecordingParam, sorter_dir)

        return SpikeDict


import os
import datetime
import math
import pandas as pd
import tkinter as tk
from tkinter import StringVar, IntVar, ttk
from tkinter import filedialog as fd

class GoalSetter(tk.Toplevel):
    def __init__(self, parent, title_set):
        super().__init__(parent)
        self.destroy_ind = 0
        self.title('Задание цели')
        self.label_num=len(title_set)
        self.minsize(200,self.label_num*27)
        label_list=[]
        self.text_list=[]
        textbox_list=[]
        for i in range(self.label_num):
            label_list.append(tk.Label(self, text=str(title_set[i])).pack())
            self.text_list.append(tk.StringVar(self))
            textbox_list.append(ttk.Entry(self,textvariable=self.text_list[i]).pack())
        btn = ttk.Button(self, text="Ок", command=self.values_check)
        btn.pack()
        self.protocol("WM_DELETE_WINDOW", self.handler)

    def handler(self):
        self.destroy_ind = 1
        self.destroy()

    def values_check(self):
        self.destroy_ind = 0
        for i in range(self.label_num):
            if not (('.' in self.text_list[i].get() and self.text_list[i].get().replace('.', '').isdigit())
                    or self.text_list[i].get().isdigit()
                    or self.text_list[i].get() in ['зачет','незачет']):
                tk.messagebox.showinfo(title='Ошибка', message='Проверьте введенные данные')
                return
        self.destroy()

    def open(self):
        self.grab_set()
        self.wait_window()
        goal=[]
        for i in range(self.label_num):
            if '.' in self.text_list[i].get() and self.text_list[i].get().replace('.', '').isdigit():
                goal.append(float(self.text_list[i].get()))
            elif self.text_list[i].get().isdigit():
                goal.append(int(self.text_list[i].get()))
            elif self.text_list[i].get() == '': goal.append(1)
            else: goal.append(0)
        return goal, self.destroy_ind

class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.data = pd.DataFrame()
        self.title('Приложение: Рейтинг успеваемости')
        self.geometry('900x600')
        self.minsize(900,600)
        self.frame_filedialog = tk.Frame(self,width=150,height=30)
        self.frame_view = tk.Frame(self, width=150, height=150)
        self.frame_buttons = tk.Frame(self, width=150, height=30)
        self.frame_filedialog.place(relx=0, rely=0, relwidth=1, relheight=0.08)
        self.frame_view.place(relx=0, rely=0.08, relwidth=1, relheight=0.84)
        self.frame_buttons.place(relx=0, rely=0.92, relwidth=1, relheight=0.08)
        self.open_button = ttk.Button(self.frame_filedialog, text='Открыть файл', command=self.select_file)
        self.text = tk.StringVar(self.frame_filedialog)
        self.open_textbox = ttk.Entry(self.frame_filedialog,textvariable=self.text)
        self.open_textbox.place(relx=0.01, rely=0.2, relwidth=0.6, relheight=0.6)
        self.open_button.place(relx=0.62, rely=0.2, relwidth=0.15, relheight=0.6)
        # место для отображения таблицы с данными
        self.table = ttk.Treeview(self.frame_view, show='headings')
        self.scroll_pane_y =ttk.Scrollbar(self.frame_view, command=self.table.yview)
        self.scroll_pane_x =ttk.Scrollbar(self.frame_view, command=self.table.xview, orient='horizontal')
        self.table.configure(yscrollcommand=self.scroll_pane_y.set, xscrollcommand=self.scroll_pane_x.set)
        self.scroll_pane_y.pack(side=tk.RIGHT, fill=tk.Y)
        self.scroll_pane_x.pack(side=tk.BOTTOM, fill=tk.X)
        self.table.pack(expand=tk.YES, fill=tk.BOTH)
        #конпки сохранения и оценки
        self.no_goal = IntVar()
        self.no_pass = IntVar()
        self.flunk_button = ttk.Checkbutton(self.frame_buttons, text="Учитывать неуспевающих студентов", variable=self.no_pass).place(relx=0.23, rely=0.2,relheight=0.6)
        self.goal_button = ttk.Checkbutton(self.frame_buttons, text="Ввести цель вручную", variable=self.no_goal).place(relx=0.03, rely=0.2,relheight=0.6)
        self.rate_button = ttk.Button(self.frame_buttons,text='Рейтинг',command = self.rate_up)
        self.save_button = ttk.Button(self.frame_buttons, state=tk.DISABLED, text='Сохранить как',command=self.save_file_as)
        self.rate_button.place(relx=0.83, rely=0.2,relwidth=0.15, relheight=0.6)
        self.save_button.place(relx=0.65, rely=0.2,relwidth=0.15, relheight=0.6)

    # проверка имени файла в строке на существование и тип
    def name_check(self, file):
        if os.path.exists(file):
            filename, file_extension = os.path.splitext(file)
            if file_extension in ['.xls', '.xlsx', '.xlsm', '.xlsb']: return False
            else: return True
        else: return True

    # вывод таблицы на форму
    def table_update(self):
        self.table.delete(*self.table.get_children())
        headers=self.data.columns.values.tolist()
        self.table['columns'] = headers
        for header in headers:
            self.table.heading(header, text=header, anchor='center')
            self.table.column(header,anchor='center')
        for row in self.data.values.tolist():
            self.table.insert('', tk.END, values=row)

    # открыть выбранный файл
    def select_file(self):
        if self.text.get() == '' or self.name_check(self.text.get()):
            filetypes = (
                ('Excel Files', '*.xls *.xlsx *.xlsm *.xlsb'),
                ('All Files', '*.*')
            )
            filename = fd.askopenfilename(
                title='Выберите файл',
                initialdir=r'C:\\',
                filetypes=filetypes)
            self.text.set(filename)
        else: filename = self.text.get()

        if filename != '':
            self.save_button.configure(state=tk.DISABLED)
            self.rate_button.configure(state=tk.ACTIVE)
            # загрузка содержимого в датафрейм
            self.data = pd.read_excel(filename,0)
            self.table_update()

    # сохранение файла
    def save_file_as(self):
        filename = fd.asksaveasfilename(
            initialfile ="Рейтинг"+str(datetime.date.today()),
            defaultextension=".xlsx",
            initialdir=r'C:\\')
        with pd.ExcelWriter(filename) as writer:
            self.data.to_excel(writer)

    def target_proximity(self, vector, goal):
        goal
        result1 = result2 = 0
        ab=0
        a2=0
        b2=0
        size=len(goal)
        for i in range(size):
            if vector[i] == 0 and self.no_pass.get() == 0:
                return [0, 0]
            else:
                ab=ab+goal[i]*vector[i]
                a2=a2+math.pow(goal[i],2)
                b2=b2+math.pow(vector[i],2)
        result1=ab/(math.sqrt(a2)*math.sqrt(b2))
        result2=ab*100/a2
        return [result1, result2]

    def rate_up(self):
        # переводим зачет и незачет в числовые эквиваленты
        # временный датафрейм для удобства вычислений
        df=self.data.copy()
        credit_map = {'незачет': 0, 'зачет': 1}
        df=df.replace(credit_map)
        first_column=''

        # заполняем пропущенные значения
        df = df.replace(r'^\s+$', pd.np.nan, regex=True)
        df.fillna(0,inplace=True)

        # проверяем присутствие только числовых значений
        columns = df.columns.tolist()
        types = df.dtypes.tolist()
        try:
            int_pos = types.index('int64')
        except ValueError:
            int_pos=len(columns)
        try:
            float_pos = types.index('float64')
        except ValueError:
            float_pos=len(columns)
        if float_pos>-1 and int_pos<float_pos:
            try:
                types.index('object',int_pos)
                tk.messagebox.showinfo(title='Ошибка', message='Данные предоставлены с ошибками. Проверьте источник информации')
                return
            except ValueError:
                first_column=columns[int_pos]
        elif int_pos>float_pos:
            try:
                types.index('object',float_pos)
                tk.messagebox.showinfo(title='Ошибка', message='Данные предоставлены с ошибками. Проверьте источник информации')
                return
            except ValueError:
                first_column=columns[float_pos]
        else:
            tk.messagebox.showinfo(title='Ошибка', message='Данные предоставлены с ошибками. Проверьте источник информации')
            return

        # проверяем на отрицательные значения и отмечаем неуспевающих студентов
        for name in columns[columns.index(first_column):]:
            if not df[df[name]<0].empty :
                tk.messagebox.showinfo(title='Ошибка', message='В таблице присутствуют отрицательные значения.')
                return
            if self.no_pass.get() == 0 : df.loc[(df[name]==2), name] = 0

        # отделяем цель
        if self.no_goal.get()==0:
            goal = df.loc[0][first_column:].values.tolist()
            self.data=self.data[1:].copy()
            df=df[1:].copy()
        else:
            window= GoalSetter(self, columns[columns.index(first_column):])
            goal, answer = window.open()
            if answer > 0: return

        # применяем формулы к данным
        self.data[['Приближенность к цели','Успешность, %']] = df.apply(lambda x: pd.Series(self.target_proximity(x.loc[first_column:].values.tolist(),goal)), axis =  1)
        # сортировка по убыванию
        self.data = self.data.sort_values(['Успешность, %','Приближенность к цели'],ascending=[False, False]).reset_index(drop=True)
        self.save_button.configure(state=tk.ACTIVE)
        self.rate_button.configure(state=tk.DISABLED)
        self.table_update()

if __name__ == "__main__":
    app = App()
    app.mainloop()


import numpy as np
import matplotlib.pyplot as plt

Fd = ['1.350', '1.440', '1.465', '1.770']
p = []
for f in Fd:
    p.append(np.loadtxt("data_{}000.dat".format(f)))
p_delta = []
for f in Fd:
    p_delta.append(np.loadtxt("data_{}000_delta.dat".format(f)))

#%%

fig1 = plt.figure(figsize=(15,15))
for i in range(4):
    ax = fig1.add_subplot(2,2,i+1)
    ax.plot(p[i][:,0],p[i][:,1], label="Fd={}".format(Fd[i]))
    ax.set_xlabel("$time$")
    ax.set_ylabel(u"$\theta$")
    ax.legend()
plt.savefig("theta_vs_time.png")

#%%

fig2 = plt.figure(figsize=(15,15))
for i in range(4):
    ax = fig2.add_subplot(2,2,i+1)
    ax.scatter(p[i][:,1],p[i][:,2], s=5, label="Fd={}".format(Fd[i]))
    ax.set_xlabel(u"$\theta$")
    ax.set_ylabel("$\omega$")
    ax.legend()
plt.savefig("omega_vs_theta.png")

#%%

fig3 = plt.figure(figsize=(15,15))
for i in range(4):
    ax = fig3.add_subplot(2,2,i+1)
    ax.semilogy(p[i][:,0],np.abs(p_delta[i][:,1] - p[i][:,1]),marker="+", label="Fd={}".format(Fd[i]))
    ax.set_xlabel(u"$time$")
    ax.set_ylabel("$\Delta\Theta$")
    ax.legend()
plt.savefig("lyapunov.png")
#%%

bifurcacion = np.loadtxt("bifurcacion.dat")

#%%

fig4 = plt.figure(figsize=(15,15))
ax = fig4.add_subplot(111)

ax.scatter(bifurcacion[:,0], bifurcacion[:,1], marker=".", s=1)
ax.set_title("Diagrama de Bifurcación")
ax.set_ylim(1,3)

plt.savefig("bifurcacion.png")


#!/usr/bin/python

import csv
import urllib
import urllib2
import json
import StringIO
from StringIO import StringIO
import argparse
import sys
import time
import multiprocessing
from os import listdir
from os.path import isfile, join

reload(sys)
sys.setdefaultencoding('utf-8')

if sys.version_info < (2, 7):
    def __writeheader(self):
        header = dict(zip(self.fieldnames, self.fieldnames))
        self.writerow(header)
        csv.DictWriter.writeheader = __writeheader

def getwriter(header, fname_out, delimiter, writer_cache, file_cache):
#    global writer_cache
#    global file_cache
    if not fname_out in writer_cache:
        output_file = open(fname_out,'w+')
        writer = csv.DictWriter(output_file,fieldnames=header,delimiter=delimiter)
        if sys.version_info < (2, 7):
            __writeheader(writer)
        else:
            writer.writeheader()
        writer_cache[fname_out]=writer
        file_cache[fname_out]=output_file
    return writer_cache[fname_out]

# Choose method
def getmethod(line):
    if 'api_method' in line:
        return line['api_method']
    return 'all'

def argparser():
    parser = argparse.ArgumentParser(description='Specify input and output filenames')
    parser.add_argument('-i', '--input', dest='input_folder', default=None, required=True, help='Full path to input folder to read from')
    parser.add_argument('-o', '--output', dest='output_folder', default=None, required=False, help='Full path to output folder to write to')
    parser.add_argument('-r', '--rejected', dest='rejected_filename', default=None, required=False, help='Full path to rejected filename')
    parser.add_argument('-u', '--url', dest='url', default='http://invhdp01:8080/sax/v1/media/', required=False, help='REST API')
    parser.add_argument('-v', '--verbose', dest='verbose', default=False, action='store_true', required=False)
    parser.add_argument('-d', '--delimiter', dest='delimiter', default='\t', required=False)
    parser.add_argument('-b', '--bad', dest='bad', default=100, required=False, help='Number of bad rows allowed')
    parser.add_argument('-s', '--sample', dest='sample', default=1000, required=False, help='Size of sample for pre-validation')
    parser.add_argument('-p','--numProcessors', required=False, type=int,
    					default=multiprocessing.cpu_count(),
    					help='Number of processors to use. ' + \
    					"Default for this machine is %d" % (multiprocessing.cpu_count(),) )
    args = parser.parse_args()
    return args

def validation(fname, fname_out):
    c = 0
    br = 0
    flag = True
    writer_cache = dict()
    file_cache = dict()
#    DEBUG
#    print(fname)
#    print(fname_out)
#    print(params.delimiter)
    with open(fname,'rb') as f:
        reader = csv.DictReader(f,delimiter=params.delimiter)
        for line in reader:
#            DEBUG
#            print(line)
            if (not line["urlip"]): # and (not line["ua"]):
                br = br+1
                writer = getwriter(reader.fieldnames,fname_out,params.delimiter,writer_cache,file_cache)
                writer.writerow(dict(line.items()))
            else:
                pass
            c = c+1
            if (br >= params.bad):
                print("File contains many errors.")
                flag = False
                break
            if c > params.sample:
                break
        print("Number of bad rows: "+str(br))
        print("Number of lines validated: "+str(c))
        print("")
        #Close all open files
        for key, value in file_cache.iteritems():
            value.close()
    return flag

def main(fname, fname_out):
    i = 1
    j = 1
    writer_cache = dict()
    file_cache = dict()
    print("Processing file %s" % fname)
    with open(fname,'rb') as f:
        reader = csv.DictReader(f,delimiter=params.delimiter)
        headers = reader.fieldnames
#        DEBUG
#        print(headers)
        for line in reader:
            request = params.url+getmethod(line)+'?'
            #If we don't have ua column, we need to pass empty ua to REST service
            #otherwise it will return incorrect response
            if not 'ua' in headers:
                request = request + 'ua=&'
            request = request  + urllib.urlencode(line)
            if params.verbose:
                print("Request "+str(i)+": "+request)
                i =i+1
            t = 9 # Number of retry attempts
            while t >= 0:
                success = False
                try:
                    response = urllib2.urlopen(request).read()
                    if params.verbose:
                        print("Response "+str(j)+": "+response)
                        j=j+1
                    io = StringIO(response)
                    parsed = json.load(io)

                    wr_output = 'output'
                    writer = getwriter(reader.fieldnames+sorted(parsed.keys()),fname_out,params.delimiter,writer_cache,file_cache)
#                    DEBUG
#                    print ('Headers: ' + str(reader.fieldnames+sorted(parsed.keys())))
#                    print('Line: ' + str(line))
#                    print('')
#                    print('Line item: ' + str(line.items()))
#                    print('')
#                    print('Parsed item: ' + str(parsed.items()))
                    writer.writerow(dict(line.items()+parsed.items()))
                    success = True
                except Exception as e:
                    print("Eroor message from REST API: " + str(e))
                    print("Request: " + request)
                    print("Response: " + response)
                    time.sleep(5) #Sleep for 5 seconds
                t=t-1
                if success:
                    t = -100 #Condition to exit from while
    print("Output file %s has been created." % fname_out)
#    print("Exiting script.")
#Close all open files
    for key, value in file_cache.iteritems():
        value.close()
    return fname_out

params = argparser()
#Set output_folder parameter if not defined
if params.output_folder == None:
    params.output_folder = params.input_folder

#Get only files from input directory
onlyfiles = [f for f in listdir(params.input_folder) if isfile(join(params.input_folder, f)) and not f.startswith('.')]
if params.verbose:
    print('Number of files in input directory: ' + str(len(onlyfiles)))
    print('')
    print('Files: ')
    print(onlyfiles)

#Validation of files one by one from input directory
i=0
files_validated = []
while i < len(onlyfiles):
    if params.verbose == True:
        print('Validating file: ')
        print(onlyfiles[i])
        print('----------------')
    fname = None
    fname = params.input_folder + onlyfiles[i]
    fname_out = None
    fname_out = params.output_folder + onlyfiles[i] + '.rejected'

    v = validation(fname, fname_out)
    if v == True:
        print("Validation of file %s passed!" % (onlyfiles[i]))
        files_validated.append(onlyfiles[i])
#        DEBUG
#        print(files_validated)
    else:
        print("Validation of file %s failed!" % (onlyfiles[i]))
    i=i+1

print("Only next passed validation files will be processed:")
print(files_validated)

#Multiprocessing files
#Start pool
pool = multiprocessing.Pool(processes=params.numProcessors)

print("Number of processes choosen: " + str(params.numProcessors))

#Build task list
tasks = []
i = 0
while i < len(files_validated):
#DEBUG
#    print('Processing file: ')
#    print(files_validated[i])
#    print('----------------')
    fname = None
    fname = params.input_folder + files_validated[i]
    fname_out = None
    fname_out = params.output_folder + files_validated[i] + '.out'

    tasks.append( (fname, fname_out, ) )
    i=i+1

#DEBUG
#print("Tasks:")
#print(tasks)
#print("======")

#Run tasks
results = [pool.apply_async(main, (t[0],t[1])) for t in tasks]
#DEBUG
#print("Results:")
#print(results)
#print("======")
#Process results
#for result in results:
#    processed_fname = result.get()
#    print("Result: output file %s has been created" % (processed_fname) )

pool.close()
pool.join()

#Processing files one by one from input directory
#i=0
#while i < len(files_validated):
#    DEBUG
#    print('==========')
#    if params.verbose == False:
#        print('Processing file: ')
#        print(files_validated[i])
#        print('----------------')
#    fname = None
#    fname = params.input_folder + files_validated[i]
#    fname_out = None
#    fname_out = params.output_folder + files_validated[i] + '.out'
#    main(fname, fname_out)
#    i=i+1

#Close all open files
#for key, value in file_cache.iteritems():
#    value.close()


import torch
from torch import nn

from .model import BiFPN, Regressor, Classifier, EfficientNet
from .utils import Anchors, BBoxTransform, ClipBoxes
from .process import postprocess
from .loss import FocalLoss

class EfficientDetWithLoss(nn.Module):
    def __init__(self, **kwargs):
        super().__init__()
        self.model = EfficientDetBackbone(**kwargs)
        self.criterion = FocalLoss()
        self.threshold = kwargs.get("threshold", 0.2)
        self.iou_threshold = kwargs.get("iou_threshold", 0.2)

    def forward(self, imgs, annotations):
        if self.training:
            features, regression, classification, anchors = self.model(imgs)
            cls_loss, reg_loss = self.criterion(classification, regression, anchors, annotations)
        else:
            with torch.no_grad():
                features, regression, classification, anchors = self.model(imgs)
                cls_loss, reg_loss = self.criterion(classification, regression, anchors, annotations)
        losses = {"cls_loss": cls_loss, "reg_loss": reg_loss}
        return losses

    def infer(self, imgs):
        with torch.no_grad():
            features, regression, classification, anchors = self.model(imgs)
        regressBoxes = BBoxTransform()
        clipBoxes = ClipBoxes()

        out = postprocess(imgs,
                          anchors, regression, classification,
                          regressBoxes, clipBoxes,
                          self.threshold, self.iou_threshold)
        return out

class EfficientDetBackbone(nn.Module):
    def __init__(self, num_classes=80, compound_coef=0, load_weights=False, **kwargs):
        super().__init__()
        self.compound_coef = compound_coef

        self.backbone_compound_coef = [0, 1, 2, 3, 4, 5, 6, 6, 7]
        self.fpn_num_filters = [64, 88, 112, 160, 224, 288, 384, 384, 384]
        self.fpn_cell_repeats = [3, 4, 5, 6, 7, 7, 8, 8, 8]
        self.input_sizes = [512, 640, 768, 896, 1024, 1280, 1280, 1536, 1536]
        self.box_class_repeats = [3, 3, 3, 4, 4, 4, 5, 5, 5]
        self.pyramid_levels = [5, 5, 5, 5, 5, 5, 5, 5, 6]
        self.anchor_scale = [4., 4., 4., 4., 4., 4., 4., 5., 4.]
        self.aspect_ratios = kwargs.get('ratios', [(1.0, 1.0), (1.4, 0.7), (0.7, 1.4)])
        self.num_scales = len(kwargs.get('scales', [2 ** 0, 2 ** (1.0 / 3.0), 2 ** (2.0 / 3.0)]))
        conv_channel_coef = {
            # the channels of P3/P4/P5.
            0: [40, 112, 320],
            1: [40, 112, 320],
            2: [48, 120, 352],
            3: [48, 136, 384],
            4: [56, 160, 448],
            5: [64, 176, 512],
            6: [72, 200, 576],
            7: [72, 200, 576],
            8: [80, 224, 640],
        }

        num_anchors = len(self.aspect_ratios) * self.num_scales

        self.bifpn = nn.Sequential(
            *[BiFPN(self.fpn_num_filters[self.compound_coef],
                    conv_channel_coef[compound_coef],
                    True if _ == 0 else False,
                    attention=True if compound_coef < 6 else False,
                    use_p8=compound_coef > 7)
              for _ in range(self.fpn_cell_repeats[compound_coef])])

        self.num_classes = num_classes
        self.regressor = Regressor(in_channels=self.fpn_num_filters[self.compound_coef], num_anchors=num_anchors,
                                   num_layers=self.box_class_repeats[self.compound_coef],
                                   pyramid_levels=self.pyramid_levels[self.compound_coef])
        self.classifier = Classifier(in_channels=self.fpn_num_filters[self.compound_coef], num_anchors=num_anchors,
                                     num_classes=num_classes,
                                     num_layers=self.box_class_repeats[self.compound_coef],
                                     pyramid_levels=self.pyramid_levels[self.compound_coef])

        self.anchors = Anchors(anchor_scale=self.anchor_scale[compound_coef],
                               pyramid_levels=(torch.arange(self.pyramid_levels[self.compound_coef]) + 3).tolist(),
                               **kwargs)

        self.backbone_net = EfficientNet(self.backbone_compound_coef[compound_coef], load_weights)

    def freeze_bn(self):
        for m in self.modules():
            if isinstance(m, nn.BatchNorm2d):
                m.eval()

    def forward(self, inputs):
        max_size = inputs.shape[-1]

        _, p3, p4, p5 = self.backbone_net(inputs)

        features = (p3, p4, p5)
        features = self.bifpn(features)

        regression = self.regressor(features)
        classification = self.classifier(features)
        anchors = self.anchors(inputs, inputs.dtype)

        return features, regression, classification, anchors

    def init_backbone(self, path):
        state_dict = torch.load(path)
        try:
            ret = self.load_state_dict(state_dict, strict=False)
            print(ret)
        except RuntimeError as e:
            print('Ignoring ' + str(e) + '"')


import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import pickle
import seaborn as sns

import matplotlib.pyplot as plt

from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor
from sklearn.metrics import plot_confusion_matrix
# Different classification metrics
# Accuracy, Reciver Operating Characteristic (ROC curve)/Area under curve (AUC), Confusion matrix, Classification report
from sklearn.metrics import accuracy_score, roc_curve, roc_auc_score, confusion_matrix, classification_report, mean_absolute_error
from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.model_selection import cross_val_score
# Let's try the Ridge Regression model
from sklearn.linear_model import Ridge
# Import the LinearSVC estimator class
from sklearn.svm import LinearSVC

# Import Boston housing dataset
from sklearn.datasets import load_boston

# Fill missing values with Scikit-Learn
from sklearn.impute import SimpleImputer
from sklearn.compose import ColumnTransformer

selector = 1

def plot_roc_curve(fpr, tpr):
    """
    Plots a ROC curve given the false positive rate (fpr)
    and true positive rate (tpr) of a model.
    """
    # Plot roc curve
    plt.plot(fpr, tpr, color="orange", label="ROC")
    # Plot line with no predictive power (baseline)
    # plt.plot([0, 1], [0, 1], color="darkblue", linestyle="--", label="Guessing")

    # Customize the plot
    plt.xlabel("False positive rate (fpr)")
    plt.ylabel("True positive rate (tpr)")
    plt.title("Receiver Operating Characteristic (ROC) Curve")
    plt.legend()
    plt.show()

def plot_conf_mat(conf_mat):
    """
    Plots a confusion matrix using Seaborn's heatmap().
    """
    fig, ax = plt.subplots(figsize=(3, 3))
    ax = sns.heatmap(conf_mat,
                     annot=True,  # Annotate the boxes with conf_mat info
                     cbar=False)
    plt.xlabel("Predicted label")
    plt.ylabel("True label")

    # Fix the broken annotations (this happened in Matplotlib 3.1.1)
    bottom, top = ax.get_ylim()
    ax.set_ylim(bottom + 0.5, top - 0.5)
    plt.show()

def main_fn(string0: str = "fn") -> None:

    # Import dataset
    heart_disease = pd.read_csv("./data/heart-disease.csv")

    # View the data
    print(string0)
    print(heart_disease.head())

    # Create X (all the feature columns)
    X = heart_disease.drop("target", axis=1)

    # Create y (the target column)
    y = heart_disease["target"]

    # Split the data into training and test sets
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

    # View the data shapes
    print(X_train.shape, X_test.shape, y_train.shape, y_test.shape)

    # Choose the model/estimator
    model = RandomForestClassifier(n_estimators=100)

    # default parameters
    print(model.get_params())

    model.fit(X_train, y_train)

    # Make predictions
    y_preds = model.predict(X_test)

    # This will be in the same format as y_test
    print(y_preds)

    # print(X_test.loc[1])

    print(heart_disease.loc[206])

    # Make a prediction on a single sample (has to be array)
    # model.predict(np.array(X_test.loc[206]).reshape(1, -1))

    # On the training set
    print(model.score(X_train, y_train))

    # On the test set (unseen)
    print(model.score(X_test, y_test))

    print(classification_report(y_test, y_preds))

    print(confusion_matrix(y_test, y_preds))

    print(accuracy_score(y_test, y_preds))

    # Try different numbers of estimators (n_estimators is a hyperparameter you can change)
    np.random.seed(42)
    for i in range(10, 100, 10):
        print(f"Trying model with {i} estimators...")
        model = RandomForestClassifier(n_estimators=i).fit(X_train, y_train)
        print(f"Model accruacy on test set: {model.score(X_test, y_test)}")
        print("")

    # Try different numbers of estimators with cross-validation and no cross-validation
    np.random.seed(42)
    for i in range(10, 100, 10):
        print(f"Trying model with {i} estimators...")
        model = RandomForestClassifier(n_estimators=i).fit(X_train, y_train)
        print(f"Model accruacy on test set: {model.score(X_test, y_test)}")
        print(f"Cross-validation score: {np.mean(cross_val_score(model, X, y, cv=5)) * 100}%")
        print("")

    # Save trained model to file
    pickle.dump(model, open("random_forest_model_1.pkl", "wb"))

    # Load a saved model and make a prediction on a single example
    loaded_model = pickle.load(open("random_forest_model_1.pkl", "rb"))
    print(loaded_model.score(X_test, y_test))
    # loaded_model.predict(np.array(X_test.loc[206]).reshape(1, -1))

    print("1.-", model.score(X_test, y_test))
    # Compare predictions to truth labels to evaluate the model
    y_preds = model.predict(X_test)
    print("2.-", np.mean(y_preds == y_test))
    print("3.-", accuracy_score(y_test, y_preds))

    # predict_proba() returns probabilities of a classification label
    print(model.predict_proba(X_test[:5]))

    # Let's predict() on the same data...
    print(model.predict(X_test[:5]))

    print(heart_disease["target"].value_counts())

    print(mean_absolute_error(y_test, y_preds))

    # Single training and test split score
    model_single_score = model.score(X_test, y_test)

    # Take the mean of 5-fold cross-validation score
    model_cross_val_score = np.mean(cross_val_score(model, X, y, cv=5))

    print(model_single_score, model_cross_val_score)
    print(f"Heart Disease Classifier Cross-Validated Accuracy: {model_cross_val_score * 100:.2f}%")

    # Make predictions with probabilities
    y_probs = model.predict_proba(X_test)

    y_probs_positive = y_probs[:, 1]

    # Caculate fpr, tpr and thresholds
    fpr, tpr, thresholds = roc_curve(y_test, y_probs_positive)
    print("roc_auc_score: ", roc_auc_score(y_test, y_probs_positive))

    plot_roc_curve(fpr, tpr)

    # Plot perfect ROC curve and AUC score
    fpr, tpr, thresholds = roc_curve(y_test, y_test)
    plot_roc_curve(fpr, tpr)
    # Perfect AUC score
    print(roc_auc_score(y_test, y_test))

    y_preds = model.predict(X_test)

    print("confusion_matrix", confusion_matrix(y_test, y_preds))
    # Visualize confusion matrix with pd.crosstab()
    print(pd.crosstab(y_test,
                y_preds,
                rownames=["Actual Labels"],
                colnames=["Predicted Labels"]))

    # Set the font scale
    sns.set(font_scale=1.5)

    # Create a confusion matrix
    conf_mat = confusion_matrix(y_test, y_preds)

    # Plot it using Seaborn
    sns.heatmap(conf_mat)

    plot_conf_mat(conf_mat)

    plot_confusion_matrix(model, X, y)
    plt.show()

def second_fn(string1: str = "fn") -> None:
    # data converted to numerical data
    # Turn the categories into numbers
    print(string1)
    categorical_features = ["Make", "Colour", "Doors"]
    one_hot = OneHotEncoder()
    transformer = ColumnTransformer([("one_hot",
                                      one_hot,
                                      categorical_features)],
                                    remainder="passthrough")

    # Import data and drop the rows with missing labels
    data = pd.read_csv("./data/car-sales-extended.csv")

    print(data.head(), "len: " + str(len(data)), sep='\n')

    X = data.drop("Price", axis=1)
    y = data["Price"]

    transformed_X = transformer.fit_transform(X)
    # print(transformed_X)
    print(pd.DataFrame(transformed_X))
    print(X.head())

    # Another way to do it with pd.dummies...
    dummies = pd.get_dummies(data[["Make", "Colour", "Doors"]])
    print(dummies)

    # Split the data into training and test sets
    X_train, X_test, y_train, y_test = train_test_split(transformed_X, y, test_size=0.2)

    model = RandomForestRegressor()

    model.fit(X_train, y_train)
    print(model.score(X_test, y_test))

def third_fn(string2: str = "fn") -> None:
    # Import car sales missing data
    print(string2)
    car_sales_missing = pd.read_csv("./data/car-sales-extended-missing-data.csv")
    print(car_sales_missing.head())

    print("1", car_sales_missing.isna().sum())

    # Fill the "Make" column
    car_sales_missing["Make"].fillna("missing", inplace=True)

    # Fill the "Colour" column
    car_sales_missing["Colour"].fillna("missing", inplace=True)

    # Fill the "Odometer (KM)" column
    car_sales_missing["Odometer (KM)"].fillna(car_sales_missing["Odometer (KM)"].mean(), inplace=True)

    # Fill the "Doors" column
    car_sales_missing["Doors"].fillna(4, inplace=True)

    print("2", car_sales_missing.isna().sum())

    # Remove rows with missing Price value
    car_sales_missing.dropna(inplace=True)

    # Check our dataframe again
    print(3, car_sales_missing.isna().sum())
    print(car_sales_missing.shape, car_sales_missing.shape[0], np.size(car_sales_missing, 0), len(car_sales_missing))

    X = car_sales_missing.drop("Price", axis=1)
    y = car_sales_missing["Price"]

    categorical_features = ["Make", "Colour", "Doors"]
    one_hot = OneHotEncoder()
    transformer = ColumnTransformer([("one_hot",
                                      one_hot,
                                      categorical_features)],
                                    remainder="passthrough")

    transformed_X = transformer.fit_transform(X)

def fourth_fn(string3: str = "fn") -> None:
    car_sales_missing = pd.read_csv("./data/car-sales-extended-missing-data.csv")
    print(car_sales_missing.head())
    print(car_sales_missing.isna().sum())

    # Drop the rows with no labels
    car_sales_missing.dropna(subset=["Price"], inplace=True)
    print(car_sales_missing.isna().sum())

    # Split into X & y
    X = car_sales_missing.drop("Price", axis=1)
    y = car_sales_missing["Price"]

    # Split data into train and test
    np.random.seed(42)
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

    # Fill categorical values with 'missing' & numerical values with mean
    cat_imputer = SimpleImputer(strategy="constant", fill_value="missing")
    door_imputer = SimpleImputer(strategy="constant", fill_value=4)
    num_imputer = SimpleImputer(strategy="mean")

    # Define columns
    cat_features = ["Make", "Colour"]
    door_feature = ["Doors"]
    num_features = ["Odometer (KM)"]

    # Create an imputer (something that fills missing data)
    imputer = ColumnTransformer([
        ("cat_imputer", cat_imputer, cat_features),
        ("door_imputer", door_imputer, door_feature),
        ("num_imputer", num_imputer, num_features)
    ])

    # Fill train and test values separately
    filled_X_train = imputer.fit_transform(X_train)
    filled_X_test = imputer.transform(X_test)

    print(filled_X_train)

    # Get our transformed data array's back into DataFrame's
    car_sales_filled_train = pd.DataFrame(filled_X_train, columns=["Make", "Colour", "Doors", "Odometer (KM)"])

    car_sales_filled_test = pd.DataFrame(filled_X_test, columns=["Make", "Colour", "Doors", "Odometer (KM)"])

    # Check missing data in training set
    print(car_sales_filled_train.isna().sum())

    car_sales_filled_train.to_csv(r'./data/car-sales-extended-no-missing-data.csv', index=False, header=True)

    # Check to see the original... still missing values
    # car_sales_missing.isna().sum()
    # Now let's one hot encode the features with the same code as before
    categorical_features = ["Make", "Colour", "Doors"]
    one_hot = OneHotEncoder()
    transformer = ColumnTransformer([("one_hot",
                                      one_hot,
                                      categorical_features)],
                                    remainder="passthrough")

    # Fill train and test values separately
    transformed_X_train = transformer.fit_transform(car_sales_filled_train)
    transformed_X_test = transformer.transform(car_sales_filled_test)

    # Check transformed and filled X_train
    transformed_X_train.toarray()

    # Now we've transformed X, let's see if we can fit a model
    np.random.seed(42)

    model = RandomForestRegressor(n_estimators=100)

    # Make sure to use transformed (filled and one-hot encoded X data)
    model.fit(transformed_X_train, y_train)
    print(model.score(transformed_X_test, y_test))

def fiveth_fn(string4: str = "fn") -> None:
    boston = load_boston()

    print(type(boston))

    boston_df = pd.DataFrame(boston["data"], columns=boston["feature_names"])
    boston_df["target"] = pd.Series(boston["target"])

    print(boston_df.head())

    # How many samples?
    print("len", len(boston_df))
    print(np.size(boston_df, 0), boston_df.shape[0], boston_df.shape[1], boston_df.size, sep="\n")

    # Setup random seed
    np.random.seed(42)

    # Create the data
    X = boston_df.drop("target", axis=1)
    y = boston_df["target"]

    # Split into train and test sets
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

    # Instantiate Ridge model
    model = Ridge()
    model.fit(X_train, y_train)

    # Check the score of the Ridge model on test data
    print(model.score(X_test, y_test))

def sixth_fn(string5: str = "fn") -> None:
    # Setup random seed
    np.random.seed(42)

    boston = load_boston()

    boston_df = pd.DataFrame(boston["data"], columns=boston["feature_names"])
    boston_df["target"] = pd.Series(boston["target"])

    # Create the data
    X = boston_df.drop("target", axis=1)
    y = boston_df["target"]

    # Split the data
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

    # Instatiate Random Forest Regressor
    rf = RandomForestRegressor(n_estimators=100)
    rf.fit(X_train, y_train)

    # Evaluate the Random Forest Regressor
    rf.score(X_test, y_test)

def seventh_fn(string6: str = "fn") -> None:
    # Setup random seed
    np.random.seed(42)

    # Import dataset
    heart_disease = pd.read_csv("./data/heart-disease.csv")

    # Make the data
    X = heart_disease.drop("target", axis=1)
    y = heart_disease["target"]

    # Split the data
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

    # Instantiate LinearSVC
    clf = LinearSVC(max_iter=10000)
    clf.fit(X_train, y_train)

    # Evaluate the LinearSVC
    print("1.-", clf.score(X_test, y_test))
    # Compare predictions to truth labels to evaluate the model
    y_preds = clf.predict(X_test)
    print("2.-", np.mean(y_preds == y_test))
    print("3.-", accuracy_score(y_test, y_preds))

    # predict_proba() returns probabilities of a classification label
    clf.predict_proba(X_test[:5])

# Press the green button in the gutter to run the script.
if __name__ == '__main__':

    if selector == 1:
        main_fn('dummy0')
    elif selector == 2:
        second_fn('dummy1')
    elif selector == 3:
        third_fn('dummy2')
    elif selector == 4:
        fourth_fn('dummy3')
    elif selector == 5:
        fiveth_fn('dummy4')
    elif selector == 6:
        sixth_fn('dummy5')
    elif selector == 7:
        seventh_fn('dummy6')
# See PyCharm help at https://www.jetbrains.com/help/pycharm/


from sklearn.utils import shuffle
import torch
from torch import nn
import numpy as np
import copy
import random

class SentenceFocus():

    def __init__(self,opts) -> None:

        self.beta = opts.sief_beta

        if opts.use_model == "bert":
            self.use_bert = True
        else:
            self.use_bert = False

        self.no_na_loss = opts.no_na_loss
        self.relation_nums = opts.relation_nums

        self.entropy = nn.BCEWithLogitsLoss(reduction='none')

    def prepro_data(self,data):
        newdata = copy.deepcopy(data)
        N_bt = data["context_idxs"].shape[0]

        for i in range(N_bt):
            rand_mask_sentence(data, newdata, i,self.use_bert)

        max_len = torch.max(newdata["context_word_length"]).item()

        newdata["context_idxs"] = newdata["context_idxs"][:,:max_len]
        newdata["context_sent"] = newdata["context_sent"][:,:max_len]
        newdata["context_word_mask"] = newdata["context_word_mask"][:,:max_len]
        newdata["context_mention"] = newdata["context_mention"][:,:max_len]
        newdata["context_pos"] = newdata["context_pos"][:,:max_len]
        newdata["context_ner"] = newdata["context_ner"][:,:max_len]

        return newdata
    def importance_estimation(self,predictions,predictions_hat):
        p = torch.sigmoid(predictions)
        p_hat = torch.sigmoid(predictions_hat)
        score = p*torch.log(p/(p_hat+1e-11))
        return score
    def sentence_focusing(self,predictions,predictions_hat,relation_mask_hat,relation_multi_label):
        importance_score = self.importance_estimation(predictions,predictions_hat)
        evidence_mask = torch.logical_and((importance_score>self.beta),(relation_multi_label>0))
        evidence_mask[...,0] = False

        instance_mask = relation_mask_hat.unsqueeze(2).repeat(1,1,self.relation_nums)
        instance_mask[evidence_mask] = 0

        if self.no_na_loss:
            loss_sf = torch.sum(self.entropy(predictions_hat[...,1:], torch.sigmoid(predictions)[...,1:]) * instance_mask[...,1:]) / torch.sum(instance_mask[...,1:])
        else:
            loss_sf = torch.sum(self.entropy(predictions_hat, torch.sigmoid(predictions)) * instance_mask) / torch.sum(instance_mask)

        return loss_sf

def rand_mask_sentence(data,newdata,nb,use_bert,delete_id=None):
    N_sent = torch.max(data["context_sent"][nb]).item()
    N_words = data["context_sent"][nb].shape[0]
    if delete_id is None:
        delete_id = np.random.randint(N_sent)
    else:
        assert delete_id < N_sent
    sent_len = []
    for i in range(N_sent):
        sent_len.append(torch.sum(data["context_sent"][nb]==(i+1)).item())
    if use_bert:
        L_sent = [1]
        sent_len[0] -= 1
        sent_len[-1] -= 1
    else:
        L_sent = [0]
    left_len = np.sum(sent_len[delete_id+1:])
    sent_dict = np.arange(N_sent)
    sent_dict[delete_id] = -1
    sent_dict[delete_id+1:] -= 1
    for sent_id in range(N_sent):
        L_sent.append(L_sent[-1]+sent_len[sent_id])

    word_dict = np.arange(N_words)
    if left_len == 0:
        start1 = L_sent[delete_id]
        word_dict[start1:] = 0
        newdata["context_idxs"][nb,start1:] = 0
        if use_bert:
            new_w_sum = torch.sum(newdata["context_idxs"][nb]>0).item()
            w_sum = torch.sum(data["context_idxs"][nb]>0).item()
            newdata["context_idxs"][nb,new_w_sum] = data["context_idxs"][nb,w_sum-1]
        newdata["context_sent"][nb,start1:] = 0
        newdata["context_word_length"][nb] = torch.sum(newdata["context_idxs"][nb]>0,dim=-1)
        newdata["context_word_mask"][nb] = newdata["context_idxs"][nb]>0
        newdata["context_mention"][nb,start1:] = 0
        newdata["context_pos"][nb,start1:] = 0
        newdata["context_ner"][nb,start1:] = 0
    else:
        start1 = L_sent[delete_id]
        start2 = L_sent[delete_id+1]
        word_dict[start2:start2+left_len] = word_dict[start1:start1+left_len]
        word_dict[start1:start2] = 0
        newdata["context_idxs"][nb,start1:start1+left_len] = data["context_idxs"][nb,start2:start2+left_len]
        newdata["context_idxs"][nb,start1+left_len:] = 0
        if use_bert:
            new_w_sum = torch.sum(newdata["context_idxs"][nb]>0).item()
            w_sum = torch.sum(data["context_idxs"][nb]>0).item()
            newdata["context_idxs"][nb,new_w_sum] = data["context_idxs"][nb,w_sum-1]

        newdata["context_sent"][nb,start1:start1+left_len] = data["context_sent"][nb,start2:start2+left_len]-1
        newdata["context_sent"][nb,start1+left_len:] = 0
        if use_bert:
            newdata["context_sent"][nb,new_w_sum] = data["context_sent"][nb,w_sum-1]-1

        newdata["context_word_length"][nb] = torch.sum(newdata["context_idxs"][nb]>0,dim=-1)
        newdata["context_word_mask"][nb] = newdata["context_idxs"][nb]>0

        newdata["context_mention"][nb,start1:start1+left_len] = data["context_mention"][nb,start2:start2+left_len]
        newdata["context_mention"][nb,start1+left_len:] = 0
        newdata["context_pos"][nb,start1:start1+left_len] = data["context_pos"][nb,start2:start2+left_len]
        newdata["context_pos"][nb,start1+left_len:] = 0
        newdata["context_ner"][nb,start1:start1+left_len] = data["context_ner"][nb,start2:start2+left_len]
        newdata["context_ner"][nb,start1+left_len:] = 0

    left_entity_set = []
    total_entity_set= []
    delete_node = []
    for n_id in range(newdata["graph_info"].shape[1]):
        if newdata["graph_info"][nb,n_id,5].item() == -1:
            continue
        newdata["graph_info"][nb,n_id,0] = word_dict[data["graph_info"][nb,n_id,0]]
        newdata["graph_info"][nb,n_id,1] = word_dict[data["graph_info"][nb,n_id,1]-1]+1
        newdata["graph_info"][nb,n_id,5] = sent_dict[data["graph_info"][nb,n_id,5]]
        if newdata["graph_info"][nb,n_id,5].item() == -1:
            newdata["graph_info"][nb,n_id,0] = -1
            newdata["graph_info"][nb,n_id,1] = -1
            newdata["graph_info"][nb,n_id,2] = -1
            newdata["graph_adj"][nb,n_id,:] = 0
            newdata["graph_adj"][nb,:,n_id] = 0
            delete_node.append(n_id)

        if newdata["graph_info"][nb,n_id,3]==1:
            continue
        elif newdata["graph_info"][nb,n_id,3]==2:
            total_entity_set.append(newdata["graph_info"][nb,n_id,2].item())
            if newdata["graph_info"][nb,n_id,5].item() != -1:
                left_entity_set.append(newdata["graph_info"][nb,n_id,2].item())
        else:
            break
    delete_entity = set(total_entity_set) - set(left_entity_set) -set([-1])
    for it in delete_entity:
        p_ind,_ = torch.where(newdata['h_t_pairs'][nb]==it)
        newdata['relation_mask'][nb,p_ind] = 0
    for it in delete_node:
        if it == 0:
            continue
        p_ind,m_ind,_ = torch.where(newdata['relation_path'][nb]==it)
        newdata['relation_path'][nb,p_ind,m_ind] = 0
    return newdata

def rand_shuffle_sentence(data,newdata,nb,use_bert=False):
    N_sent = torch.max(data["context_sent"][nb]).item()
    N_words = data["context_sent"][nb].shape[0]
    new_sent_seq = list(range(N_sent))
    random.shuffle(new_sent_seq)
    sent_len = []
    for i in range(N_sent):
        sent_len.append(torch.sum(data["context_sent"][nb]==(i+1)).item())
    if use_bert:
        L_sent = [1]
        new_L_sent = [1]
    else:
        L_sent = [0]
        new_L_sent = [0]
    for sent_id in range(N_sent):
        L_sent.append(L_sent[-1]+sent_len[sent_id])
        new_L_sent.append(new_L_sent[-1]+sent_len[new_sent_seq[sent_id]])
    word_dict = np.arange(N_words)
    for sent_id in range(N_sent):
        cur_id = new_sent_seq[sent_id]
        word_dict[L_sent[cur_id]:L_sent[cur_id+1]] = \
            torch.arange(new_L_sent[sent_id],new_L_sent[sent_id+1])
        newdata["context_sent"][nb,new_L_sent[sent_id]:new_L_sent[sent_id+1]]=sent_id+1
        newdata["context_idxs"][nb,new_L_sent[sent_id]:new_L_sent[sent_id+1]]=\
        data["context_idxs"][nb,L_sent[cur_id]:L_sent[cur_id+1]]
        newdata["context_mention"][nb,new_L_sent[sent_id]:new_L_sent[sent_id+1]]=\
        data["context_mention"][nb,L_sent[cur_id]:L_sent[cur_id+1]]
        newdata["context_pos"][nb,new_L_sent[sent_id]:new_L_sent[sent_id+1]]=\
        data["context_pos"][nb,L_sent[cur_id]:L_sent[cur_id+1]]
        newdata["context_ner"][nb,new_L_sent[sent_id]:new_L_sent[sent_id+1]]=\
        data["context_ner"][nb,L_sent[cur_id]:L_sent[cur_id+1]]
    for n_id in range(newdata["graph_info"].shape[1]):
        if newdata["graph_info"][nb,n_id,5] == -1:
            continue
        sent_id = new_sent_seq.index(data["graph_info"][nb,n_id,5])
        if data["graph_info"][nb,n_id,3]==1:
            newdata["graph_info"][nb,n_id,0] = new_L_sent[sent_id]
            newdata["graph_info"][nb,n_id,1] = new_L_sent[sent_id+1]
            newdata["graph_info"][nb,n_id,5] = sent_id
        elif newdata["graph_info"][nb,n_id,3]==2:
            newdata["graph_info"][nb,n_id,0] = word_dict[data["graph_info"][nb,n_id,0]]
            newdata["graph_info"][nb,n_id,1] = word_dict[data["graph_info"][nb,n_id,1]-1]+1
            newdata["graph_info"][nb,n_id,5] = sent_id
        else:
            break
    for n_id in range(newdata["context_ems_info"].shape[1]):
        if newdata["context_ems_info"][nb,n_id,0]==1:
            continue
        elif newdata["context_ems_info"][nb,n_id,0]==2 and newdata["graph_info"][nb,n_id,5] != -1:
            newdata["context_ems_info"][nb,n_id,2] = word_dict[data["context_ems_info"][nb,n_id,2]]
            newdata["context_ems_info"][nb,n_id,3] = word_dict[data["context_ems_info"][nb,n_id,3]-1]+1
            newdata["context_ems_info"][nb,n_id,6] = new_sent_seq.index(data["context_ems_info"][nb,n_id,6])
        elif newdata["context_ems_info"][nb,n_id,0]==3 and newdata["graph_info"][nb,n_id,5] != -1:
            newdata["context_ems_info"][nb,n_id,2] = word_dict[data["context_ems_info"][nb,n_id,2]]
            newdata["context_ems_info"][nb,n_id,3] = word_dict[data["context_ems_info"][nb,n_id,3]-1]+1
        else:
            break
    return newdata


import os
import shutil
import argparse
import record
import tensorflow as tf

def convert2tfrecord(work_dir, filepath=''):
    # work_dir: '/assets/datasets'
    pascal_root = os.path.join(work_dir, 'data')
    output_dir = os.path.join(work_dir, 'tfrecord')
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    image_folder = os.path.join(pascal_root, 'JPEGImages')
    list_folder = os.path.join(pascal_root, 'ImageSets/Segmentation')
    if filepath != '':
        fn = os.path.basename(filepath)
        local_fn = os.path.join(image_folder, fn)
        local_fn_list = os.path.join(list_folder, 'val.txt')
        if not os.path.exists(local_fn):
            shutil.copyfile(filepath, local_fn)
        with open(local_fn_list, 'w') as of:
            print(fn[:fn.rfind('.')])
            of.write(fn[:fn.rfind('.')])
    # image_folder: 'data/JPEGImages'
    # list_folder:  'data/ImageSets/Segmentation'
    # output_dir:   'tfrecord'
    command = 'python seg/deeplab/datasets/build_voc2012_data.py \
                --image_folder={} \
                --list_folder={} \
                --image_format="jpg"\
                --output_dir={}'.format(image_folder, list_folder, output_dir)
    os.system(command)

def segment(checkpoint_dir, work_dir):
    # checkpoint_dir: 'exp/train_on_train_set/train'
    # dataset_dir:    'tfrecord'
    dataset_dir = os.path.join(work_dir, 'tfrecord')
    command = 'python seg/deeplab/vis.py \
                --logtostderr \
                --vis_split="val" \
                --model_variant="xception_65" \
                --atrous_rates=6 \
                --atrous_rates=12 \
                --atrous_rates=18 \
                --output_stride=16 \
                --decoder_output_stride=4 \
                --vis_crop_size=1505 \
                --vis_crop_size=2049 \
                --dataset="homeplus" \
                --colormap_type=homeplus \
                --vis_batch_size=1 \
                --checkpoint_dir={} \
                --vis_logdir={} \
                --dataset_dir={}'.format(checkpoint_dir, work_dir, dataset_dir)
    os.system(command)

def segment2skels(work_dir):
    segment_folder = os.path.join(work_dir, 'segmentation_results')
    command = 'python seg2skel/seg2skels.py \
                --segment-folder={}'.format(segment_folder)
    os.system(command)
    input('before load skel')
    # command = 'python seg2skel/load_skels.py \
    #             --segment-folder={}'.format(segment_folder)
    # os.system(command)

def main(args):
    # convert2tfrecord(args.work_dir, args.filepath)
    segment(args.checkpoint_dir, args.work_dir)
    input('before seg2skel')
    segment2skels(args.work_dir)

if __name__ == '__main__':
    program_dir = '/home/chr/sgy/web/program/'
    parser = argparse.ArgumentParser(description='Segmentation and Skeleton')
    parser.add_argument('--work-dir', default=program_dir+'assets/datasets/', type=str)
    parser.add_argument('--checkpoint-dir', default=program_dir+'assets/datasets/exp/train_on_train_set/train/', type=str)
    parser.add_argument('--filepath', default='', type=str)
    args = parser.parse_args()

    # print(os.environ['PYTHONPATH'])

    main(args)
    # with tf.Session() as sess:
    #     record.write_record(None, sess)
    #     input('write finish')

[1505, 2049]
1
None
None
None
val
xception_65
[6, 12, 18]
16

[1505, 2049]
1
None
None
None
val
xception_65
[6, 12, 18]
16


import pyautogui
import pytesseract
from PIL import Image
import time

time.sleep(3)

# It's not advised to use while loop
# There is a built-in mechanism in pyautogui to terminate program if we
# move our cursor to top left. This will cause program to break

while True:
    # region may vary for different screen
    im = pyautogui.screenshot(region=(232, 279, 835, 106))
    im.save('data.png')

    # To click text area and start typing
    pyautogui.click(x=464, y=425)

    # To get text from given image
    value = pytesseract.image_to_string(Image.open('data.png'))

    # To replace new line from it and make one clean list
    value = value.replace('\n\n',' ')
    b = value.split(' ')

    print(b)

    # Backspace is used to avoid any error
    for i in b:
        pyautogui.press('backspace')
        pyautogui.typewrite(i)
        pyautogui.press('space')
    if len(b) <= 4:
        break


import numpy as np
from scipy import stats
from math import sqrt
import multiprocessing as mp
from itertools import repeat
from sklearn.mixture import GaussianMixture, BayesianGaussianMixture
from sklearn.cluster import SpectralClustering
from sklearn.metrics import adjusted_rand_score
from sklearn.neighbors import NearestNeighbors
import matplotlib.pyplot as plt
from low_rank_rnns.modules import SupportLowRankRNN, LowRankRNN, FullRankRNN
from low_rank_rnns.helpers import gram_factorization
from low_rank_rnns.plotting import center_axes
import torch

#%% GAUSSIAN MIXTURES

def gmm_fit(neurons_fs, n_components, algo='bayes', n_init=50, random_state=None, mean_precision_prior=None,
            weight_concentration_prior_type='dirichlet_process', weight_concentration_prior=None):
    """
    Fit a mixture of gaussians to a cloud of n points
    :param neurons_fs: list of numpy arrays of shape n or numpy array of shape n x d
    :param n_components: int
    :param algo: 'em' (expectation-maximization) or 'bayes'
    :param n_init: number of random seeds for the inference algorithm
    :param random_state: random seed for the rng to eliminate randomness
    :return: vector of population labels (of shape n), best fitted model
    """
    if isinstance(neurons_fs, list):
        X = np.vstack(neurons_fs).transpose()
    else:
        X = neurons_fs
    if algo == "em":
        model = GaussianMixture(n_components=n_components, n_init=n_init, random_state=random_state)
    else:
        model = BayesianGaussianMixture(n_components=n_components, n_init=n_init, random_state=random_state,
                                        init_params='random', mean_precision_prior=mean_precision_prior,
                                        weight_concentration_prior_type=weight_concentration_prior_type,
                                        weight_concentration_prior=weight_concentration_prior)
    model.fit(X)
    z = model.predict(X)
    return z, model

def make_vecs(net):
    """
    return a list of vectors (list of numpy arrays of shape n) composing a network
    """
    return [net.m[:, i].detach().cpu().numpy() for i in range(net.rank)] + \
           [net.n[:, i].detach().cpu().numpy() for i in range(net.rank)] + \
           [net.wi[i].detach().cpu().numpy() for i in range(net.input_size)] + \
           [net.wo[:, i].cpu().detach().numpy() for i in range(net.output_size)]

def to_support_net(net, z, new_size=None, take_means=False):
    """
    Generate a SupportLowRankRNN from a LowRankRNN, with populations defined by z
    :param net: LowRankRNN
    :param z: numpy array of size n whose entries are integer labels for populations
    :param new_size: int
    :param take_means: bool, whether to take into account means of components or set them to zero
    :return: the SupportLowRankRNN
    """
    X = np.vstack(make_vecs(net)).transpose()
    _, counts = np.unique(z, return_counts=True)
    n_components = counts.shape[0]
    weights = counts / net.hidden_size
    if take_means:
        means = np.vstack([X[z == i].mean(axis=0) for i in range(n_components)])
    else:
        means = np.zeros((n_components, X.shape[1]))
    covariances = [np.cov(X[z == i].transpose()) for i in range(n_components)]

    rank = net.rank
    basis_dim = 2 * rank + net.input_size + net.output_size
    m_init = torch.zeros(rank, n_components, basis_dim)
    n_init = torch.zeros(rank, n_components, basis_dim)
    wi_init = torch.zeros(net.input_size, n_components, basis_dim)
    wo_init = torch.zeros(net.output_size, n_components, basis_dim)

    if new_size is None:
        new_size = net.hidden_size
    m_means = torch.from_numpy(means[:, :rank]).t() / sqrt(new_size)
    n_means = torch.from_numpy(means[:, rank: 2*rank]).t() / sqrt(new_size)
    wi_means = torch.from_numpy(means[:, 2*rank: 2*rank + net.input_size]).t()

    for i in range(n_components):
        # Compute Gramian matrix of the basis we have to build
        G = covariances[i]
        # compute coefficients on the basis of iid normal vectors
        X_reduced = gram_factorization(G)
        for k in range(rank):
            m_init[k, i] = torch.from_numpy(X_reduced[k]) / sqrt(new_size)
            n_init[k, i] = torch.from_numpy(X_reduced[rank + k]) / sqrt(new_size)
        for k in range(net.input_size):
            wi_init[k, i] = torch.from_numpy(X_reduced[2 * rank + k])
        for k in range(net.output_size):
            wo_init[k, i] = torch.from_numpy(X_reduced[2 * rank + net.input_size + k]) / new_size

    net2 = SupportLowRankRNN(net.input_size, new_size, net.output_size, net.noise_std, net.alpha, rank, n_components,
                             weights, basis_dim, m_init, n_init, wi_init, wo_init, m_means, n_means, wi_means)
    return net2

def inactivate_pop(net, pop):
    size = net.hidden_size - np.sum(pop)
    wi = net.wi_full[:, ~pop]
    wo = net.wo_full[~pop]

    if isinstance(net, LowRankRNN):
        m = net.m[~pop]
        n = net.n[~pop]
        net2 = LowRankRNN(net.input_size, size, net.output_size, net.noise_std, net.alpha, net.rank,
                          wi_init=wi, m_init=m, n_init=n, wo_init=wo)
    elif isinstance(net, FullRankRNN):
        mask = np.ix_(~pop, ~pop)
        wrec = net.wrec[mask]
        net2 = FullRankRNN(net.input_size, size, net.output_size, net.noise_std, net.alpha, net.rho,
                           wi_init=wi, wrec_init=wrec, wo_init=wo)
    else:
        raise NotImplementedError
    return net2

#%%  PLOTTING

def pop_scatter_linreg(vec1, vec2, pops, n_pops=None, colors=('blue', 'red', 'green', 'gray'),
                       linreg=True, figsize=(5, 5), ax=None, dotsize=4, ls=None, lw=None):
    """
    scatter plot of (vec1, vec2) points separated in populations according to int labels in vector pops, with linear
    regressions
    """
    if ax is None:
        fig, ax = plt.subplots(figsize=figsize)
    center_axes(ax)

    # Computing axes limits
    xmax = max(abs(vec1.min()), vec1.max())
    xmin = -xmax
    ax.set_xlim(xmin - .1 * (xmax - xmin), xmax + .1 * (xmax - xmin))
    ymax = max(abs(vec2.min()), vec2.min())
    ymin = -ymax
    ax.set_ylim(ymin - .1 * (ymax - ymin), ymax + .1 * (ymax - ymin))
    xs = np.linspace(xmin - .1 * (xmax - xmin), xmax + .1 * (xmax - xmin), 100)

    if n_pops is None:
        n_pops = np.unique(pops).shape[0]
    for i in range(n_pops):
        ax.scatter(vec1[pops == i], vec2[pops == i], color=colors[i], s=dotsize)
        if linreg:
            slope, intercept, r_value, p_value, std_err = stats.linregress(vec1[pops == i], vec2[pops == i])
            print(f"pop {i}: slope={slope:.2f}, intercept={intercept:.2f}")
            ax.plot(xs, slope * xs + intercept, color=colors[i], zorder=-1, ls=ls, lw=lw)
    ax.set_xticks([])
    ax.set_yticks([])

#%% SPECTRAL CLUSTERING AND STABILITY ANALYSIS

def generate_subsamples(neurons_fs, fraction=.8):
    indexes = np.random.choice(neurons_fs.shape[0], int(fraction * neurons_fs.shape[0]), replace=False)
    indexes = np.sort(indexes)
    return neurons_fs[indexes], indexes

def spectral_clustering(neurons_fs, n_clusters, metric='euclidean', n_neighbors=10):
    if metric == 'euclidean':
        model = SpectralClustering(n_clusters, affinity='nearest_neighbors')
        model.fit(neurons_fs)
    elif metric == 'cosine':
        model = SpectralClustering(n_clusters, affinity='precomputed')
        nn = NearestNeighbors(n_neighbors=n_neighbors, algorithm='brute', metric='cosine')
        nn.fit(neurons_fs)
        knn_graph = nn.kneighbors_graph()
        knn_graph = 0.5 * (knn_graph + knn_graph.transpose())
        model.fit(knn_graph)
    return model

def clustering_stability_task(neurons_fs, algo, n_clusters, metric, n_neighbors, mean_precision_prior=1e5):
    sample, indexes = generate_subsamples(neurons_fs)
    if algo == 'spectral':
        model = spectral_clustering(sample, n_clusters, metric, n_neighbors)
        labels = model.labels_
    else:
        labels, _ = gmm_fit(sample, n_clusters, mean_precision_prior=mean_precision_prior,
                            weight_concentration_prior_type='dirichlet_distribution')
    return labels, indexes

def clustering_stability(neurons_fs, n_clusters, n_bootstrap, algo='gmm', metric='cosine', n_neighbors=10,
                         mean_precision_prior=1e5, normalize=None):
    """
    Compute clustering stability distribution for a particular number of clusters and algorithm
    :param neurons_fs: numpy array of shape Nxd (neurons embedded in some feature space)
    :param n_clusters: int
    :param n_bootstrap: int
    :param algo: 'spectral' or 'gmm'
    :param metric: 'euclidean' or 'cosine' for spectral clustering
    :param n_neighbors: int, for spectral clustering
    :param mean_precision_prior:
    :param normalize: None, 'normal' or 'uniform'
    :return: list of n_bootstrap x (n_bootstrap - 1) / 2 ARI values for bootstrapped clusterings (possibly normalized)
    """

    with mp.Pool(mp.cpu_count()) as pool:
        args = repeat((neurons_fs, algo, n_clusters, metric, n_neighbors, mean_precision_prior), n_bootstrap)
        res = pool.starmap(clustering_stability_task, args)
        labels_list, indexings = zip(*res)

    aris = []
    # Align bootstrap samples and compute pairwise Rand indexes
    for i in range(n_bootstrap):
        for j in range(i+1, n_bootstrap):
            # build aligned labellings
            indexes_i = indexings[i]
            indexes_j = indexings[j]
            labels_i = []
            labels_j = []
            l = 0
            for k in range(len(indexes_i)):
                if l > len(indexes_j):
                    break
                while l < len(indexes_j) and indexes_j[l] < indexes_i[k]:
                    l += 1
                if l < len(indexes_j) and indexes_j[l] == indexes_i[k]:
                    labels_i.append(labels_list[i][k])
                    labels_j.append(labels_list[j][l])
                    l += 1
            aris.append(adjusted_rand_score(labels_i, labels_j))

    if normalize is not None:
        if normalize == 'normal':
            X_base = np.random.randn(neurons_fs.shape[0], neurons_fs.shape[1])
        elif normalize == 'uniform':
            X_base = (np.random.rand(neurons_fs.shape[0], neurons_fs.shape[1]) - 0.5) * 2
        base_aris = clustering_stability(X_base, n_clusters, n_bootstrap, metric, normalize=None)
        base_mean, base_std = np.mean(base_aris), np.std(base_aris)
        aris = [(ari - base_mean) / base_std for ari in aris]
    return aris

def boxplot_clustering_stability(neurons_fs, clusters_nums, aris=None, algo='gmm', n_bootstrap=20, metric='cosine',
                                 n_neighbors=10, ax=None):
    """
    :param neurons_fs: numpy array of shape Nxd (neurons embedded in some feature space)
    :param clusters_nums: list of ints
    :param aris: if precomputed aris, list of lists with ari distributions
    :param algo: 'spectral' or 'gmm'
    :param n_bootstrap: int
    :param metric: 'euclidean' or 'cosine' for spectral clustering
    :param n_neighbors: int, for spectral clustering
    :param ax: matplotlib axes if already setup
    :return: axes
    """
    if aris is None:
        aris = [clustering_stability(neurons_fs, k, n_bootstrap, algo, metric, n_neighbors) for k in clusters_nums]
    aris = np.array(aris)
    if ax is None:
        fig, ax = plt.subplots()
    col_lines = 'indianred'
    bp = ax.boxplot(aris.T, patch_artist=True)
    for box in bp['boxes']:
        box.set(color='steelblue', facecolor='steelblue')
    for med in bp['medians']:
        med.set(color=col_lines)
    for l in bp['whiskers']:
        l.set(color=col_lines)
    for l in bp['caps']:
        l.set(color=col_lines)
    ax.set_xticks(list(range(1, aris.shape[0] + 1)))
    ax.set_xticklabels(clusters_nums)
    ax.set(xlabel='number of clusters', ylabel='stability', ylim=(-.1, 1.1))
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    return ax


import torch
import torch.nn as nn
import torch.nn.functional as F

class ResBlock(nn.Module):
    def __init__(self, in_ch, out_ch):
        super(ResBlock, self).__init__()

        self.model = nn.Sequential(nn.Conv2d(in_ch, out_ch, kernel_size=1, stride=1),
                                   nn.BatchNorm2d(out_ch),
                                   nn.ReLU(),
                                   nn.Conv2d(out_ch, out_ch, kernel_size=1, stride=1),
                                   nn.BatchNorm2d(out_ch))

    def forward(self, x):
        return x + self.model(x)

class IntModel(nn.Module):
    def __init__(self):
        super(IntModel, self).__init__()
        self.conv_A = self._build_conv()
        self.conv_B = self._build_conv()

        self.lstm_A = nn.LSTM(512, 256, 2, batch_first=True)
        self.lstm_B = nn.LSTM(512, 256, 2, batch_first=True)

        self.classifier = self._build_cls()

    def forward(self, x1, x2):
        bs = x1.shape[0]
        depth = x1.shape[1]
        chw = x1.shape[-3:]

        x1 = torch.reshape(x1, [-1] + list(chw))
        x2 = torch.reshape(x2, [-1] + list(chw))

        encoded_A = self.conv_A(x1)
        encoded_B = self.conv_B(x2)

        encoded_A = torch.reshape(encoded_A, (bs, depth, -1))
        encoded_B = torch.reshape(encoded_B, (bs, depth, -1))

        out_A, (h_A, c_A) = self.lstm_A(encoded_A)
        out_B, (h_B, c_B) = self.lstm_B(encoded_B)

        h_A = torch.reshape(torch.stack(torch.unbind(h_A, dim=1), dim=0), (bs, -1))
        h_B = torch.reshape(torch.stack(torch.unbind(h_B, dim=1), dim=0), (bs, -1))

        feat_AB = torch.cat((h_A, h_B), dim=1)

        prob = self.classifier(feat_AB)

        return prob

    def _build_cls(self, in_size=1024, num_cls=6):
        model = [nn.Linear(in_size, num_cls)]
        return nn.Sequential(*model)

    def _build_conv(self, in_ch=32, npf=64):
        n_blocks = 3
        model = [nn.Conv2d(in_ch, 64, kernel_size=3, stride=2, padding=1),
                 nn.ReLU(True)]

        for cnt in range(n_blocks):
            previous = npf * 2 ** cnt
            model += [nn.Conv2d(previous, previous * 2, kernel_size=3, stride=2, padding=1),
                      nn.BatchNorm2d(previous * 2),
                      nn.ReLU(True),
                      ResBlock(previous * 2, previous * 2)]

        model += [nn.AdaptiveMaxPool2d(1)]
        return nn.Sequential(*model)

if __name__ == '__main__':
    m = ResBlock(64,64)

    # x1 = torch.randn(4,5,32,64,64)
    # x2 = torch.randn(4,5,32,64,64)
    data = torch.randn(4,64,128,128)
    out = m(data)
    import ipdb
    ipdb.set_trace()