import torch
import numpy as np
import matplotlib.pyplot as plt

# set up matplotlib
plt.ion()

# Helper function to plot duration of episodes and an average over the last 100 iterations
def plot_variables(fig, plot_var, title):
    fig, ax1, ax2 = fig
    durations_t = torch.tensor(plot_var['durations'], dtype=torch.float)
    rewards_t = torch.tensor(plot_var['rewards'], dtype=torch.float)

    fig.suptitle(title)
    ax1.set_xlabel('Episode')
    ax1.set_ylabel('Duration')
    ax2.set_xlabel('Episode')
    ax2.set_ylabel('Reward')
    ax1.plot(durations_t.numpy(), 'bo')
    ax2.plot(rewards_t.numpy(), 'bo')

    # Take 100 episode averages and plot them too
    if len(durations_t) >= 50:
        means = durations_t.unfold(0, 50, 1).mean(1).view(-1)
        means = torch.cat((torch.zeros(49), means))
        ax1.plot(means.numpy(), 'r')
        means = rewards_t.unfold(0, 50, 1).mean(1).view(-1)
        means = torch.cat((torch.zeros(49), means))
        ax2.plot(means.numpy(), 'r')

    plt.pause(0.001)    # Small pause to update plots


import matplotlib.pyplot as plt # plt 用于显示图片
from PIL import Image
import numpy as np
import seaborn as sns
from seaborn.matrix import clustermap
MAX_NUM = 1000

class MyGaussianBlur():
    def __init__(self, radius = 1, sigma = 1.5):
        '''
        Description
        ----------
        高斯模糊

        Parameters
        ----------
        radius : int
            半径

        sigma : float
            $\sigma$值
        '''
        self.__radius = radius
        self.__sigma2 = sigma*sigma
        self.__filterLen = radius*2+1
        self.__filter = np.zeros((self.__filterLen, self.__filterLen))
        for i in range(radius*2+1):
            for j in range(radius*2+1):
                self.__filter[i,j] = self.__calcGuassian(i-radius,j-radius)
        self.__filter /= np.sum(self.__filter)

    def __calcGuassian(self,x,y):
        return np.exp(-(x*x+y*y)/(2*self.__sigma2))/(2*np.pi*self.__sigma2)

    def smooth(self, img):
        '''
        Description
        ----------
        得到img的高斯模糊矩阵

        Parameters
        ----------
        img : ndarray (height, width, _)
            原始图像

        sigma : float
            $\sigma$值

        Returns
        ----------
        output : ndarray (height, width, _)
            高斯模糊后的图像
        '''
        if len(img.shape)==3:
            tempImg = img
        elif len(img.shape)==2:
            tempImg = img[:,:,np.newaxis]
        paddedImg = np.pad(tempImg, ((self.__radius, self.__radius), (self.__radius, self.__radius), (0,0)), 'constant', constant_values=0)

        output = np.zeros_like(tempImg)
        filter = np.repeat(self.__filter[:,:, np.newaxis], tempImg.shape[2], axis=2)
        for i in range(output.shape[0]):
            for j in range(output.shape[1]):
                output[i,j,:] = np.sum(paddedImg[i:i+self.__filterLen, j:j+self.__filterLen, :]*filter, axis=(0,1))
        return output.reshape(img.shape)

class Segmentation():
    def __init__(self, k, min_size = 50, gaussian_radius = 1, gaussian_sigma=1.5):
        '''
        Description
        ----------
        基于图的分割

        Parameters
        ----------
        k : int
            修正项常数

        min_size : int
            区域像素最小数量

        gaussian_radius : int
            高斯模糊半径

        gaussian_sigma : float
            高斯模糊$\sigma$值
        '''
        self.k = k
        self.__minSize = min_size
        self.__gaussianRadius = gaussian_radius
        self.__gaussianSigma = gaussian_sigma

    def __getEdgeValue(self, img):
        '''
        获取八连通边的权重值字典
        '''
        blur = MyGaussianBlur(self.__gaussianRadius, self.__gaussianSigma)
        tempImg = blur.smooth(img)

        edgeDict = dict()
        for i in range(img.shape[0]):
            for j in range(img.shape[1]):
                if j<img.shape[1]-1:
                    edgeDict[((i,j),(i,j+1))] = self.__getPixelDiff(tempImg[i,j], tempImg[i,j+1])
                if i<img.shape[0]-1:
                    edgeDict[((i,j),(i+1,j))] = self.__getPixelDiff(tempImg[i,j], tempImg[i+1,j])
                    if j>0:
                        edgeDict[((i,j),(i+1,j))] = self.__getPixelDiff(tempImg[i,j], tempImg[i+1,j-1])
                    if j<img.shape[1]-1:
                        edgeDict[((i,j),(i+1,j+1))] = self.__getPixelDiff(tempImg[i,j], tempImg[i+1,j+1])
        return edgeDict

    def __getPixelDiff(self, pixel1, pixel2):
        '''
        计算两个像素的不相似度
        '''
        return np.sqrt(np.sum((pixel2-pixel1)**2))

    def getCluster(self, img):
        '''
        Description
        ----------
        获取图像的图分割

        Parameters
        ----------
        img : ndarray (height, width, 3)
            RGB像素矩阵

        Returns
        ----------
        clusterIndexMap : ndarray (height, width)
            分割结果矩阵，clusterIndexMap[i,j]是像素(i,j)所属区域的id

        clusterIdList: list(int)
            区域id列表
        '''
        edgeDict = self.__getEdgeValue(img)
        clusterIndexMap = np.ones((img.shape[0],img.shape[1]),dtype=int)*-1# 标号矩阵
        clusterDict = dict() # 存储各个区域的信息
        clusterId = 1
        # 初始情况下每个像素就是一个区域
        for i in range(img.shape[0]):
            for j in range(img.shape[1]):
                clusterDict[clusterId] = dict()
                clusterDict[clusterId]['list'] = [(i,j)] # 区域像素坐标列表
                clusterDict[clusterId]['diff'] = self.k/len(clusterDict[clusterId]['list']) # 类内差异
                clusterIndexMap[i,j] = clusterId
                clusterId += 1
        # 排序
        edgeSortList = sorted(edgeDict.items(), key = lambda ed:(ed[1],ed[0]))

        # 合并
        for ((pixelInx1,pixelInx2),edgeValue) in edgeSortList:
            # 获取所属类标号
            clusterId1 = clusterIndexMap[pixelInx1]
            clusterId2 = clusterIndexMap[pixelInx2]
            if clusterId1==clusterId2:
                continue
            if edgeValue>min(clusterDict[clusterId1]['diff'], clusterDict[clusterId2]['diff']):
                continue
            # 合并两个区域
            clusterDict[clusterId1]['list'].extend(clusterDict[clusterId2]['list'])
            num = len(clusterDict[clusterId1]['list'])
            clusterDict[clusterId1]['diff'] = edgeValue + self.k/num
            clusterDict.pop(clusterId2)
            clusterIndexMap[clusterIndexMap==clusterId2] = clusterId1
        # 合并过小的区域
        for ((pixelInx1,pixelInx2),edgeValue) in edgeSortList:
            clusterId1 = clusterIndexMap[pixelInx1]
            clusterId2 = clusterIndexMap[pixelInx2]
            if clusterId1==clusterId2:
                continue
            if len(clusterDict[clusterId1]['list'])>=self.__minSize and len(clusterDict[clusterId2]['list'])>=self.__minSize:
                continue
            clusterDict[clusterId1]['list'].extend(clusterDict[clusterId2]['list'])
            num = len(clusterDict[clusterId1]['list'])
            clusterDict[clusterId1]['diff'] = edgeValue + self.k/num
            clusterDict.pop(clusterId2)
            clusterIndexMap[clusterIndexMap==clusterId2] = clusterId1

        return clusterIndexMap, list(clusterDict.keys())

    def getColorImg(self, img, clusterIndexMap, clusterIndexList):
        '''
        获取标记分割的图像，不同区域用不同颜色表示
        '''
        newImgArray = img.copy()
        colorList = list()
        for i in clusterIndexList:
            color = np.random.randint(256,size=(3))
            colorList.append(color)
            newImgArray[clusterIndexMap==i] = color
        return newImgArray

    def getSuperPixelImg(self, img, clusterIndexMap, clusterIndexList):
        '''
        获取标记分割的图像，不同区域用红色边包围
        '''
        newImgArray = img.copy()
        for i in range(img.shape[0]):
            for j in range(img.shape[1]):
                left = max(j-1,0)
                right = min(img.shape[1]-1,j+1)
                top = max(0, i-1)
                bottom = min(i+1, img.shape[0]-1)
                if np.sum((clusterIndexMap[top:bottom+1,left:right+1]!=clusterIndexMap[i,j]).astype(int))>0:
                    newImgArray[i,j,:] = np.array([255,0,0])

        return newImgArray

    def getMaskedImg(self, img, mask, clusterIndexMap, clusterIndexList):
        '''
        获取img新的mask
        '''
        newMask = mask.copy()
        newMask[mask>0] = 1
        newImgArray = np.zeros_like(img,dtype=int)
        labelList = list()# 不同区域的标签
        for i in clusterIndexList:
            num = np.sum((clusterIndexMap==i).astype(int))
            if num/2<=np.sum(newMask[clusterIndexMap==i])/3:
                # 属于前景
                newImgArray[clusterIndexMap==i] = 255
                labelList.append(1)
            else:
                # 属于背景
                labelList.append(0)
        return newImgArray, labelList

    def calcIoU(self, img, mask, clusterIndexMap, clusterIndexList):
        '''
        计算IoU值
        '''
        newMask,_ = self.getMaskedImg(img, mask, clusterIndexMap, clusterIndexList)
        R1 = newMask[:,:,0]
        R2 = mask[:,:,0].copy()
        R1[R1>0] = 1
        R2[R2>0] = 1
        intersection = np.sum(R1*R2)
        union = np.sum(R1+R2)-intersection
        return intersection/union

def main():
    imgList = list()
    maskList = list()
    usedIdList = list()
    IoUList = list()
    id = 13
    while id<MAX_NUM:
        usedIdList.append(id)
        id += 100
    for id in usedIdList:
        img = Image.open('imgs/{}.png'.format(id))
        imgList.append(np.asarray(img))
        img = Image.open('gt/{}.png'.format(id))
        maskList.append(np.asarray(img))

    model = Segmentation(k=200, gaussian_radius=1, gaussian_sigma=0.8)
    for i in range(len(usedIdList)):
        model.k = 150
        clusterIndexMap, clusterIndexList = model.getCluster(imgList[i])
        while len(clusterIndexList)<50 or len(clusterIndexList)>70:
            if len(clusterIndexList)<50:
                model.k = int(model.k*0.8)
                if model.k<=0:
                    break
            else:
                model.k = int(model.k*1.2)
                if model.k>=1000:
                    break
            clusterIndexMap, clusterIndexList = model.getCluster(imgList[i])
        newMask,_ = model.getMaskedImg(imgList[i], maskList[i], clusterIndexMap, clusterIndexList)
        Image.fromarray(np.uint8(newMask)).save('new_gt/{}_new_mask.png'.format(usedIdList[i]))
        newImg = model.getSuperPixelImg(imgList[i], clusterIndexMap, clusterIndexList)
        Image.fromarray(np.uint8(newImg)).save('new_imgs/{}_segmentation.png'.format(usedIdList[i]))
        IoUList.append(model.calcIoU(imgList[i], maskList[i], clusterIndexMap, clusterIndexList))
        print("#{} IoU:{}".format(usedIdList[i], IoUList[i]))

    print("average IoU: {}".format(np.sum(np.array(IoUList))/len(IoUList)))

if __name__=='__main__':
    main()


'''
Utility functions for the application
'''
from datetime import datetime
from functools import wraps

from flask import redirect, request, session, url_for

from app.models import DesignatedDriver as DD
from app.models import Event, db
from twilio.rest import Client

def get_all_entries(drivers=True):
    """
    @purpose: Get a list of json objects for the given entires
    @args:  The table that should be queried
    @returns:   A list of the entries in question as JSON objects
    """
    if drivers:
        drivers = []
        for result in DD.query.all():
            driver = {"name": None, "phone": None}
            driver['name'] = result._driver_name
            driver['number'] = result._driver_phone
            drivers.append(driver)
        return drivers
    else:
        events = []
        for result in Event.query.all():
            local_event = {"name": None, "start_time": None, "end_time": None}
            local_event['name'] = result._name
            datetime_object = datetime.strptime(result._start_time,
                                                '%m/%d/%Y %I:%M %p')
            local_event['start_time'] = datetime_object
            datetime_object = datetime.strptime(result._end_time,
                                                '%m/%d/%Y %I:%M %p')
            local_event['end_time'] = datetime_object
            local_event['id'] = result._event_id
            events.append(local_event)
        return events

def add_entry_to_db(entry, is_event=True):
    """
    @purpose:   Adds an entry to the database
    @args:  The entry as a dictionary, a bool to tell if it is an event
    @return:    True / False based on the commit to the database
    """
    if is_event:
        try:
            entry_id = len(Event.query.all())
            if entry_id == 0:
                entry_id = 1
            else:
                entry_id += 1
            new_event = Event(entry['event_name'], entry['start_time'],
                              entry['end_time'], entry_id)
            db.session.add(new_event)
            db.session.commit()
            return entry_id
        except:
            return 0
    else:
        try:
            new_driver = DD(entry['name'], entry['pwd'], entry['phone'])
            db.session.add(new_driver)
            db.session.commit()
            return len(new_driver)
        except:
            return 0

def add_driver_to_event(driver_phone, event_id):
    """
    @purpose:   Links a driver to an event
    @args:  Driver's phone number, the id of the event
    @return:    True / False based on the update to the database
    """
    try:
        driver = DD.query.filter_by(_driver_phone=driver_phone).first()
        driver._driver_curr_event = event_id
        db.session.commit()
        return True
    except:
        return False

def change_driver_state(driver_phone):
    """
    @purpose: Changes the state of the driver's availability
    @args: Driver's phone number
    @returns: True / False based on if the commit went well
    """
    try:
        driver = DD.query.filter_by(_driver_phone=driver_phone).first()
        driver._driver_is_available = not (driver._driver_is_available)
        db.session.commit()
        return True
    except:
        return True

def get_driver(driver_phone):
    """
    @purpose: Changes the state of the driver's availability
    @args: Driver's phone number
    @returns: True / False based on if the commit went well
    """
    try:
        result = DD.query.filter_by(_driver_phone=driver_phone).first()
        driver = {"name": None, "phone": None}
        driver['name'] = result._driver_name
        driver['number'] = result._driver_phone
        driver['available'] = result._driver_is_available

        return driver
    except:
        return None

def get_event_drivers(event_id):
    """
    @purpose: Gets a list of all the drivers that are associated with an event
    @args: The id of the event
    @return: A list of the drivers in a JSON format
    """
    drivers = []
    for result in DD.query.filter_by(_driver_curr_event=event_id).all():
        driver = {"name": None, "phone": None, "available": None}
        driver['name'] = result._driver_name
        driver['phone'] = result._driver_phone
        driver['available'] = result._driver_is_available
        drivers.append(driver)
    return drivers

def auth_user(phone, pwd):
    """
    @purpose: Authenticate a user with their phone and their password.
    @args: The user's username. The password.
    @return: True or false if the user is validated
    """
    result = DD.query.filter_by(_driver_phone=phone).first()
    if result is not None and result._driver_password == pwd:
        return True
    else:
        return False
    return False

def login_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if not session.get('phone_num'):
            return redirect(url_for('login', next=request.url))
        return f(*args, **kwargs)

    return decorated_function

def call(num):
    account_sid = ''  # Removed and key deleted
    auth_token = ''  # Removed and key deleted

    twiml_link = ''
    twilio_number = ''

    if account_sid and auth_token and twiml_link and twilio_number:
        client = Client(account_sid, auth_token)
        call = client.calls.create(url=twiml_link, to=num, from_=twilio_number)


import numpy as np
import xgboost as xgb

dtrain=xgb.DMatrix(r'C:\Users\mashiji\Desktop\agaricus.txt.train')
dtest=xgb.DMatrix(r'C:\Users\mashiji\Desktop\agaricus.txt.test')
watchlist=[(dtest,'eval'),(dtrain,'train')]

param={'max_depth':2,'eta':1,'silent':1,'objective':'binary:logistic'}
bst=xgb.train(param,dtrain,1,watchlist)
ptrain=bst.predict(dtrain,output_margin=True)
ptest=bst.predict(dtest,output_margin=True)
dtrain.set_base_margin(ptrain)
dtest.set_base_margin(ptest)

import xgboost as xgb
dtrain=xgb.DMatrix(r'C:\Users\mashiji\Desktop\agaricus.txt.train')
dtest=xgb.DMatrix(r'C:\Users\mashiji\Desktop\agaricus.txt.test')
param=[('max_depth',2),('objective','binary:logistic'),('eval_metric','logloss'),('eval_metric','error')]
num_round=2
watchlist=[(dtest,'eval'),(dtrain,'train')]

evals_result = {}
bst = xgb.train(param, dtrain, num_round, watchlist, evals_result=evals_result)
print('Access logloss metric directly from evals_result:')
print(evals_result['eval']['logloss'])

print('')
print('Access metrics through a loop:')
for e_name, e_mtrs in evals_result.items():
    print('- {}'.format(e_name))
    for e_mtr_name, e_mtr_vals in e_mtrs.items():
        print('   - {}'.format(e_mtr_name))
        print('      - {}'.format(e_mtr_vals))

print('')
print('Access complete dictionary:')
print(evals_result)


'''
'''

import os
import codecs
from types import SimpleNamespace
import numpy as np
import tensorflow as tf
from datetime import datetime
import time
import random
import pyemblib
import configlogger
from drgriffis.common import log
import dataset
import cross_validation
from model import CNNParams, CNNModel

def trainModel(session, model, train, dev, test, embeds,
        batch_size=5, patience=3, early_stopping=0., max_epochs=-1, fold=None,
        preds_file=None, verbose=False, debug=False):

    epoch, best_epoch = 0, -1
    epoch_dev_metrics, current_best = [], 1e9
    training = True
    patience_so_far = 0

    log.writeln('Starting training')
    while training:
        epoch += 1
        batch = 1
        log.writeln('\n== Epoch %d ==\n\n  Training...' % epoch)

        np.random.shuffle(train)

        correct, total = 0., 0
        batch_start = 0
        n_batches = int(np.ceil(len(train) / batch_size))

        if not verbose:
            log.track(message='  >> Processed {0:,}/%s batches' % ('{0:,}'.format(n_batches)), writeInterval=10)

        while (batch_start < len(train)):
            if debug:
                sys.stderr.write('------------------------------\nTRAINING\n')
                sys.stderr.flush()

            next_batch_samples = train[batch_start:batch_start + batch_size]
            next_batch = np.array([
                [
                    embeds[src],
                    embeds[snk]
                ]
                    for (_, src, snk, _) in next_batch_samples
            ])
            batch_labels = np.array([
                lbl for (_, _, _, lbl) in next_batch_samples
            ])

            batch_loss = model.trainStep(
                next_batch,
                batch_labels
            )

            if verbose:
                log.writeln('    Batch {0:,}/{1:,} loss -- {2:.8f}'.format(batch, n_batches, batch_loss))
            else:
                log.tick()

            batch += 1
            batch_start += len(next_batch)

        if not verbose:
            log.flushTracker()

        log.writeln('\n  Training complete.\n  Evaluating on dev...')
        dev_metrics = testModel(
            session,
            model,
            dev,
            embeds,
            batch_size=batch_size,
            preds_file=None,
            training=True,
        )
        log.writeln('    Dev loss -- %f (Best: %f) [Accuracy: %f (%d/%d)]' % (
            dev_metrics.loss, current_best, dev_metrics.accuracy, dev_metrics.correct, dev_metrics.total
        ))

        epoch_dev_metrics.append(dev_metrics)

        # patience/early stopping handling
        if dev_metrics.loss < (current_best - early_stopping):
            patience_so_far = 0
        else:
            patience_so_far += 1
            log.writeln('    >>> Impatience building... (%d/%d) <<<' % (patience_so_far, patience))
            if patience_so_far >= patience:
                log.writeln("    >>> Ran out of patience! <<<")
                log.writeln("           (╯'-')╯︵ ┻━┻ ")
                break

        if dev_metrics.loss < current_best:
            log.writeln('    >>> Improvement! Saving model state. <<<')
            model.save(fold)
            current_best = dev_metrics.loss
            best_epoch = epoch

        if (max_epochs > 0) and epoch >= max_epochs:
            log.writeln("    >>> Hit maximum epoch threshold! <<<")
            log.writeln("                 ¯\(°_o)/¯")
            break

    log.writeln('\nTraining halted.')

    model.restore(fold)

    log.writeln('\nEvaluating best model on train:')
    train_metrics = testModel(
        session,
        model,
        train,
        embeds,
        batch_size=batch_size,
        preds_file=None,
        training=True
    )
    log.writeln('  Accuracy: %f (%d/%d)' % (train_metrics.accuracy, train_metrics.correct, train_metrics.total))

    log.writeln('\nEvaluating best model on test:')
    test_metrics = testModel(
        session,
        model,
        test,
        embeds,
        batch_size=batch_size,
        preds_file=preds_file,
        training=True
    )
    log.writeln('  Accuracy: %f (%d/%d)' % (test_metrics.accuracy, test_metrics.correct, test_metrics.total))

    return best_epoch, epoch_dev_metrics, test_metrics, train_metrics

def testModel(session, model, eval_data, embeds,
        batch_size=5, preds_file=None, training=False,
        debug=False, verbose=False):
    metrics = SimpleNamespace()
    metrics.loss = 0.
    metrics.correct = 0
    metrics.total = 0

    metrics.per_class = {
        dataset.Hypernym: SimpleNamespace(
            tp = 0,
            fp = 0,
            fn = 0
        ),
        dataset.Hyponym: SimpleNamespace(
            tp = 0,
            fp = 0,
            fn = 0
        ),
        dataset.Meronym: SimpleNamespace(
            tp = 0,
            fp = 0,
            fn = 0
        ),
        dataset.Holonym: SimpleNamespace(
            tp = 0,
            fp = 0,
            fn = 0
        )
    }

    batch_start = 0

    while (batch_start < len(eval_data)):
        if debug:
            sys.stderr.write('------------------------------\nTESTING\n')
            sys.stderr.flush()

        next_batch_samples = eval_data[batch_start:batch_start + batch_size]
        next_batch = np.array([
            [
                embeds[src],
                embeds[snk]
            ]
                for (_, src, snk, _) in next_batch_samples
        ])
        batch_labels = np.array([
            lbl for (_, _, _, lbl) in next_batch_samples
        ])

        batch_results = model.getPredictions(
            next_batch,
            batch_labels
        )

        if debug:
            sys.stderr.write('BATCH RESULT: %s\n' % (str(batch_results)))
            sys.stderr.flush()
        (loss, preds, scores) = batch_results
        if str(loss) == 'nan' or str(loss) == 'inf':
            sys.stdout.write('HEY I FOUND ONE\n')
            sys.stdout.flush()
        metrics.loss += np.sum(loss)

        for i in range(len(next_batch)):
            correct_prediction = False

            #found_nan = False
            #for j in range(len(mention.candidates)):
            #    if np.isnan(scores[i][j]):
            #        log.writeln('[WARNING] Found NaN in predicted scores, skipping (Mention ID: %s)' % str(mention.ID))
            #        found_nan = True
            #        break
            #if found_nan:
            #    continue

            # track sample status
            if preds[i] == batch_labels[i]:
                metrics.correct += 1
                metrics.per_class[batch_labels[i]].tp += 1
                correct_prediction = True
            else:
                metrics.per_class[preds[i]].fp += 1
                metrics.per_class[batch_labels[i]].fn += 1
            metrics.total += 1

            # predictions + scores
            if preds_file:
                preds_file.write('Sample %d -- Scores [ %s ] -- Predicted: %d  Gold: %d\n' % (
                    eval_data[batch_start+i][0],
                    ' '.join([str(f) for f in scores[i]]),
                    preds[i],
                    eval_data[batch_start+i][-1]
                ))

        batch_start += len(next_batch)

    if metrics.total > 0:
        metrics.accuracy = float(metrics.correct)/metrics.total
        macro_f1s = []
        for (cls, cls_metrics) in metrics.per_class.items():

            if (cls_metrics.tp + cls_metrics.fp) > 0:
                cls_metrics.precision = (
                    float(cls_metrics.tp) /
                    (cls_metrics.tp + cls_metrics.fp)
                )
            else:
                cls_metrics.precision = 0

            if (cls_metrics.tp + cls_metrics.fn) > 0:
                cls_metrics.recall = (
                    float(cls_metrics.tp) /
                    (cls_metrics.tp + cls_metrics.fn)
                )
            else:
                cls_metrics.recall = 0

            if (cls_metrics.precision + cls_metrics.recall) > 0:
                cls_metrics.f1 = (
                    (2 * cls_metrics.precision * cls_metrics.recall) /
                    (cls_metrics.precision + cls_metrics.recall)
                )
            else:
                cls_metrics.f1 = 0

            macro_f1s.append(cls_metrics.f1)
        metrics.macro_f1 = np.mean(macro_f1s)
    else:
        metrics.accuracy = 0
        metrics.macro_f1 = 0

    return metrics

def preprocess(ds, embeddings, options):
    preprocessed = SimpleNamespace()

    preprocessed.samples = ds
    preprocessed.embeddings = embeddings

    preprocessed.samples_by_id = {
        s[0] : s
            for s in preprocessed.samples
    }
    preprocessed.labels_by_id = {
        s[0] : s[-1]
            for s in preprocessed.samples
    }

    preprocessed.splits = cross_validation.crossValidationSplits(
        preprocessed.labels_by_id,
        n_folds=options.n_folds,
        dev_size=options.dev_size,
        persistent_path=options.cross_validation_file,
        random_seed=options.random_seed,
        log=log
    )

    return preprocessed

def runCrossValidationExperiment(preprocessed, options, preds_file):
    params = CNNParams(
        embedding_dim = preprocessed.embeddings.size,
        fully_connected_dim = options.fully_connected_dim,
        num_classes = len(dataset.Classes),
        num_filters = options.num_filters,
        filter_width = options.filter_width,
        filter_vstride = options.filter_vstride,
        filter_hstride = options.filter_hstride,
        pool_width = options.pool_width,
        pool_hstride = options.pool_hstride
    )

    train_metrics, test_metrics, best_dev_metrics, best_epochs = [], [], [], []
    if options.dev_results_file:
        options.dev_results_file = open(options.dev_results_file, 'w')

    for i in range(len(preprocessed.splits)):
        log.writeln(('\n\n{0}\n  Starting fold %d/%d\n{0}\n'.format('#'*80)) % (i+1, len(preprocessed.splits)))

        np.random.seed(options.random_seed + i)
        tf.set_random_seed(options.random_seed + i)
        tf.reset_default_graph()

        with tf.Session() as session:
            cnn = CNNModel(
                session,
                params,
                checkpoint_path=options.checkpoint_path
            )

            (train_ids, dev_ids, test_ids) = preprocessed.splits[i]
            train, dev, test = [], [], []
            for _id in train_ids:
                if _id in preprocessed.samples_by_id:
                    train.append(preprocessed.samples_by_id[_id])
            for _id in dev_ids:
                if _id in preprocessed.samples_by_id:
                    dev.append(preprocessed.samples_by_id[_id])
            for _id in test_ids:
                if _id in preprocessed.samples_by_id:
                    test.append(preprocessed.samples_by_id[_id])

            best_epoch, fold_dev_metrics, fold_test_metrics, fold_train_metrics = trainModel(
                session,
                cnn,
                train,
                dev,
                test,
                preprocessed.embeddings,
                batch_size=options.batch_size,
                patience=options.patience,
                early_stopping=options.early_stopping,
                max_epochs=options.max_epochs,
                fold=i,
                preds_file=preds_file
            )

            if options.dev_results_file:
                options.dev_results_file.write('%d\tTotalLoss\t%s\n' % (i, ','.join([str(m.loss) for m in fold_dev_metrics])))
                options.dev_results_file.write('%s\tAccuracies\t%s\n' % (i, ','.join([str(m.accuracy) for m in fold_dev_metrics])))

            train_metrics.append(fold_train_metrics)
            test_metrics.append(fold_test_metrics)
            best_dev_metrics.append(fold_dev_metrics[best_epoch - 1])  # epoch starts at 1, fold_dev_metrics at 0
            best_epochs.append(best_epoch)

            del(cnn)

    for (lbl, metric_set) in [('train', train_metrics), ('dev', best_dev_metrics), ('test', test_metrics)]:
        log.writeln('\n\n-- Cross-validation report (%s) --\n' % lbl)
        log.writeln('Accuracy/# epochs to convergence per fold:')
        for i in range(len(metric_set)):
            m = metric_set[i]
            log.writeln('  Fold %d -- Accuracy: %f (%d/%d) [%d epochs]' % (i+1, m.accuracy, m.correct, m.total, best_epochs[i]))

        log.writeln('\nOverall cross-validation accuracy (%s): %f' % (lbl, np.mean([m.accuracy for m in metric_set])))

    if options.dev_results_file:
        options.dev_results_file.close()

if __name__ == '__main__':
    def _cli():
        import optparse
        parser = optparse.OptionParser(usage='Usage: %prog DATASET')
        parser.add_option('--embeddings', dest='embedding_f',
                help='(REQUIRED) input embedding file')
        parser.add_option('--batch-size', dest='batch_size',
                help='batch size for execution (default: %default)',
                type='int', default=5)
        parser.add_option('--n-fold', dest='n_folds',
                type='int', default=10,
                help='number of folds for cross validation (default: %default)')
        parser.add_option('--dev-size', dest='dev_size',
                type='float', default=0.1,
                help='portion of cross-validation training data to hold back for development'
                     ' (default %default; must be >0 and <1)')
        parser.add_option('--cross-validation-splits', dest='cross_validation_file',
                help='path to save cross-validation splits to (generates multiple files; optional)')
        parser.add_option('--patience', dest='patience',
                type='int', default=3,
                help='number of epochs to wait for improvement before halting;'
                     ' if set to 0, halts as soon as dev performance stops improving'
                     ' (default: %default)')
        parser.add_option('--early-stopping', dest='early_stopping',
                type='float', default=1e-5,
                help='threshold for determining when dev performance has stopped improving'
                     ' (default: %default)')
        parser.add_option('--max-epochs', dest='max_epochs',
                type='int', default=1000,
                help='maximum number of epochs to train (default %default; -1 for no limit)')
        parser.add_option('--checkpoint-file', dest='checkpoint_path',
                default='/tmp/model.ckpt',
                help='path to checkpoint file for saving model during training (default: %default)')
        parser.add_option('--random-seed', dest='random_seed',
                type='int', default=-1,
                help='random seed for reproducibility (defaults to epoch time)')
        parser.add_option('--predictions', dest='predictions_file',
                help='file to write predicted scores to')
        parser.add_option('--dev-results', dest='dev_results_file',
                help='file to write dev results to')

        group = optparse.OptionGroup(parser, 'CNN settings')
        group.add_option('--fully-connected-dim', dest='fully_connected_dim',
                type='int', default=800,
                help='dimension for fully connected layer')
        group.add_option('--num-filters', dest='num_filters',
                type='int', default=100,
                help='number of convolutional filters')
        group.add_option('--filter-width', dest='filter_width',
                type='int', default=2,
                help='width of convolutional filters (default %default)')
        group.add_option('--filter-vstride', dest='filter_vstride',
                type='int', default=1,
                help='vertical stride of convolutional filters (must be <= 2; default %deffault)')
        group.add_option('--filter-hstride', dest='filter_hstride',
                type='int', default=1,
                help='horizontal stride of convolutional filters (default %default)')
        group.add_option('--pool-width', dest='pool_width',
                type='int', default=2,
                help='max pooling width (default %default)')
        group.add_option('--pool-hstride', dest='pool_hstride',
                type='int', default=2,
                help='max pooling horizontal stride (default %default)')

        parser.add_option('-l', '--logfile', dest='logfile',
                help='name of file to write log contents to (empty for stdout)',
                default=None)
        (options, args) = parser.parse_args()

        # guarantee no overlap of model checkpoint files in concurrent experiments
        # note this does NOT use options.random_seed intentionally; does not affect
        # reproducibility, just means that model files won't overwrite one another
        random_checkpoint_identifier = random.randint(0, 100000)
        if options.checkpoint_path:
            options.checkpoint_path = '%s_%d' % (options.checkpoint_path, random_checkpoint_identifier)

        if not options.predictions_file:
            options.predictions_file = '%s.predictions' % os.path.splitext(options.logfile)[0]
        if not options.dev_results_file:
            options.dev_results_file = '%s.dev_results' % os.path.splitext(options.logfile)[0]

        now_stamp = datetime.strftime(datetime.now(), '%Y-%m-%d_%H-%M-%S')
        if options.logfile:
            options.logfile = '%s.%s' % (options.logfile, now_stamp)
        if options.predictions_file:
            options.predictions_file = '%s.%s' % (options.predictions_file, now_stamp)
        if options.dev_results_file:
            options.dev_results_file = '%s.%s' % (options.dev_results_file, now_stamp)
        if options.checkpoint_path:
            options.checkpoint_path = '%s.%s' % (options.checkpoint_path, now_stamp)

        if options.random_seed < 0:
            options.random_seed = int(time.time())

        if (
            len(args) != 1
            or (not options.embedding_f)
        ):
            parser.print_help()
            exit()
        return args, options

    (dataset_f,), options = _cli()
    log.start(logfile=options.logfile)
    configlogger.writeConfig(log, [
        ('Dataset file', dataset_f),
        ('Word embeddings', options.embedding_f),
        ('Batch size', options.batch_size),
        ('CNN settings', [
            ('# convolutional filters', options.num_filters),
            ('Filter width', options.filter_width),
            ('Filter v-stride', options.filter_vstride),
            ('Filter h-stride', options.filter_hstride),
            ('Pooling width', options.pool_width),
            ('Pooling h-stride', options.pool_hstride),
            ('Fully connected dimension', options.fully_connected_dim),
        ]),
        ('Training settings', [
            ('Patience', options.patience),
            ('Early stopping criterion', options.early_stopping),
            ('Max training epochs', options.max_epochs),
            ('Checkpoint file', options.checkpoint_path),
            ('Cross validation splits file', options.cross_validation_file),
            ('Number of folds', options.n_folds),
            ('Fraction of training used for dev', options.dev_size),
            ('Writing predictions to', options.predictions_file),
            ('Writing dev results to', options.dev_results_file),
            ('Random seed', options.random_seed),
        ]),
    ], 'WordNet classification experiment')

    t_sub = log.startTimer('Reading word embeddings from %s...' % options.embedding_f)
    embeddings = pyemblib.read(options.embedding_f)
    log.stopTimer(t_sub, message='Read {0:,} embeddings ({1}s).\n'.format(
        len(embeddings), '{0:.2f}'
    ))

    log.writeln('Reading dataset from %s...' % dataset_f)
    ds = dataset.load(dataset_f)
    log.writeln('Read {0:,} samples.\n'.format(len(ds)))

    preprocessed = preprocess(ds, embeddings, options)

    if options.predictions_file:
        preds_stream = codecs.open(options.predictions_file, 'w', 'utf-8')

    runCrossValidationExperiment(
        preprocessed,
        options,
        preds_stream
    )

    if options.predictions_file:
        preds_stream.close()

    log.stop()


#!/usr/bin/env python

import __builtin__
import logging
import mock
import sys

level = logging.INFO
# level = logging.DEBUG
logging.basicConfig(level=level)
logger = logging.getLogger(__name__)

orig_open = __builtin__.open

def setup(**kwargs):
    install_requires = kwargs.get('install_requires')
    logger.debug('install_requires = %r' % install_requires)

    for req in install_requires:
        if '==' in req:
            sys.stderr.write(
                'WARNING: exact pin: %r\n' % req)

def open(name, **kwargs):
    logger.debug('open: %s', name)

    if 'requirements' in name:
        sys.stderr.write(
            'WARNING: reads %r - looks like a requirements file?\n'
            % name)
        sys.stderr.write(
            '  You might want to look at '
            'https://caremad.io/2013/07/setup-vs-requirement/\n')

    return orig_open(name, **kwargs)

def setuppycheck(argv=None):
    if argv is None:
        argv = sys.argv[1:]

    for setuppy in argv:
        with mock.patch('setuptools.setup', side_effect=setup):
            with mock.patch('__builtin__.open', side_effect=open):
                execfile(setuppy, globals())

if __name__ == '__main__':
    setuppycheck()


from transformers import BertTokenizer, BertForSequenceClassification
from transformers import AutoTokenizer, AutoModelForSequenceClassification
from transformers import pipeline
from sklearn import preprocessing
import torch
class classify():
    '''
    This function contanins all the classifiers used in the sentiment analysis pipeline
    bert_classifier = The FinBERT classifier lablled BERT1 in the accompanying analysis
    bert_classifier_2 = The FinBERT classifier lablled BERT2 in the accompanying analysis
    roberta_classifier = The RoBERTa classifier lablled RoBERTa in the accompanying analysis

    This function applies the specified classifier on text data
    This is used to classify the text data obtained after the pre-processing steps labelled 'text_clean'
    '''
    def bert_classifier(self, text):
        '''
        More details about the classifier are available at: https://huggingface.co/yiyanghkust/finbert-tone
        '''
        finbert = BertForSequenceClassification.from_pretrained('yiyanghkust/finbert-tone',num_labels=3, from_tf=True)
        tokenizer = BertTokenizer.from_pretrained('yiyanghkust/finbert-tone')
        nlp = pipeline("sentiment-analysis", model=finbert, tokenizer=tokenizer)

        sentences = text
        results = nlp(sentences)
        return results

    def bert_classifier_2(self, text):
        '''
        More details about the classifier are available at: https://huggingface.co/ProsusAI/finbert
        '''
        tokenizer = AutoTokenizer.from_pretrained("ProsusAI/finbert")
        model = AutoModelForSequenceClassification.from_pretrained("ProsusAI/finbert")

        inputs = tokenizer(text, padding = True, truncation = True, return_tensors='pt')
        outputs = model(**inputs)
        predictions = torch.nn.functional.softmax(outputs.logits, dim=-1)
        return predictions

    def roberta_classifier(self, text):
        '''
        More details about the classifier are available at: https://huggingface.co/mrm8488/distilroberta-finetuned-financial-news-sentiment-analysis
        '''
        tokenizer = AutoTokenizer.from_pretrained("mrm8488/distilroberta-finetuned-financial-news-sentiment-analysis")
        model = AutoModelForSequenceClassification.from_pretrained("mrm8488/distilroberta-finetuned-financial-news-sentiment-analysis")

        inputs = tokenizer(text, padding=True, truncation=True, return_tensors="pt")
        outputs = model(**inputs)
        predictions = outputs.logits.detach().numpy()
        min_max_scaler = preprocessing.MinMaxScaler()
        predictions = min_max_scaler.fit_transform(predictions)
        return predictions


'''
Created on 5 mars 2017

@author: OPBO6311
'''

from root.nested.constantes import Constantes
from copy import deepcopy
import requests
from tkinter import ttk
from tkinter import *
import json

class Replay(object):
    "La fenêtre permettant de rejouer une partie spécifique"
    dimensionx=400
    dimensiony=400
    fenreplay=Constantes.nondefini
    canvas=Constantes.nondefini
    boutonmoins=Constantes.nondefini
    boutonplus=Constantes.nondefini
    progress=Constantes.nondefini
    progresslabel=Constantes.nondefini
    energielabel=Constantes.nondefini
    stockage={}
    timetic=0
    progresstext="0/999"
    energietext="100"

    def __init__(self, entryid):
        "Constructeur de la classe permettant de rejouer une partie spécifique"

        #Aller chercher le json avec lequel on va jouer. Le stocker.
        target='http://127.0.0.1:5000/serverAPI/{0}'.format(entryid)
        r=requests.get(target)
        print("status code:", r.status_code)
        print("response:", r.text)
        parsedjson = json.loads(r.text)
        self.stockage=deepcopy(parsedjson)
        print("replay ", self.stockage)
        self.dimensionx=self.stockage["entry"]["start"]["dimensions"]["x"]
        self.dimensiony=self.stockage["entry"]["start"]["dimensions"]["y"]

        #Créer la fenêtre et l'afficher.
        self.fenreplay=Tk()
        self.fenreplay.title("Replay pour {0}".format(self.stockage["entry"]["entryid"]))

        self.progress = ttk.Progressbar(self.fenreplay, orient="horizontal", length=self.dimensionx-100, mode="determinate")
        self.progress["value"] = 0
        self.progress["maximum"] = self.stockage["entry"]["end"]["survie"]
        self.progress.bind("<Button-1>", self.clicgaucheprogressbar)
        self.progresstext="0/{0}".format(self.progress["maximum"])
        self.progresslabel=Label(self.fenreplay, text= self.progresstext)
        self.progresslabel.grid(row=1, column=0, sticky=E)
        self.boutonmoins = Button(self.fenreplay, text = '<', command = self.clickmoins, repeatdelay=500, repeatinterval=100).grid(row=1, column=1)

        self.boutonpluss = Button(self.fenreplay, text = '>', command = self.clickplus,  repeatdelay=500, repeatinterval=100).grid(row=1, column=3)
        self.progress.grid(row=1, column=2)

        self.canvas = Canvas(self.fenreplay,bg='dark grey',height=self.dimensiony,width=self.dimensionx)
        self.canvas.grid(row=2, columnspan=4, sticky=S)

        self.energie = ttk.Progressbar(self.fenreplay, orient="vertical", length=self.dimensiony, mode="determinate")
        self.energie["value"] = 0
        self.energie["maximum"] = Constantes.cobayeenergiedepart
        self.energie.grid(row=2, column=5, sticky=S)
        self.energietext="{0}".format(self.energie["maximum"])
        self.energielabel=Label(self.fenreplay, text= self.energietext)
        self.energielabel.grid(row=1, column=5, sticky=E)

        self.afficher(0)

    def clickmoins(self):
        "Clic sur le bouton moins-un-tick"
        if (self.timetic>0):
            self.timetic=self.timetic-1
            self.progresstext="{0}/{1}".format(self.timetic,self.progress["maximum"])
            self.progresslabel["text"]=self.progresstext
        self.progress["value"]=self.timetic
        self.afficher(self.timetic)

    def clickplus(self):
        "Clic sur le bouton plus-un-tick"
        if (self.timetic<self.progress["maximum"]):
            self.timetic=self.timetic+1
            self.progresstext="{0}/{1}".format(self.timetic,self.progress["maximum"])
            self.progresslabel["text"]=self.progresstext
        self.progress["value"]=self.timetic
        self.afficher(self.timetic)

    def clicgaucheprogressbar(self, event):
        print ("Clic gauche progressbar en ", event.x, event.y, self.progress["length"])
        self.timetic=int((event.x/(self.progress["length"]-1))*self.progress["maximum"])
        self.progresstext="{0}/{1}".format(self.timetic,self.progress["maximum"])
        self.progresslabel["text"]=self.progresstext
        self.progress["value"]=self.timetic
        self.afficher(self.timetic)

    def afficher(self, tic):
        "Effacer le canvas et construire la configuration du tick"
        self.canvas.delete("all")
        #print("replay all:", self.stockage["entry"]["tours"][tic]["population"])
        liste=self.stockage["entry"]["tours"][tic]["population"]
        for elt in liste:
            #print("Replay elt: {0}, et catégorie: {1} et x: {2}".format(elt, elt["catégorie"], elt["x"]))
            if (elt["catégorie"]=="cobaye"):
                x=elt["x"]
                y=elt["y"]
                energie=elt["energie"]
                if (energie > self.energie["maximum"]):
                    self.energie["maximum"]=energie
                self.energie["value"]=energie
                self.energietext="{0}".format(energie)
                self.energielabel["text"]=self.energietext
                forme = self.canvas.create_oval(x-5, y-5, x+5, y+5, width=2, fill='blue')
            elif (elt["catégorie"]=="prédateur"):
                x=elt["x"]
                y=elt["y"]
                forme = self.canvas.create_oval(x-5, y-5, x+5, y+5, width=2, fill='red')
            elif (elt["catégorie"]=="nourriturefixe"):
                x=elt["x"]
                y=elt["y"]
                forme = self.canvas.create_rectangle(x-5, y-5, x+5, y+5, width=2, fill='green')


import itertools
import logging
import math
import sys

import numpy
import OpenGL

OpenGL.ERROR_ON_COPY = True
from OpenGL.arrays import vbo  # noqa
from OpenGL.GL import *  # noqa
from OpenGL.GLUT import *  # noqa
import OpenGL.GL.shaders as glsl  # noqa

log = logging.getLogger(__name__)

class Renderer(object):
    """
    This class is responsible for rendering the voxels to a window.

    """

    def __init__(self, program, size):
        """
        Creates a renderer using the provided shader program and window size.

        """
        width, height = size
        self._program = program
        self._voxels = []
        self._vbo_voxels = None
        self._frustum = Frustum(width, height, 5000, 25.0)
        self._camera = Camera()
        self._camera.position = numpy.array([0, 0, 5000])
        self._camera.orientation = Quaternion.from_axis_angle(numpy.array([0, 1, 0]), 0)
        self._clear_color = Color(0.3, 0.3, 0.3, 1.0)

        self.resize(width, height)

    @property
    def camera(self):
        """
        The camera that provides the scene view.

        """
        return self._camera

    @property
    def frustum(self):
        """
        The frustum that defines the viewing volume of the camera.

        """
        return self._frustum

    def add_voxel(self, voxel):
        """
        Add a voxel to the renderer.

        """
        # Setting the VBO to None will trigger its re-creation before rendering.
        self._vbo_voxels = None
        self._voxels.append(voxel)

    def add_voxels(self, voxels):
        """
        Adds an iterable of voxels to the renderer.

        """
        self._vbo_voxels = None
        self._voxels.extend(v for v in voxels)

    def resize(self, width, height):
        """
        Sets the dimensions of the viewport and ensure that the frustum matches.

        """
        assert width > 0
        assert height > 0

        glViewport(0, 0, width, height)

        self.frustum.resize((width, height))

    def _render_fiducials(self):
        """
        A debugging function that draws 9 equally-spaced crosses about the
        origin.

        """
        length = 20
        sep = 100

        hues = (c / 10.0 for c in range(1, 10))
        colors = [Color.from_hsv(hue, 0.5, 0.95) for hue in hues]
        centers = [x for x in itertools.product([-sep, 0, sep], repeat=3)]
        for center, color in zip(centers, colors):
            glPushMatrix()
            glTranslate(*center)
            glBegin(GL_LINES)
            glColor3f(color.r, color.g, color.b)
            glVertex3f(+length, 0, 0)
            glVertex3f(-length, 0, 0)
            glVertex3f(0, +length, 0)
            glVertex3f(0, -length, 0)
            glVertex3f(0, 0, +length)
            glVertex3f(0, 0, -length)
            glEnd()
            glPopMatrix()

    def display(self):
        """
        This is the function that performs the actual rendering.

        """
        with glsl.ShaderProgram(self._program.handle):
            try:
                # Initialize the OpenGL state
                glClearColor(*self._clear_color)

                glMatrixMode(GL_MODELVIEW)
                glLoadIdentity()
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

                glEnable(GL_CULL_FACE)
                glEnable(GL_DEPTH_TEST)
                glDepthFunc(GL_LESS)

                # Determine the model-view transform from the camera
                orientation = self.camera.orientation
                axis = orientation.axis()
                angle = orientation.angle()

                glRotatef(-180.0 * angle / math.pi, axis[0], axis[1], axis[2])

                position = self.camera.position
                x = position[0]
                y = position[1]
                z = position[2]

                glTranslate(-x, -y, -z)

                self._program.light_position(0, 0, 5000)

                # Reconstruct the VBO if necessary
                if self._vbo_voxels is None:
                    self._construct_vbo_voxels()

                # Pass all of the data to the hardware
                if self._vbo_voxels is not None:
                    self._vbo_voxels.bind()
                    try:
                        glEnableClientState(GL_VERTEX_ARRAY)
                        glEnableClientState(GL_NORMAL_ARRAY)
                        glEnableClientState(GL_COLOR_ARRAY)
                        glVertexPointer(3, GL_FLOAT, 40, self._vbo_voxels)
                        glNormalPointer(GL_FLOAT, 40, self._vbo_voxels + 12)
                        glColorPointer(4, GL_FLOAT, 40, self._vbo_voxels + 24)
                        glDrawArrays(GL_QUADS, 0, len(self._vbo_voxels))
                    finally:
                        self._vbo_voxels.unbind()
                        glDisableClientState(GL_VERTEX_ARRAY)
                        glDisableClientState(GL_NORMAL_ARRAY)
                        glDisableClientState(GL_COLOR_ARRAY)
            except Exception:
                # @todo need to print out the relevant information and terminate
                # execution.
                raise

        glutSwapBuffers()

    def _construct_vbo_voxels(self):
        """
        Extract the vertices in the voxels and create the VBO.

        """
        if len(self._voxels):
            vertices = numpy.vstack(tuple(v.vertices for v in self._voxels))
            self._vbo_voxels = vbo.VBO(vertices)

class ShaderProgram(object):
    """
    This class encapsulates the shader program and provides some utilities and
    convenience functions for interacting with the shader program.
    """

    def __init__(self):
        """
        Create an instance of ShaderProgram.

        """
        self._vertex_shaders = []
        self._fragment_shaders = []
        self._program = None

    @property
    def vertex_shaders(self):
        """
        This list of vertex shaders associated with this program.

        """
        return self._vertex_shaders

    @property
    def fragment_shaders(self):
        """
        This list of fragment shaders associated with this program.

        """
        return self._fragment_shaders

    @property
    def handle(self):
        """
        Returns the handle/id of the shader program. Ideally we would not be
        exposing this. Consider it deprecated.

        """
        return self._program

    def load_vertex_shader(self, filename):
        """
        Loads and compiles the specified vertex shader.

        """
        self.compile_vertex_shader(open(filename).read())

    def compile_vertex_shader(self, shader):
        """
        Compiles a vertex shader

        """
        try:
            self._vertex_shaders.append(glsl.compileShader(shader, GL_VERTEX_SHADER))
        except RuntimeError as e:
            loc, shader, errcode = e.args
            log.error("%s" % (errcode,))
            log.error("%s" % (loc,))
            for number, line in enumerate(shader[0].split("\r\n")):
                log.error("%d: %s" % (number, line))
            sys.exit(1)

    def load_fragment_shader(self, filename):
        """
        Loads and compiles the specified fragment shader.

        """
        self.compile_fragment_shader(open(filename).read())

    def compile_fragment_shader(self, shader):
        """
        Compiles the specified fragment shader.

        """
        try:
            self._fragment_shaders.append(
                glsl.compileShader(shader, GL_FRAGMENT_SHADER)
            )
        except RuntimeError as e:
            loc, shader, errcode = e.args
            log.error("%s" % (errcode,))
            log.error("%s" % (loc,))
            for number, line in enumerate(shader[0].split("\r\n")):
                log.error("%d: %s" % (number, line))
            sys.exit(1)

    def build(self):
        """
        Compiles and links that shader program. Note that repeated calls to this
        function can be made, but the exiting shader program (known by this
        object) will be destroyed first.

        """
        if self._program is not None:
            glDeleteProgram(self._program)

        # Create the shader program and attach all of the shaders
        self._program = glCreateProgram()

        for shader in self._vertex_shaders:
            glAttachShader(self._program, shader)

        for shader in self._fragment_shaders:
            glAttachShader(self._program, shader)

        # Linking stage
        glLinkProgram(self._program)

        # Check that the program in valid and throw and informative exception if
        # it is not.
        glValidateProgram(self._program)
        if not glGetProgramiv(self._program, GL_VALIDATE_STATUS):
            info = glGetProgramInfoLog(self._program)
            raise RuntimeError("Invalid program: %s" % (info,))

        # Find all of the active uniform variables in the program and bind them
        # to this object. This provides a nice interface for setting the uniform
        # variables.
        num_active_uniforms = glGetProgramiv(self._program, GL_ACTIVE_UNIFORMS)
        for index in range(num_active_uniforms):
            name, _, dtype = glGetActiveUniform(self._program, index)
            location = glGetUniformLocation(self._program, name)

            # @todo support for data types
            if dtype == GL_FLOAT_VEC3:

                def set_uniform_3f(x, y, z):
                    glUniform3f(location, x, y, z)

                setattr(self, name.decode("utf-8"), set_uniform_3f)

class Frustum(object):
    """
    The class represents a frustum and handles the perspective transformation
    for the renderer.

    """

    def __init__(self, height, width, depth, fov):
        """
        Creates a frustum.

        """
        self._height = height
        self._width = width
        self._depth = depth
        self._fov = fov

    @property
    def height(self):
        """
        The height of the frustum in the near plane.

        """
        return self._height

    @property
    def width(self):
        """
        The width of the frustum in the near plane.

        """
        return self._width

    @property
    def depth(self):
        """
        The distance from the near plane to the far plane.

        """
        return self._depth

    @property
    def near(self):
        """
        The distance to the near plane.

        """
        return self.width * math.tan(self.fov * math.pi / 180.0)

    @property
    def far(self):
        """
        The distance to the far plane.

        """
        return self.depth + self.near

    @property
    def fov(self):
        """
        The field of view (degrees).

        """
        return self._fov

    def resize(self, size):
        """
        Resizes the frustum using the provided dimensions.

        """
        self._width, self._height = size

        half_width = self.width / 2.0
        half_height = self.height / 2.0

        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glFrustum(
            -half_width, half_width, -half_height, half_height, self.near, self.far
        )

class Camera(object):
    """
    The camera class is used to define the viewers perspective.
    """

    def __init__(self):
        self._basis = numpy.diag((1.0, 1.0, 1.0))
        self._orientation = Quaternion.from_axis_angle(
            numpy.array([0.0, 1.0, 0.0]), 0.0
        )
        self._position = numpy.array([0, 0, 0], dtype=numpy.float32)

    @property
    def position(self):
        """
        The position of the camera in the world co-ordinates.

        """
        return self._position

    @position.setter
    def position(self, position):
        """
        Sets the position of the camera in world co-ordinates.

        """
        self._position = position.astype(float)

    @property
    def orientation(self):
        """
        The orientation of the camera (quaternion) in world co-ordinates.

        """
        return self._orientation

    @orientation.setter
    def orientation(self, orientation):
        """
        Sets the orientation of the camera (quaternion) in world co-ordinates.

        """
        self._orientation = orientation

    @property
    def up(self):
        """
        The 'up' vector of the camera in world co-ordinates.

        """
        return numpy.array(self._orientation.rotate(self._basis[:, 1]))

    @property
    def down(self):
        """
        The 'down' vector of the camera in world co-ordinates.

        """
        return -self.up

    @property
    def forward(self):
        """
        The 'forward' vector of the camera in world co-ordinates.

        """
        return -numpy.array(self._orientation.rotate(self._basis[:, 2]))

    @property
    def backward(self):
        """
        The 'backward' vector of the camera in world co-ordinates.

        """
        return -self.forward

    @property
    def left(self):
        """
        The 'left' vector of the camera in world co-ordinates.

        """
        return -numpy.array(self._orientation.rotate(self._basis[:, 0]))

    @property
    def right(self):
        """
        The 'right' vector of the camera in world co-ordinates.

        """
        return -self.left

    def pitch(self, angle):
        """
        Rotates the pitch of the camera (radians).

        """
        self._orientation = (
            Quaternion.from_axis_angle(self.right, angle) * self._orientation
        )
        self._orientation.normalize()

    def roll(self, angle):
        """
        Rotates the roll of the camera (radians).

        """
        self._orientation = (
            Quaternion.from_axis_angle(self.forward, angle) * self._orientation
        )
        self._orientation.normalize()

    def yaw(self, angle):
        """
        Rotates the yaw of the camera (radians).

        """
        self._orientation = (
            Quaternion.from_axis_angle(self.up, angle) * self._orientation
        )
        self._orientation.normalize()

    def move_forward(self, distance):
        """
        Move the camera in the forward direction.

        """
        self._position += distance * self.forward

    def move_backward(self, distance):
        """
        Move the camera in the backward direction.

        """
        self._position -= distance * self.forward

    def move_left(self, distance):
        """
        Move the camera in the left direction.

        """
        self._position += distance * self.left

    def move_right(self, distance):
        """
        Move the camera in the right direction.

        """
        self._position -= distance * self.left

    def move_up(self, distance):
        """
        Move the camera in the up direction.

        """
        self._position += distance * self.up

    def move_down(self, distance):
        """
        Move the camera in the down direction.

        """
        self._position -= distance * self.up

class Quaternion(object):
    """
    This class represents a quaternion implemented using numpy arrays.
    """

    def __init__(self, w, x, y, z):
        """
        Creates a quaternion.

        """
        self._data = numpy.array([w, x, y, z], dtype=numpy.float32)

    def __iadd__(self, q):
        """
        Adds a quaternion to this instance. Returns a reference to this
        instance.

        """
        self._data = numpy.add(self._data, q._data)
        return self

    def __isub__(self, q):
        """
        Subtracts a quaternion from this instance. Returns a reference to this
        instance.

        """
        self._data = numpy.subtract(self._data, q._data)
        return self

    def __imul__(self, q):
        """
        Post-multiplies this quaternion by another quaternion and returned a
        reference to this instance.

        """
        # (ur + ui)(vr + vi) = (ur * vr - ui * vi) + ur * vi + vr * ui + ui x vi

        u = self._data
        v = q._data

        r = u[0] * v[0] - numpy.dot(u[1:], v[1:])
        s = u[0] * v[1:] + v[0] * u[1:] + numpy.cross(u[1:], v[1:])

        self._data[0] = r
        self._data[1:] = s

        return self

    def __add__(self, q):
        """
        Adds a quaternion to this quaternion and returns the result.

        """
        r = self.clone()
        r += q
        return r

    def __sub__(self, q):
        """
        Subtracts a quaternion from this quaternion and returns the result.

        """
        r = self.clone()
        r -= q
        return r

    def __mul__(self, q):
        """
        Post-multiplies this quaternion by a another quaternion and results the
        result.

        """
        r = self.clone()
        r *= q
        return r

    def __eq__(self, q):
        """
        Returns True if the provided quaternion is equal to this quaternion.

        """
        return numpy.array_equal(self._data, q._data)

    def __ne__(self, q):
        """
        Returns False if the provided quaternion is equal to this quaternion.

        """
        return not numpy.array_equal(self._data, q._data)

    def __repr__(self):
        return repr((self.w, self.x, self.y, self.z))

    @property
    def w(self):
        """
        The w component of the quaternion.

        """
        return self._data[0]

    @property
    def x(self):
        """
        The x component of the quaternion.

        """
        return self._data[1]

    @property
    def y(self):
        """
        The y component of the quaternion.

        """
        return self._data[2]

    @property
    def z(self):
        """
        The z component of the quaternion.

        """
        return self._data[3]

    @property
    def length(self):
        """
        The length of the quaternion.

        """
        return numpy.linalg.norm(self._data)

    @classmethod
    def from_axis_angle(cls, axis, angle):
        """
        Creates an instance of Quaternion using an axis (unit vector) and an
        angle (radians).

        """
        lensqr = numpy.dot(axis, axis)
        if abs(lensqr - 1.0) > 0.0001:
            axis = axis / math.sqrt(lensqr)

        c = math.cos(angle / 2.0)
        s = math.sin(angle / 2.0)
        return cls(c, s * axis[0], s * axis[1], s * axis[2])

    def clone(self):
        """
        Returns a copy of this quaternion.

        """
        return Quaternion(self.w, self.x, self.y, self.z)

    def conjugate(self):
        """
        Conjugates this quaternion and returns a reference to this instance.

        """
        self._data[1:] = -self._data[1:]
        return self

    def invert(self):
        """
        Inverts this quaternion and returns a reference to this instance.

        """
        self.conjugate()
        self._data = self._data / numpy.dot(self._data, self._data)
        return self

    def normalize(self):
        """
        Normalizes this quaternion and returns a reference to this instance.

        """
        self._data = self._data / self.length
        return self

    def conjugated(self):
        """
        Returns a conjugates copy of this quaternion.

        """
        return self.clone().conjugate()

    def inverted(self):
        """
        Returns an inverted copy of this quaternion.

        """
        return self.clone().invert()

    def normalized(self):
        """
        Returns a normalized copy of this quaternion.

        """
        return self.clone().normalize()

    def angle(self):
        """
        Returns the angle that this quaternion represents (assumes that this is
        a unit quaternion).

        """
        return 2.0 * math.atan2(numpy.linalg.norm(self._data[1:]), self.w)

    def axis(self):
        """
        Returns the axis that this quaternion represents (assumes that this is a
        unit quaternion).

        """
        s2 = abs((1.0 - self.w) * (1.0 + self.w))
        if s2 < 0.000001:
            # When s2 is effectively zero, the angle of the quaternion is
            # approximately zero, so the axis returned is arbitrary.
            x = 0
            y = 0
            z = 1
        else:
            norm = numpy.linalg.norm(self._data[1:])
            x = self.x / norm
            y = self.y / norm
            z = self.z / norm

        return (x, y, z)

    def matrix(self):
        """
        Returns a matrix representation of the quaternion.

        """
        w = self.w
        x = self.x
        y = self.y
        z = self.z

        R = numpy.zeros((3, 3))
        R[0, 0] = 1.0 - 2.0 * (y * y + z * z)
        R[1, 1] = 1.0 - 2.0 * (x * x + z * z)
        R[2, 2] = 1.0 - 2.0 * (x * x + y * y)
        R[0, 1] = 2.0 * (x * y + w * z)
        R[0, 2] = 2.0 * (x * z - w * y)
        R[1, 2] = 2.0 * (y * z + w * x)
        R[1, 0] = 2.0 * (x * y - w * z)
        R[2, 0] = 2.0 * (x * z + w * y)
        R[2, 1] = 2.0 * (y * z - w * x)

        return R

    def rotate(self, point):
        """
        Rotates a vector by this quaternion and returns the result.

        """
        x, y, z = point
        q = self * Quaternion(0, x, y, z) * self.inverted()
        return [float(v) for v in q.axis()]

class Color(object):
    """
    This class represents an RGBA color.
    """

    def __init__(self, r, g, b, a):
        """
        Creates a color.

        """
        self._color = (r, g, b, a)

    @property
    def r(self):
        """
        The red component of the color.

        """
        return self._color[0]

    @property
    def g(self):
        """
        The green component of the color.

        """
        return self._color[1]

    @property
    def b(self):
        """
        The blue component of the color.

        """
        return self._color[2]

    @property
    def a(self):
        """
        The alpha component of the color.

        """
        return self._color[3]

    @r.setter
    def r(self):
        """
        Sets the red component of the color.

        """
        return self._color[0]

    @g.setter
    def g(self):
        """
        Sets the green component of the color.

        """
        return self._color[1]

    @b.setter
    def b(self):
        """
        Sets the blue component of the color.

        """
        return self._color[2]

    @a.setter
    def a(self):
        """
        Sets the alpha component of the color.

        """
        return self._color[3]

    @classmethod
    def from_hsv(cls, h, s, v):
        """
        Creates a color from HSV values.

        """
        hi = int(6 * h)
        f = 6 * h - hi
        p = v * (1 - s)
        q = v * (1 - f * s)
        t = v * (1 - (1 - f) * s)

        if hi == 0:
            r, g, b = v, t, p
        if hi == 1:
            r, g, b = q, v, p
        if hi == 2:
            r, g, b = p, v, t
        if hi == 3:
            r, g, b = p, q, v
        if hi == 4:
            r, g, b = t, p, v
        if hi == 5:
            r, g, b = v, p, q

        return cls(r, g, b, 1.0)

    def __iter__(self):
        return (c for c in self._color)

    def __getitem__(self, i):
        return self._color[i]

    def __setitem__(self, i, v):
        self._color[i] = v

    def __getslice__(self, i, j):
        return self._color[i:j]

    def __setslice__(self, i, j, v):
        self._color[i:j] = v

    def __repr__(self):
        return repr(self._color)

class Voxel(object):
    """
    This is a simple representation of a cubic, volume element that is used in
    rendering.
    """

    OFFSETS = numpy.array(
        [
            [+1, -1, -1, +1, 0, 0, 0, 0, 0, 0],
            [+1, +1, -1, +1, 0, 0, 0, 0, 0, 0],
            [+1, +1, +1, +1, 0, 0, 0, 0, 0, 0],
            [+1, -1, +1, +1, 0, 0, 0, 0, 0, 0],
            [+1, -1, +1, 0, 0, +1, 0, 0, 0, 0],
            [+1, +1, +1, 0, 0, +1, 0, 0, 0, 0],
            [-1, +1, +1, 0, 0, +1, 0, 0, 0, 0],
            [-1, -1, +1, 0, 0, +1, 0, 0, 0, 0],
            [+1, +1, +1, 0, +1, 0, 0, 0, 0, 0],
            [+1, +1, -1, 0, +1, 0, 0, 0, 0, 0],
            [-1, +1, -1, 0, +1, 0, 0, 0, 0, 0],
            [-1, +1, +1, 0, +1, 0, 0, 0, 0, 0],
            [-1, -1, +1, -1, 0, 0, 0, 0, 0, 0],
            [-1, +1, +1, -1, 0, 0, 0, 0, 0, 0],
            [-1, +1, -1, -1, 0, 0, 0, 0, 0, 0],
            [-1, -1, -1, -1, 0, 0, 0, 0, 0, 0],
            [-1, -1, -1, 0, 0, -1, 0, 0, 0, 0],
            [-1, +1, -1, 0, 0, -1, 0, 0, 0, 0],
            [+1, +1, -1, 0, 0, -1, 0, 0, 0, 0],
            [+1, -1, -1, 0, 0, -1, 0, 0, 0, 0],
            [-1, -1, +1, 0, -1, 0, 0, 0, 0, 0],
            [-1, -1, -1, 0, -1, 0, 0, 0, 0, 0],
            [+1, -1, -1, 0, -1, 0, 0, 0, 0, 0],
            [+1, -1, +1, 0, -1, 0, 0, 0, 0, 0],
        ],
        dtype=numpy.float32,
    )

    def __init__(self, x, y, z, hx, hy, hz, r, g, b, a):
        """
        Creates a voxel using (x, y, z) as the center of the voxel, (hx, hy, hz)
        as the half-widths of the voxel is the x, y, and z axis respectively,
        and (r, g, b, a) is a float32 RGBA color.

        """
        scale = numpy.array([hx, hy, hz, 1, 1, 1, 1, 1, 1, 1], dtype=numpy.float32)
        shift = numpy.array([x, y, z, 0, 0, 0, r, g, b, a], dtype=numpy.float32)

        product = numpy.multiply(Voxel.OFFSETS, scale[numpy.newaxis, :])

        self._vertices = numpy.add(product, shift[numpy.newaxis, :])

    @property
    def vertices(self):
        """
        The vertices of the voxel.

        """
        return self._vertices


'''
Reference:
	Samuel Oliveira, Victor Diniz, Anisio Lacerda, and Gisele L Pappa. 2016. Evolu-tionary rank aggregation for recommender systems.
	IEEE Congress on Evolutionary Computation (CEC). IEEE, 255–262.
'''
import torch
from torch import nn
import torch.nn.functional as F
from modules.attention import *
from modules import layers
from models import BaseModel
from utils import utils

class ERA(BaseModel.GeneralShuffleModel):
	reader, runner ="BaseReader", "BaseRunner"
	extra_log_args = ['hidden_sizes']

	@staticmethod
	def parse_model_args(parser):
		parser.add_argument('--window_size',type=int,default=10,help='mAgr Window size.')
		parser.add_argument('--hidden_sizes',type=str,default='16')
		return BaseModel.GeneralShuffleModel.parse_model_args(parser)

	def __init__(self,args,corpus):
		super().__init__(args,corpus)
		self.model_num = args.model_num
		self.window_size = args.window_size
		n_features = 5
		hidden_sizes = [int(x) for x in args.hidden_sizes.split(",")]
		self.hidden_sizes = [n_features]+hidden_sizes
		self.mlp = nn.Sequential()
		for i in range(len(self.hidden_sizes)-1):
			self.mlp.add_module('Linear-%d'%(i),
					nn.Linear(self.hidden_sizes[i],self.hidden_sizes[i+1]))
			self.mlp.add_module('Activate-%d'%(i),nn.ReLU())
		self.mlp.add_module('Linear-%d'%(len(self.hidden_sizes)-1),
					nn.Linear(self.hidden_sizes[-1],1))

	def forward(self, data):
		features = [data['p10'],data['mAgr']]
		for m in range(self.model_num):
			features.append(data['psc_%d'%(m)])
		features = torch.stack(features,dim=2).float()
		ens_scores = self.mlp(features).squeeze()
		return ens_scores

	class Dataset(BaseModel.GeneralShuffleModel.Dataset):

		def __init__(self, model, corpus, phase):
			super().__init__(model,corpus,phase)
			self.window_size = model.window_size

		def _get_feed_dict(self, index):
			feed_dict = super()._get_feed_dict(index)
			all_rankings = []
			for i, key in enumerate(['c_pCTR_s','c_pCVR_s','c_pFVR_s']):
				ranked_idx = np.argsort(feed_dict[key])[::-1]
				rankings = np.argsort(ranked_idx) + 1 # larger score, smaller ranking
				psc = 1- (rankings-1)/len(rankings)
				feed_dict['psc_%d'%(i)] = psc
				all_rankings.append(rankings)
			all_rankings = np.array(all_rankings)
			feed_dict['p10'] = (all_rankings<=10).sum(axis=0)
			feed_dict['mAgr'] = 1/2 * (np.abs(all_rankings[1]-all_rankings[0])<=self.window_size)

			return feed_dict


from score.IoV_state import IoVSendMessage
import random
import uuid

# 读取位置信息，生成广播消息
def file_location(files):
    gen = []
    with open(files, 'r') as f:
        locations = f.readlines()
    for i in range(0, len(locations)):
        locations[i] = locations[i].rstrip('\n')
        a = locations[i].split(',')
        # gen.append((a[0][1:], a[1][:-2]))
        gen.append((a[0][1:], a[1][:-1]))
    return gen

# 随机产生若干个accident，每一个可以保持一段时间
def accident_factory():
    """
    :return:  set=([id, timer])
    """
    ACCIDENT_NUM = 10
    accident_set = set()
    for i in range(ACCIDENT_NUM):
        accident_set.add((i, random.randint(1, 100)))
    return accident_set

# 随机产生一条轨迹，轨迹必须是单调的，可以递增也可以递减
def trajectory():
    veh_num = 50
    # rsu_num = 20
    # road_len = 2000
    time_len = 200000
    start_point = random.sample(range(time_len), 50)
    veh_trajectory = []
    for i in range(veh_num):
        veh_id = uuid.uuid3(uuid.NAMESPACE_DNS, str(i))
        # xy = range(road_len)
        veh_trajectory.append({start_point[i]: veh_id})
    return veh_trajectory


# 基本ライブラリ
import streamlit as st
import numpy as np
import pandas as pd
from PIL import Image
from PIL import ImageFilter,ImageOps

import torch
import io
#from airplane_class_1 import transform, Net # animal.py から前処理とネットワークの定義を読み込み
#import airplane_maesyori_1

# maesyori
def keepAspectResizeSimple(path, size):
    # 画像の読み込み
    image = Image.open(path)
    # サイズを幅と高さにアンパック
    width, height = size
    # 矩形と画像の幅・高さの比率の小さい方を拡大率とする
    ratio = min(width / image.width, height / image.height)
    # 画像の幅と高さに拡大率を掛けてリサイズ後の画像サイズを算出
    resize_size = (round(ratio * image.width), round(ratio * image.height))
    # リサイズ後の画像サイズにリサイズ
    resized_image = image.resize(resize_size)
    return resized_image

def expand2square(pil_img, background_color):
    width, height = pil_img.size
    if width == height:
        return pil_img
    elif width > height:
        result = Image.new(pil_img.mode, (width, width), background_color)
        result.paste(pil_img, (0, (width - height) // 2))
        return result
    else:
        result = Image.new(pil_img.mode, (height, height), background_color)
        result.paste(pil_img, ((height - width) // 2, 0))
        return result

# net
# 必要なモジュールのインポート
from torchvision import transforms
import pytorch_lightning as pl
import torch.nn as nn
import torch.nn.functional as F
#学習時に使ったのと同じ学習済みモデルをインポート
from torchvision.models import efficientnet_b0

# 学習済みモデルに合わせた前処理を追加
transform = transforms.Compose([
    transforms.Resize(224),
    #transforms.CenterCrop(224),
    transforms.ToTensor(),
    #transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
    transforms.Grayscale(num_output_channels=3),
])

#　ネットワークの定義
class Net(pl.LightningModule):

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

        #学習時に使ったのと同じ学習済みモデルを定義
        self.feature = efficientnet_b0(pretrained=True)
        self.bnr = nn.BatchNorm1d(1000)
        self.fc = nn.Linear(1000, 10)

    def forward(self, x):
        #学習時に使ったのと同じ順伝播
        h = self.feature(x)
        h = self.bnr(h)
        h = self.fc(h)
        return h

# 学習済みモデルをもとに推論する
def predict(img):
    # ネットワークの準備
    net = Net().cpu().eval()
    # # 学習済みモデルの重み（dog_cat.pt）を読み込み
    net.load_state_dict(torch.load('./class_5.pt', map_location=torch.device('cpu')))
    #　データの前処理
    img = transform(img)
    img =img.unsqueeze(0) # 1次元増やす
    #　推論
    # 推論の実行
    with torch.no_grad():
        y1 = net(img)
        y2 = F.softmax(y1, dim=-1)
        y = torch.argmax(y2).cpu().detach().numpy()
        y2 = y2.cpu().detach().numpy()
    #y = torch.argmax(net(img), dim=1).cpu().detach().numpy()
    return y,y2

#　推論したラベルから犬か猫かを返す関数
def getName(label):
    if label==0:
        return 'Boeing-787'
    elif label==1:
        return 'MD-90'
    elif label==2:
        return 'Airbus-A320neo'
    elif label==3:
        return 'Boeing-777'
    elif label==4:
        return 'Airbus-A330'
    elif label==5:
        return 'Boeing-747'
    elif label==6:
        return 'CRJ'
    elif label==7:
        return 'E-Jet'
    elif label==8:
        return 'Airbus-A380'
    elif label==9:
        return 'MSJ'

# 生成
class UNetDown(nn.Module):
    def __init__(self, in_channels, out_channels, normalize=True, dropout=0.0):
        super(UNetDown, self).__init__()
        layers = [nn.Conv2d(in_channels, out_channels, 4, stride=2, padding=1, bias=False)]
        if normalize:
            layers.append(nn.InstanceNorm2d(out_channels))
        layers.append(nn.LeakyReLU(0.2))
        if dropout:
            layers.append(nn.Dropout(dropout))
        self.model = nn.Sequential(*layers)

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

class UNetUp(nn.Module):
    def __init__(self, in_channels, out_channels, dropout=0.0):
        super(UNetUp, self).__init__()
        layers = [nn.ConvTranspose2d(in_channels, out_channels, 4, stride=2, padding=1, bias=False),
                  nn.InstanceNorm2d(out_channels),
                  nn.ReLU(inplace=True)]
        if dropout:
            layers.append(nn.Dropout(dropout))
        self.model = nn.Sequential(*layers)

    def forward(self, x, skip_input):
        x = self.model(x)
        x = torch.cat((x, skip_input), 1)
        return x

class Generator(nn.Module):
    def __init__(self, in_channels=1, out_channels=3):
        super(Generator, self).__init__()

        self.down1 = UNetDown(in_channels, 64, normalize=False)
        self.down2 = UNetDown(64, 128)
        self.down3 = UNetDown(128, 256)
        self.down4 = UNetDown(256, 512, dropout=0.5)
        self.down5 = UNetDown(512, 512, dropout=0.5)
        self.down6 = UNetDown(512, 512, dropout=0.5)
        self.down7 = UNetDown(512, 512, dropout=0.5)
        self.down8 = UNetDown(512, 512, normalize=False, dropout=0.5)

        self.up1 = UNetUp(512, 512, dropout=0.5)
        self.up2 = UNetUp(1024, 512, dropout=0.5)
        self.up3 = UNetUp(1024, 512, dropout=0.5)
        self.up4 = UNetUp(1024, 512, dropout=0.5)
        self.up5 = UNetUp(1024, 256)
        self.up6 = UNetUp(512, 128)
        self.up7 = UNetUp(256, 64)

        self.final = nn.Sequential(
            nn.ConvTranspose2d(128, out_channels, 4, stride=2, padding=1),
            nn.Tanh()
        )

    def forward(self, x):
        d1 = self.down1(x)
        d2 = self.down2(d1)
        d3 = self.down3(d2)
        d4 = self.down4(d3)
        d5 = self.down5(d4)
        d6 = self.down6(d5)
        d7 = self.down7(d6)
        d8 = self.down8(d7)

        u1 = self.up1(d8, d7)
        u2 = self.up2(u1, d6)
        u3 = self.up3(u2, d5)
        u4 = self.up4(u3, d4)
        u5 = self.up5(u4, d3)
        u6 = self.up6(u5, d2)
        u7 = self.up7(u6, d1)

        return self.final(u7)

transforms2 = transforms.Compose([
    #Resize((256, 256), Image.BICUBIC),
    transforms.ToTensor(),
])

from torchvision.transforms.functional import to_pil_image

def tensor_to_pil(tensor):
    return to_pil_image(tensor.cpu().detach().squeeze(0))

# 重みをロード
# 学習済みモデルをもとに推論する
def predict2(img):
    # ネットワークの準備
    generator = Generator().cpu().eval()
    # # 学習済みモデルの重み（dog_cat.pt）を読み込み
    generator.load_state_dict(torch.load("./generator.pth", map_location=torch.device('cpu')))
    #　データの前処理
    img = transforms2(img)
    img =img.unsqueeze(0) # 1次元増やす
    #　推論
    # 推論の実行
    with torch.no_grad():
        fake_output = generator(img)
    #y = torch.argmax(net(img), dim=1).cpu().detach().numpy()
    return fake_output

# テキスト入力による値の動的変更
app_type = st.sidebar.selectbox(
    'モード選択 1=分類  2=生成 ',
    list(range(1, 3))
)

if app_type==1:
    # タイトルとテキストを記入
    st.title('Airplane classifiers and generators')
    st.write('飛行機の画像分類と画像生成を試してみよう！')

    st.write('その１：飛行機画像分類！')

    # file upload
    #from PIL import Image

    uploaded_file = st.file_uploader('Choose a image file')

    # データフレームの準備
    df = pd.DataFrame({
        #'Class' : [0, 1, 2],
        'メーカー' : ['Boeing', 'McDonnell Douglas', 'Airbus','Boeing', 'Airbus','Boeing', 'Bombardier','Embraer', 'Airbus','MHI'],
        '機種' : ['B787', 'MD-90', 'A320neo','B777','A330','B747', 'CRJ','E-Jet','A380','MSJ']
    })
    st.write('※現在の対応機種')
    # 静的なテーブル
    st.table(df)

    if uploaded_file is not None:
        image = Image.open(uploaded_file)
        size = (256, 256)
        img3 = keepAspectResizeSimple(uploaded_file,size)
        img3 = expand2square(img3, (0, 0, 0))
        img3 = img3.convert('RGB')
        img_array = np.array(image)
        col1, col2 = st.columns(2)
        with col1:
            st.header("original")
            st.image(
                image, caption='upload images',
                use_column_width=True
            )
        with col2:
            st.header("resized")
            st.image(
                img3, caption='upload images',
                use_column_width=True
            )
        # 入力された画像に対して推論
        pred, pred2 = predict(img3)
        AirplaneName = getName(pred)
        st.write('## Result')
        st.write('この飛行機はきっと',AirplaneName,'です!')
        st.write('自信度は',np.round(np.max(pred2)*100,1),'%です!')
        st.write(pred2*100)

elif app_type==2:
    # タイトルとテキストを記入
    st.title('Airplane classifiers and generators')
    st.write('飛行機の画像分類と画像生成を試してみよう！')

    st.write('その２：飛行機画像生成！')
    st.write('イラストや白黒写真からカラー写真を生成します。')
    st.write('写真や塗りつぶしがあるイラストを読み込むときは、エッジ検出をONにしてください。')
    st.write('カラー写真も読み込み可。分類ページリストの機種だと精度よく出ます。')
    edge_on = st.checkbox('エッジ検出ON')

    # file upload
    #from PIL import Image

    uploaded_file = st.file_uploader('Choose a image file')
    if uploaded_file is not None:
        image = Image.open(uploaded_file)
        size = (256, 256)
        img3 = keepAspectResizeSimple(uploaded_file,size)
        img3 = expand2square(img3, (255, 255, 255))
        img3 = img3.convert('L')
        img_array = np.array(image)
        if edge_on:
            img3 = img3.filter(ImageFilter.FIND_EDGES)
            img3 = ImageOps.invert(img3)
        col1, col2 = st.columns(2)
        with col1:
            st.header("original")
            st.image(
                image, caption='upload images',
                use_column_width=True
            )
        with col2:
            st.header("resized")
            st.image(
                img3, caption='upload images',
                use_column_width=True
            )
        # 入力された画像に対して推論
        pred_image = predict2(img3)
        pred_image_pil = tensor_to_pil(pred_image)
        st.write('## Result')
        st.header("生成画像！")
        st.image(
                pred_image_pil, caption='Generate_Airplane',
                use_column_width=True
            )


import torchvision.transforms as TF
import torchvision.transforms.functional as TFF
import numpy as np
from PIL import Image
import argparse
from pathlib import Path
from tqdm.auto import tqdm

def _get_new_shape(img):
    H, W = np.array(img).shape[:2]
    H_new, W_new = 512, round(512 * W / H)
    return H_new, W_new

def resize_image(img):
    H_new, W_new = _get_new_shape(img)
    mode = TF.InterpolationMode.BILINEAR
    return TFF.resize(img, (H_new, W_new), interpolation=mode)

def resize_mask(img):
    H_new, W_new = _get_new_shape(img)
    mode = TF.InterpolationMode.NEAREST
    return TFF.resize(img, (H_new, W_new), interpolation=mode)

def resize_folder(source, target, rtype):
    source ,target = Path(source), Path(target)
    print('source is ', source.absolute())
    target.mkdir(exist_ok=False, parents=True)
    skipped = []
    for pt in tqdm(list(source.iterdir())):
        if pt.suffix in ['.jpg', '.png']:
            image = Image.open(pt)
            if rtype == 'image':
                image = resize_image(image)
            else:
                image = resize_mask(image)
            targ_name = pt.name[:-len(pt.suffix)] + '.png'
            image.save(target / targ_name)
        else:
            skipped.append(pt.name)
    print(f'Skipped files: {", ".join(skipped)}')

if __name__ == '__main__':
    parser = argparse.ArgumentParser('resize')
    parser.add_argument('--source', type=str, help='absolute path to source folder', required=True)
    parser.add_argument('--target', type=str, help='absolute path to target folder', required=True)
    parser.add_argument('--type', choices=['image', 'mask'], help='resize type', required=True)
    args = parser.parse_args()
    print(args)
    print('Start resizing...')
    resize_folder(args.source ,args.target, args.type)
    print('Resizing ended')


import datetime
import openai
from config import apikey
import speech_recognition as sr
import os
import win32com.client
import pyaudio
import webbrowser
# import required module
import subprocess, sys
import random
import win32com.client as wincl

speaker = win32com.client.Dispatch("SAPI.SpVoice")

chatStr = ""
def chat(query):
    global chatStr
    print(chatStr)
    openai.api_key = apikey
    chatStr += f"Rajat:{query}\n Jarvis:"
    response = openai.Completion.create(
        # model="gpt-3.5-turbo",
        model="text-davinci-003",
        prompt=chatStr,
        temperature=0.7,
        max_tokens=256,
        top_p=1,
        frequency_penalty=0,
        presence_penalty=0
    )
    # todo: wrap this inside of a try catch block
    speaker.speak (response["choices"][0]["text"])
    chatStr += f"{response['choices'][0]['text']}\n"
    return response["choices"][0]["text"]

    # with open(f"Openai/prompt-{random.randint(1,343434343434)}" , "w") as f:
    with open(f"Openai/{' '.join(prompt.split('AI')[1:]).strip()}.txt", "w") as f:
        f.write(text)

def ai(prompt):
    openai.api_key = apikey
    text = f"OpenAI response for Prompt: {prompt} \n****************************************\n\n"

    response = openai.Completion.create(
       # model="gpt-3.5-turbo",
        model="text-davinci-003",
        prompt=prompt,

        temperature=0.8,
        max_tokens=1024,
        top_p=1,
        frequency_penalty=0,
        presence_penalty=0
    )
    # todo: wrap this inside of a try catch block
    #  print (response["choices"][0]["text"])
    text += response["choices"][0]["text"]
    if not os.path.exists("Openai"):
        os.mkdir("Openai")

    #with open(f"Openai/prompt-{random.randint(1,343434343434)}" , "w") as f:
    with open(f"Openai/{' '.join(prompt.split('AI')[1:]).strip()}.txt" , "w") as f:
        f.write(text)

def say(text):
    os.system(f"say {text}")

def takeCommand():
    r=sr.Recognizer()
    with sr.Microphone() as source :
        r.pause_threshold = 0.5
        audio = r.listen(source)
        try:
            query = r.recognize_google(audio, language="en-in")
            print(f"user said: {query}")
            return query
        except Exception as e:
            return "Some Error Occured. Sorry from R buddy"

def speak(text):
    speaker = wincl.Dispatch("SAPI.SpVoice")
    speaker.Speak(text)

if __name__ == '__main__':
    i=0
    speaker.Speak("Jarvais.. AI")
    while i<=50:
        i=i+1
        print("listening..")
        query= takeCommand()

        # todo: make a list of sites
        sites = [["youtube","https://youtube.com"],["google","https://google.com"],
                 ["Facebook","https://facebook.com"],["linkedin","https://linkedin.com"],
                 ["my portfolio","file:///C:/Users/Abhi/Desktop/Web%20Designing/portfolio/portfolio/index.html"],
                 ["github profile", "https://github.com/Rajat-rj45"], ["instagram profile", "https://www.instagram.com/rajat__ak47/"],
                 ["galgotia college", "https://galgotiacollege.edu/"], ["icloud", "https://gu.icloudems.com/corecampus/index.php"],
                 ["AKTU", "https://aktu.ac.in/syllabus%202023-2024.html"], ["Sarkari result", "https://www.sarkariresult.com/"],
                 ["twitter", "https://twitter.com"], ["flipkart", "https://flipkart.com"],
                 ["Amazon", "https://amazon.com"]]
        for site in sites:
            if f"Open {site[0]}".lower() in query.lower():
                speaker.Speak(f"Opening {site[0]} sir...")
                webbrowser.open(site[1])

        if "open music" in query:
            musicPath = "C:/Users/Abhi/Downloads/rasiya.mp3"
            if os.path.exists(musicPath):
                # Open the music file with the default application
                os.startfile(musicPath)
            else:
                # Speak a message indicating that the file was not found
                speak(f"File not found: {musicPath}")

        if "what is the time" in query:
            strfTime = datetime.datetime.now().strftime("%H:%M:%S")
            print(strfTime)
            speaker.speak(f"Sir the time is {strfTime}")

        #todo: make a list
        apps=[["camera","C:/Users/Abhi/Desktop/Shortcut/Camera.lnk"],
              ["vs code","C:/Users/Abhi/Desktop/Shortcut/Visual Studio Code.lnk"],
              ["Calculator","C:/Users/Abhi/Desktop/Shortcut/Calculator.lnk"],
              ["Settings","C:/Users/Abhi/Desktop/Shortcut/Settings.lnk"],
              ["Calendar","C:/Users/Abhi/Desktop/Shortcut/Calendar.lnk"],
              ["Games","C:/Users/Abhi/Desktop/Shortcut/Solitaire & Casual Games.lnk"],
              ["Clock", "C:/Users/Abhi/Desktop/Shortcut/Clock.lnk"],
              ["This pc", "C:/Users/Abhi/Desktop/Shortcut/This PC - Shortcut.lnk"],
              ["Mail", "C:/Users/Abhi/Desktop/Shortcut/Mail.lnk"],
              ["Weather", "C:/Users/Abhi/Desktop/Shortcut/Weather.lnk"],
              ["Notepad","C:/Users/Abhi/Desktop/Shortcut/Notepad.lnk"],
              ["WhatsApp","C:/Users/Abhi/Desktop/Shortcut/WhatsApp.lnk"]]

        for app in apps :
            if f"Open {app[0]}".lower() in query.lower():
                speaker.Speak(f"Opening {app[0]} sir...")
                os.startfile(app[1])

        if "Using AI".lower() in query.lower():
            speaker.speak("yes sir")
            ai(prompt=query)

        elif "jarvis Quit".lower() in query.lower():
            exit()

        elif "reset chat".lower() in query.lower():
            chatStr=""

        else:
            print("Chatting...")
            chat(query)


# Predict in Keras
import json
from tensorflow.keras.preprocessing.text import tokenizer_from_json
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.sequence import pad_sequences
import numpy as np
from nltk.stem import WordNetLemmatizer
import re

stopwords = nltk.corpus.stopwords.words('english')
lemmatizer = WordNetLemmatizer()

# This can be replaced with the model location
SAVE_PATH = ''

negative_tweet_text = 'i had an very sick bad service'
positive_tweet_text = 'i had an excellent service'

#Define the indexing for each possible label in a dictionary
class_to_index = {"Neutral":0, "Negative":1, "Positive": 2}

#Creates a reverse dictionary
index_to_class = dict((v,k) for k, v in class_to_index.items())

ids_to_names = lambda n: np.array([index_to_class.get(x) for x in n])

def preprocess_tweet(tweet_text):
    tweet_text = re.sub('[^a-zA-Z]', ' ', tweet_text)
    tweet_text = tweet_text.lower()
    tweet_text = tweet_text.split()
    tweet_text = [lemmatizer.lemmatize(word) for word in tweet_text if (not(word in set(stopwords))) & (len(word)>1) ]
    tweet_text = ' '.join(tweet_text)
    return tweet_text

with open(f'{save_path}/keras_model_files/keras_tokenizer.json') as f:
    data = json.load(f)
    keras_tokenizer = tokenizer_from_json(data)

reconstructed_keras_model = load_model(f'{current_path}/keras_model_files/keras_model')

preprocessed_tweet = [preprocess_tweet(tweet_text) for tweet_text in [negative_tweet_text, positive_tweet_text]]

predict_texts_to_sequences = keras_tokenizer.texts_to_sequences(preprocessed_tweet)
predict_texts_to_sequences = pad_sequences(predict_texts_to_sequences, padding='post', maxlen=max_len)

keras_predictions = np.argmax(reconstructed_keras_model.predict(predict_texts_to_sequences), axis=1)

keras_prediction_labels_test = ids_to_names(keras_predictions)

print(keras_prediction_labels_test)