#!/usr/bin/env python
"""
AER1415 Computer Optimization - Assignment 2

Author: Atilla Saadat
Submitted: Mar 31, 2021
Email: asaadat@utias-sfl.net

Question 1

"""

from numpy import *
import matplotlib
from matplotlib import pyplot as plt
from mpl_toolkits import mplot3d
from matplotlib import cm
import matplotlib.colors as colors

from rosen import *

def newtons_method(plot=False,verbose=False):
	#initialize parameters
	x0 = array([-1., -2.])
	x = [x0]
	vals = [rosen(x0)]
	#calculate first 5 iterates
	for iterNum in range(5):
		x_k = x[-1]
		g_k = rosen_gk(x_k)
		H_k = rosen_Hk_n2(x_k)

		#inverse hessian search direction calculation
		p_k = -dot(linalg.inv(H_k),g_k)
		x_k1 = x_k + p_k
		val_k1 = rosen(x_k1)

		x.append(x_k1)
		vals.append(val_k1)

	x = array(x)
	vals = array(vals)

	if verbose:
		for idx,x_k in enumerate(x):
			print('Iter: {} - x*: {}, val:: {}'.format(idx,x_k,vals[idx]))
	#plot and save contour
	if plot:
		print('Creating Contour Plot - Please Wait')
		X, Y = meshgrid(linspace(-1.5, 2, 500), linspace(-3, 3, 500))
		Z = array([rosen([j,i]) for i,j in zip(X.flatten(),Y.flatten())]).reshape(X.shape)
		fig, ax = plt.subplots()
		fig.set_size_inches(18.5, 10.5)
		pcm = ax.pcolormesh(X, Y, Z,norm=colors.LogNorm(vmin=Z.min(), vmax=Z.max()),cmap='RdBu_r',rasterized=True)
		ax.plot(*x.T,'-o',color='#16F41B',markersize=2)
		ax.set_xlabel(r'$x_1$')
		ax.set_ylabel(r'$x_2$')
		ax.set_title('Newtons method - Rosenbrock Test Function - n=2')
		fig.colorbar(pcm, ax=ax, extend='max',label=r'$f(x)$')
		print('Contour Plot Done!')
		plt.savefig('Q1_NewtonsMethod.svg', format = 'svg', bbox_inches = 'tight')
		plt.show()

	return {'x*': x[-1], 'val': vals[-1]}

newtons_method(plot=True,verbose=True)


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

def Var(array):
    mean = 0
    n = len(array)**3
    for k in range(0,len(array)):
        for i in range(0,len(array)):
            for j in range(0,len(array)):
                mean = mean + array[k,i,j]
    mean = mean/n

    summation = 0
    for k in range(0,len(array)):
        for i in range(0,len(array)):
            for j in range(0,len(array)):
                summation = summation + (x[k,i,j]-mean)**2

    var = summation/n
    return var

# test here

def Contour_plot(array,subarray):
    pixel_n = len(array)
    xlabel = np.arange(0,pixel_n)
    ylabel = np.arange(0,pixel_n)
    X, Y = np.meshgrid(xlabel,ylabel)
    Z = array[subarray]
    plt.contourf(X,Y,Z,20,cmap='RdGy')
    plt.xlabel('Pixel x location')
    plt.ylabel('Pixel y location')
    plt.xticks(np.arange(0,pixel_n,2))
    plt.yticks(np.arange(0,pixel_n,2))
    cb = plt.colorbar()
    cb.set_label('Field value')
    plt.show()

def Weight(array):
    n = len(array)
    for k in range(0,n):
        for i in range(0,n):
            for j in range(0,n):
                array[k,i,j] = (np.e**k) * array[k,i,j]

    return array


import dash
from dash import html, dcc, Input, Output, State, callback
import dash_bootstrap_components as dbc

import sys
# adding charts to the system path

from charts.colors import graphics_colors as gc

def make_dropdown(id, value, options = [], background = gc['dropdown_background']):
    dropdown = dcc.Dropdown(
    options,
    id = id,
    value = value,
    style = {
        "cursor": "pointer",
        "font-size":"12px"},
    className = "p-2",
    clearable=False)
    return dropdown

def make_card (header:str, id:str, className = "card text-white bg-primary mb-3"):
    card = dbc.Card(
        [
            dbc.CardHeader(header),
            dbc.CardBody(
                [
                    dcc.Markdown(id = id)

                ]
            )
        ],
        className = className
    )

    return card


from datasets import load_dataset
import json
import requests
from collections import defaultdict

from langchain.llms import OpenAI
from langchain import PromptTemplate, FewShotPromptTemplate
from langchain.prompts.example_selector import LengthBasedExampleSelector
from inference_api import YiyanInferenceApi, HfInferenceApi
import regex
import sys

from mpi4py import MPI

dataset_mapping_url = f"https://raw.githubusercontent.com/SJTU-LIT/ceval/main/subject_mapping.json"

llm = YiyanInferenceApi("yiyan-007", debug=False)
# llm = OpenAI(model_name="text-davinci-003")

def get_data_mapping(mapping_url):
    headers = {
            'Content-Type': 'application/json',
            'Accept': 'application/json'
        }
    response = requests.request("GET", mapping_url, headers=headers)
    return json.loads(response.content.decode('utf-8'))

def escape_format(text : str) -> str :
    return text.replace('{', '{{').replace('}', '}}')

def gen_by_fewshot_prompt(task_name, fewshot_set, test_set, output) :

    prompt_template = """问题：{question} \n选项\nA: {A}\nB: {B}\nC: {C}\nD: {D}\n思考：{explanation}\n答案：{answer}\n\n"""

    example_prompt = PromptTemplate(
        input_variables = ['question', 'A', 'B', 'C', 'D', 'explanation', 'answer'],
        template = prompt_template
    )

    fewshot_examples = []
    for id in range(len(fewshot_set)) :
        fewshot_examples.append({'question': escape_format(fewshot_set[id]['question']),
                                 'A': escape_format(fewshot_set[id]['A']),
                                 'B': escape_format(fewshot_set[id]['B']),
                                 'C': escape_format(fewshot_set[id]['C']),
                                 'D': escape_format(fewshot_set[id]['D']),
                                 'explanation': escape_format(fewshot_set[id]['explanation']),
                                 'answer': fewshot_set[id]['answer']})

    example_selector = LengthBasedExampleSelector(
        examples = fewshot_examples,
        example_prompt = example_prompt,
        max_length = 1024,
        get_text_length = lambda x: len(x) # tokens per Chinese character
    )

    few_shot_prompt = FewShotPromptTemplate(
        example_selector = example_selector,
        example_prompt = example_prompt,
        prefix = f"请作为一个{task_name}科目的考生，参考示例回答单项选择题，示例如下：\n",
        suffix = """下面是要回答的问题，可以先写出思考过程，然后给出ABCD的一个选项作为答案，确保用<答案：>作为答案的前缀\n
                    问题：{question}\n选项\nA: {A}\nB: {B}\nC: {C}\nD: {D}\n思考：""",

        input_variables = ['question', 'A', 'B', 'C', 'D'],
        example_separator = "\n\n"
    )

    correct, total = 0, 0
    for id in range(len(test_set)) :
        try :
            grounded_prompt = few_shot_prompt.format(question = escape_format(test_set[id]['question']),
                                                            A = escape_format(test_set[id]['A']),
                                                            B = escape_format(test_set[id]['B']),
                                                            C = escape_format(test_set[id]['C']),
                                                            D = escape_format(test_set[id]['D']))
            completion = llm(grounded_prompt)
            llm_answer = extract_answer(completion)
            answer = test_set[id]['answer']
            print(f"question: {task_name}-{id}, llm_answer={llm_answer}, answer={answer}, completion={repr(completion)}",
                  file = output)
            total += 1
            if llm_answer == answer :
                correct += 1
        except Exception as e :
            print(f"Exception {e} in answer generation for question <{id}> in task <{task_name}>")

    return (correct, total)

def extract_answer(completion) :

    # string find part
    answer_prefixes = ['答案：', '答案:', '答案为', '答案是', '答案选',
                       '故选', '选项中最接近的是', '选项为', '答案应该是',
                       '因此选择', '因此答案为：', '即选项', '故选择',
                       '正确的选项是', '答案选', '因此答案为 ', '故选 ']
    for answer_prefix in answer_prefixes :
        if answer_prefix in completion :
            pos = completion.rfind(answer_prefix) + len(answer_prefix)
            if pos < len(completion) :
                answer = completion[pos]
                if answer == '{' and pos + 1 < len(completion) :
                    answer = completion[pos + 1]
                if answer in ['A', 'B', 'C', 'D'] :
                    return answer
    # regex part
    answer_patterns = [r'选项\((.*?)\)为正确', r'选项(.*?)为正确',
                       r'选项\((.*?)\)正确', r'选项(.*?)正确',
                       r'选项\((.*?)\)是正确', r'选项(.*?)是正确',
                       r'选择\((.*?)\)为正确', r'选择(.*?)为正确',
                       r'因此\((.*?)\)选项正确', r'因此(.*?)选项正确',
                       r'答案：<\((.*?)\)>', r'答案：<(.*?)>']

    for pattern in answer_patterns :
        match = regex.search(pattern, completion)
        if match :
            answer = match.group(1)
            if answer in ['A', 'B', 'C', 'D'] :
                return answer

    return 'Err'

if __name__ == "__main__" :

    data_mapping = get_data_mapping(dataset_mapping_url)
    g_correct, g_total = 0.0, 0.0

    tested_subject = 0
    topK = len(data_mapping.keys())

    # distribute with MPI
    comm = MPI.COMM_WORLD
    rank = comm.Get_rank()

    output = f'yiyan-ceval-result-rank{rank}.log'
    with open(output, 'w') as f :
        for id, name in enumerate(data_mapping.keys()) :
            if id % comm.size == rank : # process a sub-task
                dataset=load_dataset(r"ceval/ceval-exam",name=name)
                # print(dataset['dev'][0])
                (correct, total) = gen_by_fewshot_prompt(data_mapping[name][1], dataset['dev'], dataset['val'], f)
                g_correct += correct
                g_total += total
                print(f"Task <{name}>: correct={correct}, total={total}", file=f)
                print(f"Global accuracy so far: {g_correct/g_total:.4f}(g_correct={g_correct}, g_total={g_total})", file=f)

                tested_subject += 1
                if tested_subject >= topK :
                    break


import csv
import itertools
from abc import ABC, abstractmethod
from datetime import timedelta

from django.http import HttpResponse, StreamingHttpResponse
from django.utils import timezone
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page

from rest_framework.views import APIView

from eric.appointments.config import CALENDAR_EXPORT_CACHE_SECONDS, DISPLAY_EXPORT_CACHE_SECONDS
from eric.appointments.utils import Echo
from eric.shared_elements.models import Meeting, Resource
from eric.site_preferences.models import options as site_preferences

class PublicCSVExportView(APIView, ABC):
    authentication_classes = ()
    permission_classes = ()
    download_file_name = "export.csv"

    def get(self, request, *args, **kwargs):
        response = self.build_http_response()
        response["Content-Disposition"] = f'attachment; filename="{self.download_file_name}"'
        return response

    def build_http_response(self):
        """
        Returns the CSV data as standard HTTP response.
        """

        response = HttpResponse(content_type="text/csv")
        writer = csv.writer(response, delimiter=";")
        for row in self.headers_and_rows:
            writer.writerow(row)

        return response

    def build_stream_response(self):
        """
        Returns the CSV data as streaming response.
        Might become necessary, if there is a huge amount of data.
        """

        pseudo_buffer = Echo()
        writer = csv.writer(pseudo_buffer, delimiter=";")
        streaming_content = (writer.writerow(row) for row in self.headers_and_rows)
        response = StreamingHttpResponse(streaming_content, content_type="text/csv")
        return response

    @property
    def headers_and_rows(self):
        """Iterator for all CSV rows (headers + content)"""
        return itertools.chain((self.csv_headers,), self.csv_rows)

    @property
    @abstractmethod
    def csv_rows(self):
        """Returns an iterator for data rows"""
        pass

    @property
    @abstractmethod
    def csv_headers(self):
        """Returns the CSV headers as list"""
        pass

@method_decorator(cache_page(CALENDAR_EXPORT_CACHE_SECONDS), "dispatch")
class CalendarCsvView(PublicCSVExportView):
    """
    Outputs anonymous CSV data of study room bookings within the next two weeks for simple calendars.
    """

    download_file_name = "calendar-export.csv"

    @property
    def study_room_bookings(self):
        """
        Gets all bookings within the next two weeks.
        """

        start_of_today = timezone.now().date()
        in_two_weeks = start_of_today + timedelta(days=14)
        return (
            Meeting.objects.study_room_bookings()
            .filter(deleted=False)
            .intersecting_interval(start_of_today, in_two_weeks)
            .order_by("date_time_start")
        )

    @property
    def csv_headers(self):
        return [
            "appointment_id",
            "resource_name",
            "start",
            "end",
        ]

    @property
    def csv_rows(self):
        return (
            [
                appointment.pk,
                appointment.resource.name,
                appointment.date_time_start.isoformat(),
                appointment.date_time_end.isoformat(),
            ]
            for appointment in self.study_room_bookings
        )

@method_decorator(cache_page(DISPLAY_EXPORT_CACHE_SECONDS), "dispatch")
class DisplayCsvView(PublicCSVExportView):
    """
    Outputs anonymous CSV data of study room bookings from today for simple displays.
    """

    download_file_name = "display-export.csv"

    @property
    def study_room_bookings(self):
        """
        Returns upcoming bookings of today.
        """

        now = timezone.now()
        end_of_today = now.replace(hour=23, minute=59, second=59, microsecond=999_999)
        return (
            Meeting.objects.study_room_bookings()
            .filter(deleted=False)
            .intersecting_interval(now, end_of_today)
            .order_by("date_time_start")
        )

    @property
    def bookings_per_room(self):
        number = site_preferences.bookings_per_room_in_study_room_booking_display_export
        assert number > 0, "Export is configured to have no columns"
        return number

    @property
    def csv_headers(self):
        headers = [
            "RaumId",
            "Raumbezeichnung",
        ]

        # append the per-appointment headers with a two-digit index (e.g. "TerminStart01")
        for index in range(1, self.bookings_per_room + 1):
            for key in ["TerminStart", "TerminEnde", "Laufend", "TerminBezeichnung", "Organisator", "TerminDatum"]:
                headers.append(f"{key}{index:02d}")

        headers.extend(
            [
                "Datum",
                "Template",
            ]
        )

        return headers

    def format_date(self, date):
        return timezone.localtime(date)

    @property
    def csv_rows(self):
        study_rooms = Resource.objects.study_rooms().order_by("study_room_info__room_id")
        return (self.row_for_room(resource) for resource in study_rooms)

    def row_for_room(self, resource: Resource):
        study_room = resource.study_room_info
        now = timezone.now()

        cells = [study_room.room_id, study_room.name]

        # add available booking information
        bookings = self.study_room_bookings.filter(resource=resource)[: self.bookings_per_room]
        for booking in bookings:
            start_time = self.format_date(booking.date_time_start).strftime("%H:%M")
            end_time = self.format_date(booking.date_time_end).strftime("%H:%M")
            running_flag = booking.date_time_start <= now < booking.date_time_end
            appointment_name = booking.title
            organiser_name = booking.created_by.userprofile.first_name_and_last_name
            booking_date = self.format_date(booking.date_time_start).strftime("%d.%m.%Y")
            cells.extend([start_time, end_time, running_flag, appointment_name, organiser_name, booking_date])

        # add empty cells if there are not enough bookings to show
        empty_booking_count = self.bookings_per_room - len(bookings)
        empty_cells = [""] * 6 * empty_booking_count
        cells.extend(empty_cells)

        current_date = now.strftime("%d.%m.%Y")
        template = study_room.display_design.key
        cells.extend([current_date, template])

        return cells


import numpy as np  # linear algebra
import pandas as pd  # data processing, CSV file I/O (e.g. pd.read_csv)
import os
import torch
import torchvision
import torch.nn as nn  # All neural network modules, nn.Linear, nn.Conv2d, BatchNorm, Loss functions
import torchvision.datasets as datasets  # Has standard datasets we can import in a nice way
import torchvision.transforms as transforms  # Transformations we can perform on our dataset
import torch.nn.functional as F  # All functions that don't have any parameters
from torch.utils.data import DataLoader, Dataset  # Gives easier dataset managment and creates mini batches
from torchvision.datasets import ImageFolder
import torch.optim as optim  # For all Optimization algorithms, SGD, Adam, etc.
from PIL import Image
from tqdm import tqdm
from torchvision import models
from sklearn.model_selection import train_test_split

class ImageLoader(Dataset):
    def __init__(self, dataset, transform=None):
        self.dataset = self.checkChannel(dataset)  # some images are CMYK, Grayscale, check only RGB
        self.transform = transform

    def __len__(self):
        return len(self.dataset)

    def __getitem__(self, item):
        image = Image.open(self.dataset[item][0])
        classCategory = self.dataset[item][1]
        if self.transform:
            image = self.transform(image)
        return image, classCategory

    def checkChannel(self, dataset):
        datasetRGB = []
        for index in range(len(dataset)):
            if (Image.open(dataset[index][0]).getbands() == ("R", "G", "B")):  # Check Channels
                datasetRGB.append(dataset[index])
        return datasetRGB

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")  # use gpu or cpu
print(device)

dataset = ImageFolder("D:/mzy/img1_0/train/")
train_data, test_data, train_label, test_label = train_test_split(dataset.imgs, dataset.targets, test_size=0.2,
                                                                  random_state=42)
#
train_transform = transforms.Compose([
    transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize([0.5] * 3, [0.5] * 3)
])  # train transform
test_transform = transforms.Compose([
    transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize([0.5] * 3, [0.5] * 3)
])  # test transform
train_dataset = ImageLoader(train_data, train_transform)
test_dataset = ImageLoader(test_data, test_transform)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=True)

# load pretrain model and modify...

# model = models.resnet50(pretrained=True)
model = models.resnet50(pretrained=False)
model.load_state_dict(torch.load('D:/mzy/resnet50-19c8e357.pth'))

# If you want to do finetuning then set requires_grad = False
# Remove these two lines if you want to train entire model,
# and only want to load the pretrain weights.

for param in model.parameters():
    param.requires_grad = False  # 原本是False

num_ftrs = model.fc.in_features
model.fc = nn.Linear(num_ftrs, 2)
model.to(device)

# Loss and optimizer
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)

# Train and test
def train(num_epoch, model):
    for epoch in range(0, num_epoch):
        #         current_loss = 0.0
        #         current_corrects = 0
        losses = []
        model.train()
        loop = tqdm(enumerate(train_loader), total=len(train_loader))  # create a progress bar
        for batch_idx, (data, targets) in loop:
            data = data.to(device=device)
            targets = targets.to(device=device)
            scores = model(data)

            loss = criterion(scores, targets)
            optimizer.zero_grad()
            losses.append(loss)
            loss.backward()
            optimizer.step()
            _, preds = torch.max(scores, 1)
            #             current_loss += loss.item() * data.size(0)
            #             current_corrects += (preds == targets).sum().item()
            #             accuracy = int(current_corrects / len(train_loader.dataset) * 100)
            loop.set_description(f"Epoch {epoch + 1}/{num_epoch} process: {int((batch_idx / len(train_loader)) * 100)}")
            loop.set_postfix(loss=loss.data.item())

        # save model
        torch.save({
            'model_state_dict': model.state_dict(),
            'optimizer_state_dict': optimizer.state_dict(),
        }, 'checpoint_epoch_' + str(epoch) + '.pt')

# model.eval() is a kind of switch for some specific layers/parts of the model that behave differently,
# during training and inference (evaluating) time. For example, Dropouts Layers, BatchNorm Layers etc.
# You need to turn off them during model evaluation, and .eval() will do it for you. In addition,
# the common practice for evaluating/validation is using torch.no_grad() in pair with model.eval()
# to turn off gradients computation:

def test():
    model.eval()
    test_loss = 0
    correct = 0
    with torch.no_grad():
        for x, y in test_loader:
            x = x.to(device)
            y = y.to(device)
            output = model(x)
            _, predictions = torch.max(output, 1)
            correct += (predictions == y).sum().item()
            test_loss = criterion(output, y)

    test_loss /= len(test_loader.dataset)
    print("Average Loss: ", test_loss, "  Accuracy: ", correct, " / ",
          len(test_loader.dataset), "  ", int(correct / len(test_loader.dataset) * 100), "%")

# if __name__ == "__main__":
train(6, model)  # train
test()  # test

print("----> Loading checkpoint")
checkpoint = torch.load("./checpoint_epoch_4.pt")  # Try to load last checkpoint
model.load_state_dict(checkpoint["model_state_dict"])
optimizer.load_state_dict(checkpoint["optimizer_state_dict"])

# Check the test set
dataset = ImageFolder("D:/mzy/img1_0/test/",
                      transform=transforms.Compose([
                          transforms.Resize((224, 224)),
                          transforms.ToTensor(),
                          transforms.Normalize([0.5] * 3, [0.5] * 3)
                      ]))
# print(dataset)
dataloader = DataLoader(dataset, batch_size=1, shuffle=False)

# for j, (data, labels) in enumerate(dataloader):
with torch.no_grad():
    model.eval()
    for data, target in dataloader:
        data, target = data.to(device), target.to(device)
        output = model(data)
        _, predicted = torch.max(output, 1)
#         print(f"predicted ----> {predicted[0]}")

dataset = ImageFolder("D:/mzy/mzy/img1_0/120207/")
# print(dataset)
dataloader = ImageLoader(dataset.imgs, train_transform)

train = pd.read_csv('train2.csv', header=None,
                    names=['imgId', 'skc', 'spuId', 'cid1', 'cid2', 'leafCid', 'img', 'imgPath'], keep_default_na=False)
train = train[train['imgPath'] != '']

# train[:5]

train = train.reset_index(drop=True)

def RandomImagePrediction(filepath, i):
    img_array = Image.open(filepath).convert("RGB")
    data_transforms = transforms.Compose([
        transforms.Resize((224, 224)),
        transforms.ToTensor(),
        transforms.Normalize([0.5] * 3, [0.5] * 3)
    ])
    img = data_transforms(img_array).unsqueeze(
        dim=0)  # Returns a new tensor with a dimension of size one inserted at the specified position.
    load = DataLoader(img)

    for x in load:
        x = x.to(device)
        pred = model(x)
        _, preds = torch.max(pred, 1)
        #         print(f"class : {preds}")
        if preds[0] == 0:
            # print(0)
            train1.loc[i, 'imgPath'] = ''

#             return True
#         else:
#             return False

train1 = train[['imgId', 'skc', 'spuId', 'cid1', 'cid2', 'leafCid', 'img', 'imgPath']]
print(len(train1))
print(train1[:5])

for i in range(len(train)):
    RandomImagePrediction('D:/xiangsitu/imgs/' + train1.loc[i]['imgPath'], i)
#     if(not RandomImagePrediction('../input/jiafang-1w/imgs/imgs/' + train.iloc[i]['imgPath'])):
#         train.iloc[i]['imgPath']=''

# print(train1[:15])
train2 = train1[train1['imgPath'] != '']
print(len(train2))
train3 = train1[train1['imgPath'] == '']
print(len(train3))

outputpath1 = '120207/data.csv'
outputpath0 = '120207/test_result_0.csv'
train2.to_csv(outputpath1, sep=',', index=False, header=True)
train3.to_csv(outputpath0, sep=',', index=False, header=True)


from os import path
import os
from pathlib import Path
import re
from .sysx import *

is_abs = path.isabs # 判断是否是绝对路径
is_file = path.isfile # 判断是否是文件
is_dir = path.isdir # 判断是否是文件夹
is_link = is_symlink = path.islink # 重命名判断软链接的方法
is_exist = path.exists # 判断路径是否存在

__all__ = (
    "is_abs",
    "is_file",
    "is_dir",
    "is_link",
    "is_exist",
    "not_exist",
    "is_rel",
    "cwd",
    "dirname",
    "basename",
    "to_abs",
    "is_symlink"
)

def not_exist(*args, **kwargs):
    """
    判断路径是否不存在
    """
    return not is_exist(*args, **kwargs)

def is_rel(p):
    """
    判断路径是否是相对路径
    p 参数是一个 路径字符串或者 Path 对象
    """
    return not is_abs(p)

def cwd(path_str=None):
    """
    获取或者设置当前的工作目录
    如果给出了 path_str 那么就是设置 没有给出就是获取当前的工作目录
    """
    if path_str is None:
        return os.getcwd()
    else:
        if is_rel(path_str):
            path_str = Path(cwd()) / path_str
        return os.chdir(path_str)

def dirname(path_str):
    """
    传入一个路径返回这个目标路径的上一个文件夹路径
    """
    # 判断路径是否是以 / 或者 \ 结尾的如果是去掉在返回 path.dirname 的处理结果

    if path_str.endswith(r"/") or path_str.endswith("\\"):
        path_str = path_str[0:len(path_str)-1]
    return path.dirname(path_str)

def basename(path_str):
    """
    传入一个路径返回这个目录路径指向的那个文件或者文件夹
    """
    if path_str.endswith(r"/") or path_str.endswith("\\"):
        path_str = path_str[0:len(path_str)-1]
    return path.basename(path_str)

def to_abs(path_arg):
    """
    传入一个路径字符串或者一个Path将一个路径转换成绝对路径, 返回路径字符串
    """
    if is_abs(path_arg):
        return path_arg

    path_str = str(Path(cwd()) / path_arg)

    path_list = re.split(r"[\\/]",path_str)
    path_list = [get_env(i) if i.startswith("%") and i.endswith("%") else i
                 for i in path_list]

    path_str = str(Path("/".join(path_list)))
    return path_str


import tensorflow as tf
import pdb
import math
import matplotlib.pyplot as plt
from lqrker.models.rrtp import RRTPLQRfeatures

import numpy as np

import gpflow

import tensorflow_probability as tfp

def sample_v1(nu,dim,Nsamples):
	"""
	Using a Multivariate Gaussian and the squared root of an inverse Gamma

	"""

	# Sample from inverse Gamma:
	alpha = 0.5*nu
	beta = 0.5
	dist_ig = tfp.distributions.InverseGamma(concentration=alpha,scale=beta)
	sample_ig = dist_ig.sample(sample_shape=(Nsamples,1))

	dist_nor = tfp.distributions.Normal(loc = 0.0, scale = tf.math.sqrt(nu - 2.))
	sample_nor = dist_nor.sample(sample_shape=(Nsamples,dim))

	# Sample from MVT(nu,0,I):
	sample_mvt0 = sample_nor * tf.math.sqrt(sample_ig)

	K = tf.constant([[1.0,0.2],[0.2,1.0]]) + 0.5*tf.eye(dim)
	sample_mvt = sample_mvt0 @ tf.linalg.cholesky(K)

	return sample_mvt

def sample_v2(nu,dim,Nsamples):
	"""

	Using: (i) uniform sphere, (ii) inverse gamma, and (iii) Chi-squared
	"""

	dist_sphe = tfp.distributions.SphericalUniform(dimension=dim)
	sample_sphe = dist_sphe.sample(sample_shape=(Nsamples,))

	# Sample from inverse Gamma:
	alpha = 0.5*nu
	beta = 0.5
	dist_ig = tfp.distributions.InverseGamma(concentration=alpha,scale=beta)
	sample_ig = dist_ig.sample(sample_shape=(Nsamples,1))

	# Sample from chi-squared:
	dist_chi2 = tfp.distributions.Chi2(df=dim)
	sample_chi2 = dist_chi2.sample(sample_shape=(Nsamples,1))

	# Sample from MVT(nu,0,I):
	sample_mvt0 = tf.math.sqrt((nu-2) * sample_chi2 * sample_ig) * sample_sphe

	K = tf.constant([[1.0,0.2],[0.2,1.0]]) + 0.5*tf.eye(dim)
	sample_mvt = sample_mvt0 @ tf.linalg.cholesky(K)

	return sample_mvt

if __name__ == "__main__":

	"""
	Trying to reproduce Fig. 3 from [1]

	[1] Shah, A., Wilson, A. and Ghahramani, Z., 2014, April. Student-t processes
	as alternatives to Gaussian processes. In Artificial intelligence and
	statistics (pp. 877-885). PMLR.
	"""

	dim = 2
	nu = 2.1
	Nsamples = 1e5
	M = tf.zeros(2)

	my_samples1 = sample_v1(nu,dim,Nsamples)
	my_samples2 = sample_v2(nu,dim,Nsamples)

	psd_kernels = tfp.math.psd_kernels
	kernel = psd_kernels.ExponentiatedQuadratic(amplitude=1.0,length_scale=0.5)

	# index_points = tf.constant([10,2,2,2])
	index_points = tf.constant([[-1.0],[1.0]])
	# index_points = tf.constant([[1.0],[0.5]])
	# index_points = np.expand_dims(np.linspace(-1., 1., 2), -1)
	# pdb.set_trace()
	mvt = tfp.distributions.StudentTProcess(df=nu, kernel=kernel, index_points=index_points, mean_fn=None)

	samples = mvt.sample(Nsamples)

	# pdb.set_trace()

	hdl_fig, hdl_splots = plt.subplots(3,1,figsize=(14,10),sharex=True)
	# hdl_fig.suptitle("Reduced-rank Student-t process")
	hdl_splots[0].plot(samples[:,0],samples[:,1],marker="o",color="blue",linestyle="None")

	hdl_splots[1].plot(my_samples1[:,0],my_samples1[:,1],marker="o",color="blue",linestyle="None")

	hdl_splots[2].plot(my_samples2[:,0],my_samples2[:,1],marker="o",color="blue",linestyle="None")

	plt.show(block=True)


from typing import Mapping, Any
from fastapi import APIRouter, Depends
from ert_storage.database import Session, get_db

router = APIRouter(tags=["info"])

@router.get("/server/info", response_model=Mapping[str, Any])
def info(
    *,
    db: Session = Depends(get_db),
) -> Mapping[str, Any]:
    return {"name": "Ert Storage Server"}


import torch
import torchvision as tv
import torchvision.transforms as transforms
import torch.nn as nn
import torch.optim as optim
import numpy as np
from torch.utils.data import DataLoader
from torch.autograd import Variable

import load_data
import wide_resnet as wrn

def random_choose(X_train, y_train, batch_size = 256):
    print(len(X_train))
    if (batch_size >= len(X_train)):
        return X_train, y_train
    indices = torch.from_numpy(np.random.choice(len(X_train), batch_size))

    return X_train.index_select(0, indices), y_train.index_select(0, indices)

def test_wrn(model):
    total_loss = 0
    correct = 0
    size = len(X_test)
    total = 0 # num of samples
    transformer = transforms.Compose([
        transforms.ToTensor()
    ])

    testset = tv.datasets.CIFAR10(root='./data', train=False, download=True, transform=transformer)
    testloader = DataLoader(testset, batch_size=100, shuffle=False, num_workers=2)

    calculate_loss = nn.CrossEntropyLoss()

    test_string = "# of batches: {}, loss: {}\n"
    print("Test 100 samples each time")

    with torch.no_grad():
        for step, (X, y) in enumerate(testloader):
            y_bar = model(X)
            loss = calculate_loss(y_bar, y)

            total_loss += loss.item()
            _, predicted = torch.max(y_bar.data, 1)

            correct += predicted.eq(y.data).cpu().sum()
            total += len(X)

            # save output
            with open("output.txt", "a") as output_file:
                output_file.write(test_string.format(step, loss))

            print(test_string.format(step, loss))

    with open("output.txt", "a") as output_file:
        output_file.write("Total loss: {}, correct: {}, total: {}, succ ratio: {}".format(total_loss, correct, total, 1.0*correct/total))

    print("Total loss: {}, correct: {}, total: {}, succ ratio: {}".format(total_loss, correct, total, 1.0*correct/total))

# training with all examples as torch.Tensor that are not modified
def naive_training(X_train, y_train, epoch, batch_size = 256, learning_rate = 0.1):
    # depth, widening factor, dropout rate from WRN paper, number of classes
    model = wrn.Wide_ResNet(16, 10, 0.3, 10)
    loss = 0
    optimizer = optim.SGD(model.parameters(), lr=learning_rate)

    calculate_loss = nn.CrossEntropyLoss()

    output_string = "Numpy Array - Step {}, loss: {}\n"
    for i in range(epoch):
        optimizer.zero_grad()

        # SGD
        X_batch, y_batch = random_choose(X_train, y_train, batch_size = batch_size)
        y_bar = model(X_batch)

        loss = calculate_loss(y_bar, y_batch)
        loss.backward()

        optimizer.step()

        # save output
        with open("output.txt", "a") as output_file:
            output_file.write(output_string.format(i, loss))

        # print to thescreen also
        print(output_string.format(i, loss))

    return model

# training with Dataloader
def nt():
    model = wrn.Wide_ResNet(16, 10, 0.3, 10)

    optimizer = optim.SGD(model.parameters(), lr=0.1)
    calculate_loss = nn.CrossEntropyLoss()

    loss = 0
    transformer = transforms.Compose([
        transforms.ToTensor()
    ])
    trainset = tv.datasets.CIFAR10(root='./data', train=True, download=True, transform=transformer)
    trainloader = DataLoader(trainset, batch_size=256, shuffle=False, num_workers=2)

    output_string = "Dataloader - Step {}, loss: {}\n"
    for step, (X, y) in enumerate(trainloader):
        optimizer.zero_grad()

        y_bar = model(X)

        loss = calculate_loss(y_bar, y)
        loss.backward()

        optimizer.step()

        # save output
        with open("output.txt", "a") as output_file:
            output_file.write(output_string.format(step, loss))

    return model

if __name__ == '__main__':

    X_train, y_train, X_test, y_test, label_names = load_data.load()

    X_train = torch.Tensor(X_train)
    y_train = torch.from_numpy(y_train)

    #model = naive_training(X_train, y_train, 200)
    model = nt()
    test_wrn(model)

    '''
    x, y = random_choose(X_train, y_train, 2)
    '''


import pyrealsense2 as rs
import numpy as np
import cv2 as cv

# Tracker types
tracker_types = ['BOOSTING', 'MIL','KCF', 'TLD', 'MEDIANFLOW', 'GOTURN', 'MOSSE', 'CSRT']
tracker_type = tracker_types[2]

# initialize tracker
if tracker_type == 'BOOSTING':
    tracker = cv.TrackerBoosting_create()
if tracker_type == 'MIL':
    tracker = cv.TrackerMIL_create()
if tracker_type == 'KCF':
    tracker = cv.TrackerKCF_create()
if tracker_type == 'TLD':
    tracker = cv.TrackerTLD_create()
if tracker_type == 'MEDIANFLOW':
    tracker = cv.TrackerMedianFlow_create()
if tracker_type == 'GOTURN':
    tracker = cv.TrackerGOTURN_create()
if tracker_type == 'MOSSE':
    tracker = cv.TrackerMOSSE_create()
if tracker_type == "CSRT":
    tracker = cv.TrackerCSRT_create()

# Configure depth and color streams
pipeline = rs.pipeline()
config = rs.config()

# Get device product line for setting a supporting resolution
pipeline_wrapper = rs.pipeline_wrapper(pipeline)
pipeline_profile = config.resolve(pipeline_wrapper)
device = pipeline_profile.get_device()
device_product_line = str(device.get_info(rs.camera_info.product_line))

clipping_distance = 1 / device.first_depth_sensor().get_depth_scale()

found_rgb = False
for s in device.sensors:
    if s.get_info(rs.camera_info.name) == 'RGB Camera':
        found_rgb = True
        break
if not found_rgb:
    print("The demo requires Depth camera with Color sensor")
    exit(0)

config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)

if device_product_line == 'L500':
    config.enable_stream(rs.stream.color, 960, 540, rs.format.bgr8, 30)
else:
    config.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)

# Start streaming
profile = pipeline.start(config)

# Getting the depth sensor's depth scale (see rs-align example for explanation)
depth_sensor = profile.get_device().first_depth_sensor()
depth_scale = depth_sensor.get_depth_scale()
print("Depth Scale is: " , depth_scale)

# We will be removing the background of objects more than
#  clipping_distance_in_meters meters away
clipping_distance_in_meters = 1 #1 meter
clipping_distance = clipping_distance_in_meters / depth_scale

# Create an align object
# rs.align allows us to perform alignment of depth frames to others frames
# The "align_to" is the stream type to which we plan to align depth frames.
align_to = rs.stream.color
align = rs.align(align_to)

# blank_image = np.zeros((640,1280,3), dtype=np.uint8)

for i in range(30):
    frames = pipeline.wait_for_frames()

color_frame = frames.get_color_frame()
color_image = np.asanyarray(color_frame.get_data())

# Uncomment the line below to select a different bounding box
bbox = cv.selectROI(color_image, False)

# Initialize tracker with first frame and bounding box
ok = tracker.init(color_image, bbox)

try:
    while True:

        # Wait for a coherent pair of frames: depth and color
        frames = pipeline.wait_for_frames()

        # Align the depth frame to color frame
        aligned_frames = align.process(frames)

        # Get aligned frames
        aligned_depth_frame = aligned_frames.get_depth_frame() # aligned_depth_frame is a 640x480 depth image
        color_frame = aligned_frames.get_color_frame()

        if not aligned_depth_frame or not color_frame:
            continue

        # Convert images to numpy arrays
        depth_image = np.asanyarray(aligned_depth_frame.get_data())
        color_image = np.asanyarray(color_frame.get_data())
        v,h = depth_image.shape
        blank_image = np.zeros((v, 2*h, 3), dtype=np.uint8)

        ok, bbox = tracker.update(color_image)
        # Draw bounding box
        if ok:
            # Tracking success
            p1 = (int(bbox[0]), int(bbox[1]))
            p2 = (int(bbox[0] + bbox[2]), int(bbox[1] + bbox[3]))
            cv.rectangle(color_image, p1, p2, (255,0,0), 2, 1)
        else :
            # Tracking failure
            cv.putText(color_image, "Tracking failure detected", (100,80), cv.FONT_HERSHEY_SIMPLEX, 0.75,(0,0,255),2)

        # Apply colormap on depth image (image must be converted to 8-bit per pixel first)
        depth_colormap = cv.applyColorMap(cv.convertScaleAbs(depth_image, alpha=0.03), cv.COLORMAP_JET)

        depth_colormap_dim = depth_colormap.shape
        color_colormap_dim = color_image.shape

        grey_color = 153
        depth_image_3d = np.dstack((depth_image, depth_image, depth_image))
        color_image = np.where((depth_image_3d > clipping_distance) | (depth_image_3d <= 0), grey_color, color_image)
        # If depth and color resolutions are different, resize color image to match depth image for display
        if depth_colormap_dim != color_colormap_dim:
            resized_color_image = cv.resize(color_image, dsize=(depth_colormap_dim[1], depth_colormap_dim[0]), interpolation=cv.INTER_AREA)
            images = np.hstack((resized_color_image, depth_colormap))
            images = np.vstack((images, blank_image))
        else:
            images = np.hstack((color_image, depth_colormap))
            images = np.vstack((images, blank_image))

        # Show images
        cv.namedWindow('RealSense', cv.WINDOW_AUTOSIZE)
        cv.imshow('RealSense', images)

        # exit program by pressing key 'esc'
        if cv.waitKey(1) == 27:
            break

finally:
    # Stop streaming
    pipeline.stop()


import requests
import json
w=[]
f=open('a2b-input.txt',mode='r',encoding='utf-8')
while 1:
    date=f.readline()
    if not date:
        break
    w.append(date[0:len(date)-1])
aid_list=[]
for av in w:
    url="https://api.bilibili.com/x/web-interface/view?aid="+str(av)
    eww=requests.get(url).text
    json_text = json.loads(eww)
    print(json_text)
    aid_list.append(json_text["data"]['bvid'])
f=open("a2b-output.txt", "w", encoding="utf-8")
for i in aid_list:
    qqq=str(i)+'\n'
    f.write(qqq)
f.close()


import pandas as pd
from konlpy.tag import Okt
import re
from collections import Counter
from wordcloud import WordCloud
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

okt = Okt()

def insta_morph(data):
    data_list = []
    data_list.append(data)
    df_set = pd.concat(data_list)
    df_set.duplicated(["게시글"])
    df = df_set.drop_duplicates(["게시글"], keep="first")

    new_list = []
    for row in df["게시글"]:
        if (row != ''):
            new = re.sub('[^#A-Za-z0-9ㄱ-ㅣ가-힣]+', ' ', str(row))
        if (new == ''):
            del new
        else:
            morph = okt.pos(new)
            new_list.append(morph)

    return new_list

def googlemap_morph(data):
    data_list = []
    data_list.append(data)
    df_set = pd.concat(data_list)
    df_set.duplicated(["review_text"])
    df = df_set.drop_duplicates(["review_text"], keep="first")

    new_list=[]
    for row in df["review_text"]:
        if(row !=''):
            new = re.sub('[^#A-Za-z0-9ㄱ-ㅣ가-힣]+', ' ',str(row))
            new = re.sub('원문|번역|google|제공', '', str(row)) #번역 리뷰에 뜨는 문구 제거
        if (new==''):
            del new
        else:

            morph = okt.pos(new)
            new_list.append(morph)

    return new_list

def insta_list(new_list):
    count_list1 = []
    count_list2 = []
    for sentence in new_list:
        for word, tag in sentence:
            if (tag in ['Noun', 'Adjective'] and len(word) > 1):  # 동사가 아니고 두 글자 이상일 때
                count_list1.append((word))
            if tag in 'Hashtag' and len(word) > 1:
                count_list2.append((word))

    counts1 = Counter(count_list1)
    counts2 = Counter(count_list2)
    words = counts1.most_common(100)
    hashtags = counts2.most_common(100)

    common_list=[]

    for i in range(100):
        m = okt.pos(words[i][0])
        common_list.append((words[i][0], m[0][1], words[i][1], hashtags[i][0], hashtags[i][1]))
    return words, hashtags, common_list

def googlemap_list(new_list): #구글맵 리뷰
    count_list1 = []
    for sentence in new_list:
        for word, tag in sentence:
            if (tag in ['Noun', 'Adjective'] and len(word) > 1):  # 동사가 아니고 두 글자 이상일 때
                count_list1.append((word))

    counts1 = Counter(count_list1)
    words = counts1.most_common(100)
    common_list = []

    for i in range(100):
        m = okt.pos(words[i][0])
        common_list.append((words[i][0], words[i][1], m[0][1]))
    return words, common_list

def wordcloud(words):
    wc = WordCloud(
        font_path='C:\Windows\Fonts\MALGUNBD.TTF',
        width=800,
        colormap='Accent_r',
        height=800,
        background_color="White")

    wc.generate_from_frequencies(dict(words))
    return wc

def save_insta_file(key,year, wc, common_list):
    wc.to_file('wordcloud_insta_' + key + '_' + year + '.png')
    word_count = pd.DataFrame(common_list, columns=['단어', '품사', '빈도수', '해시태그', '개수'])
    word_count.to_csv('instagram_' + key + '_' + year + '_most_common.csv', mode='wt', encoding='utf-8-sig',
                      header=True, index=False)
    xpos = np.arange(len(word_count['해시태그']))
    xtext = list(word_count["해시태그"])
    return word_count, xpos, xtext

def save_googlemap_file(key,year, wc, common_list):
    wc.to_file('wordcloud_googlemap_'+key+'_'+year+'.png')
    word_count=pd.DataFrame(common_list, columns=['단어', '빈도수', '품사'])
    word_count.to_csv('googlemap_'+key+'_'+year+'_most_common.csv', mode='wt', encoding='utf-8-sig', header=True, index=False)
    xpos = np.arange(len(word_count['단어']))
    xtext = list(word_count["단어"])
    return word_count,xpos,xtext

def draw_googlemap_graph(word_count, xpos, xtext, key, year):

    plt.title(year+ '년 ' + key+ "park most common words(googlemap)")
    plt.xlabel('단어')
    plt.ylabel('빈도수')
    plt.yticks(xpos, xtext)
    plt.ylim(0, 10)
    plt.barh(word_count['단어'], word_count['빈도수'], color='green', height=0.7)
    plt.tight_layout()
    plt.savefig('bar_googlemap_' + key + '_' + year + '.png')
    return
def draw_insta_graph(word_count, xpos, xtext, key, year):
    plt.title(year + '년 ' + key + "park most common words(instagram)")
    plt.xlabel('해시태그')
    plt.ylabel('개수')
    plt.yticks(xpos, xtext)
    plt.ylim(0, 10)
    plt.barh(word_count['해시태그'], word_count['개수'], color='green', height=0.7)
    plt.tight_layout()
    plt.savefig('bar_instagram_' + key + '_' + year + '.png')

key=['daejeo','samrak']
year=['2018','2019']

googlemap_data=[pd.read_csv('googlemap_daejeo_2018.csv', index_col=False),
        pd.read_csv('googlemap_daejeo_2019.csv', index_col=False),
         pd.read_csv('googlemap_samrak_2018.csv', index_col=False),
          pd.read_csv('googlemap_samrak_2019.csv', index_col=False)]

insta_data=[pd.read_csv('instagram_daejeo_2018.csv', index_col=False),
            pd.read_csv('instagram_daejeo_2019.csv', index_col=False),
            pd.read_csv('instagram_samrak_2018.csv', index_col=False),
            pd.read_csv('instagram_samrak_2019.csv', index_col=False)]

font_name = mpl.font_manager.FontProperties(fname='C:\Windows\Fonts\MALGUNBD.TTF').get_name()
mpl.rc('font', family=font_name)

k=0
for i in range (len(key)):
    for j in range(len(year)):
        googlemap_review = googlemap_morph(googlemap_data[k])
        common_words, common_list = googlemap_list(googlemap_review)
        wc=wordcloud(common_words)
        word_count, xpos, xtext = save_googlemap_file(key[i], year[j], wc, common_list)
        draw_googlemap_graph(word_count, xpos, xtext, key[i], year[j])
        plt.cla()
        k=k+1

p=0
for i in range (len(key)):
    for j in range(len(year)):
        insta_review = insta_morph(insta_data[p])
        common_words, common_tag, common_list = insta_list(insta_review)
        wc=wordcloud(common_words)
        word_count, xpos, xtext = save_insta_file(key[i], year[j], wc, common_list)
        draw_insta_graph(word_count, xpos, xtext, key[i], year[j])
        plt.cla()
        p=p+1


from sqlalchemy import create_engine
from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey, text
# Declarative mapping # Doing the same thing the easy way:
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, backref

engine = create_engine('sqlite:///library2.db', echo=True) # create an Engine object # connection to the database
                                                            #Note that echo=True is also passed here, this tells the engine object to log all the SQL it executed to sys.stdout.
Base = declarative_base()

class Author(Base):
    __tablename__ = 'authors'
    id = Column(Integer, primary_key=True)
    name = Column(String)

    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return self.name

class Book(Base):
    __tablename__ = 'books'
    id = Column(Integer, primary_key=True)
    title = Column(String)
    description = Column(String)
    author_id = Column(Integer, ForeignKey('authors.id'))
    author = relationship(Author, backref=backref('books', order_by=title))

    def __init__(self, title, description, author):
        self.title = title
        self.description = description
        self.author = author

    def __str__(self):
        return f"{self.id} {self.title} {self.description} {self.author}"

    def __repr__(self):
        return f"{self.id} {self.title}"

Base.metadata.create_all(engine) # create tables

##################################
# Creating instances
# У попередньому блоці ми створили суто саму базу даних,
# У наступному блоці - для виконання запитів ми використовуватимемо Session() - об'єкт через, який ми робитимемо транзакції
# Щоб створити Session(), потірбно з orm дістати sessionmaker

from sqlalchemy.orm import sessionmaker

Session = sessionmaker(bind=engine) # bound session # генеруємо сесію, команда - відай мені такий пулінг сесії на engine - наша БД
session = Session()

# створюємо об'єкти зі сторони Python
# author_1 = Author('Richard Dawkins')
# author_2 = Author('Matt Ridley')
# book_1 = Book('The Red Queen', 'A popular science book', author_2)
# book_2 = Book('The Selfish Gene', 'A popular science book', author_1)
# book_3 = Book('The Blind Watchmaker', 'The theory of evolutio', author_1)

# # на цьому етапі ми лише створюємо транзакцію - кілька запити на додавання
# session.add(author_1)
# session.add(author_2)
# session.add(book_1)
# session.add(book_2)
# session.add(book_3)
# # or simply session.add_all([author_1, author_2, book_1, book_2, book_3])

# print(book_3)
# session.commit()

# # а ось вже тут commit() внисе ці транзакції до БД
# # session.commit() # це як команда push в git # також ця команда повертає об'єктові id

# book_3.description = 'The theory of evolution' # update the object
# # book_3 in session # check whether the object is in the session
# # True
# print(book_3)
# # book_3.id = 2 # не можна так робити, адже id поле автоінкриментне, тому його не вийде засетати
# session.commit()

####################
# Querying

query = session.query(Book).order_by(Book.id) # returns a query
print(query) # FROM books ORDER BY books.id
books = session.query(Book).order_by(Book.id).all() # returns an object-list
print(books)

for book in books:
    print(book)

# return all book objects where title == 'The Selfish Gene'
session.query(Book).filter(Book.title == 'The Selfish Gene').order_by(Book.id).all()
# using LIKE
session.query(Book).filter(Book.title.like('The%')).order_by(Book.id).all()
query = session.query(Book).filter(Book.id == 9).order_by(Book.id)

query.count() # returns 0L
query.all() # returns an empty list !!
query.first() # returns None
query.one() # raises NoResultFound exception !!

query = session.query(Book).filter(Book.id == 1).order_by(Book.id)

book_1 = query.one()
book_1.description # returns u'A popular science book'
book_1.author.books # returns a list of Book-objects representing all the books from the same author.
# get a list of all Book-instances where the author's name is 'Richard Dawkins'
session.query(Book).filter(Book.author_id==Author.id).filter(Author.name=='Richard Dawkins').all()
session.query(Book).join(Author).filter(Author.name=='Richard Dawkins').all()

# Ми також можемо писати квері на чистому SQL
session.query(Book).\
    from_statement('SELECT b.* FROM books b, authors a WHERE b.author_id = a.id AND a.name=:name').\
    params(name='Richard Dawkins').all()


# -*- coding: utf-8 -*-
"""
Created on Wed May 11 15:39:29 2016

@author: rahma.chaabouni
"""
from __future__ import division

"""
  La régression logistique est utilisée pour la couche de sortie du réseau
  de neurones.
  L'équation de ce modèle est:
  y_{pred} = argmax_i P(Y=i|x,W,b)

"""
import numpy as np
import theano
import theano.tensor as T

class LogisticRegression(object):
    """
    Les paramètres de la régression:
    'W': poids
    'b' biais
    """

    def __init__(self, input, n_in, n_out):
        """ Initialisation des paramètres

        input: theano.tensor.TensorType -> variable simbolique représentant
               les entrées
        n_in: int -> nombre des unités de la couche d'entrée
        n_out: int -> nombre des unités de la couche de sortie

        """
        self.W = theano.shared(
            value=np.zeros(
                (n_in, n_out),
                dtype=theano.config.floatX
            ),
            name='W',
            borrow=True
        )
        self.b = theano.shared(
            value=np.zeros(
                (n_out,),
                dtype=theano.config.floatX
            ),
            name='b',
            borrow=True
        )

        self.p_y_given_x = T.nnet.softmax(T.dot(input, self.W) + self.b)
        self.y_pred = T.argmax(self.p_y_given_x, axis=1)
        self.params = [self.W, self.b]

        self.input = input

    def negative_log_likelihood(self, y,w):
        """Retourner la moyenne du "negative log-likelihood" des prédictions

        y: theano.tensor.TensorType -> Les vrais labels
        w: theano.tensor.TensorType -> Les poids associés à chaque label (
           définir la distribution)
        """
        return -T.sum(w*T.log(self.p_y_given_x)[T.arange(y.shape[0]), y])

    def quadraticLoss(self, y, w):

        return T.sum(w*((self.y_pred -y)*(self.y_pred -y)))

    def errors(self, y,w):
        """Retourner l'erreur de classification des prédictions
        y: theano.tensor.TensorType -> Les vrais labels
        w: theano.tensor.TensorType -> Les poids associés à chaque label (
           définir la distribution)
        """

        # check if y has same dimension of y_pred
        if y.ndim != self.y_pred.ndim:
            raise TypeError(
                'y should have the same shape as self.y_pred',
                ('y', y.type, 'y_pred', self.y_pred.type)
            )
        # check if y is of the correct datatype
        if y.dtype.startswith('int'):
            # the T.neq operator returns a vector of 0s and 1s, where 1
            # represents a mistake in prediction
            return T.sum(w*T.neq(self.y_pred, y))
        else:
            raise NotImplementedError()

    def incorrects(self, y):
        """Return a vector 0/1 for false or true predictions"""
        # check if y has same dimension of y_pred
        if y.ndim != self.y_pred.ndim:
            raise TypeError(
                'y should have the same shape as self.y_pred',
                ('y', y.type, 'y_pred', self.y_pred.type)
            )
        # check if y is of the correct datatype
        if y.dtype.startswith('int'):
            # the T.neq operator returns a vector of 0s and 1s, where 1
            # represents a mistake in prediction
            return T.neq(self.y_pred, y)
        else:
            raise NotImplementedError()

def displayimage(index, x, y, type_donnees = 'tensor', pred = None, string= None):
    """ Afficher les images x corresondant aux indices "index"
        index: vecteur d'entiers -> les indices des exemples à afficiher
        x: vecteur de matrices -> la matrice des features
        y: vecteur d'entier -> Les vrais labels
        type_donnees: string -> si 'tensor' x et y sont des theano.tensor, sinon
                      des numpy
        pred: vecteur -> Si pred != None, la prédiction et la vrai valeur seront
                         affichés
        string: string -> Si string != None l'image sera enregistrée en la nommant
    """

    import pylab as pl

    if (type_donnees == 'tensor'):
        y = y.eval()
        x = x.get_value()

    if (len(index)> 16):
        index = index[0:16]

    for count, i in enumerate(index):
        image = x[i]
        rrows = np.int(np.sqrt(len(index)))
        pl.subplot(rrows, np.int(len(index)/rrows), count+1).imshow(image.reshape(28, 28), cmap=pl.cm.gray)
        pl.title('vrai: %s et prédit: %s' % (y[i], pred[i]))
        pl.axis('off')

    if (string != None):
        pl.savefig(string)
    else:
        pl.show()

def compute_error_confMatrix(df, normalisation):
    sum_diag = sum(np.diag(df))
    return (1 - (sum_diag/normalisation))

def save_object(obj, filename):
    import pickle
    with open(filename, 'wb') as output:
        pickle.dump(obj, output, pickle.HIGHEST_PROTOCOL)

def display_marge(marge, color, ax):
    values, base = np.histogram(marge, bins=40)
    cumulative = np.cumsum(values)
    ax.plot(base[:-1], cumulative, color = color)
#    return ax


#!/usr/bin/env python3

#ENPM673 Spring 2022
#Section 0101
#Jerry Pittman, Jr. UID: 117707120
#jpittma1@umd.edu
#Project #2 Functions

import numpy as np
import cv2
import scipy
from scipy import fft, ifft
from numpy import histogram_bin_edges, linalg as LA
import matplotlib.pyplot as plt
import sys
import math
import os
from os.path import isfile, join

'''Problem 1 Functions'''
def convertImagesToMovie(folder):
    fps =   3
    fourcc = cv2.VideoWriter_fourcc(*'XVID')
    videoname=('night_drive')
    frames = []

    files = [f for f in os.listdir(folder) if isfile(join(folder, f))]

    #pictures were not in order, sadly
    files.sort(key = lambda x: x[5:-4])
    files.sort()

    for i in range(len(files)):
        filename=folder + files[i]
        img = cv2.imread(filename)
        height, width, layers = img.shape
        size = (width,height)
        # cv2.imshow('image', img)
        # print("size is ", size)
        if img is not None:
            frames.append(img)
        else:
            print("Failed to read")

    video = cv2.VideoWriter(str(videoname)+".avi",fourcc, fps, size)

    for i in range(len(frames)):
        # writing to a image array
        video.write(frames[i])

    #convert heightxwidth from 370,1224 to 480x640so divisible by 8
    cap=cv2.VideoCapture(str(videoname)+".avi")
    size = (640, 480)
    # size = (1280, 720)
    video_new = cv2.VideoWriter(str(videoname)+".avi",fourcc, fps, size)

    while True:
        ret,frame_new=cap.read()
        if ret==True:
            b=cv2.resize(frame_new,size,fx=0,fy=0, interpolation = cv2.INTER_CUBIC)
            video_new.write(b)
        else:
            break
    video_new.release()
    video.release()
    cap.release()
    cv2.destroyAllWindows()

    return video_new

def createHistogramFigure(img, name):

    plt.hist(img.ravel(),256,[0,256])
    # plt.show()
    plt.savefig(name)
    print("Histogram figure saved as: ", name)

def createHistogram(input):
    hist_vals = list()

    for i in range(256):
        c = np.where(input == i)
        hist_vals.append( [ i , len(c[0]) ] )

    return hist_vals

def conductHistogramEqualization(img):
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

    #taking the V channel of the hsv image
    vlist = hsv[:,:,2]

    height,width = vlist.shape
    # height,width, _ = img.shape

    hist = createHistogram(vlist)

    '''Cumulative Distibution Function
    Number of pixels with intensity less than or equal to "i" intensity
    normalized by N pixels'''
    cdf = list()
    z = 0
    for i in range(len(hist)):
        z = z + (hist[i][1]/(height * width))
        cdf.append(round(z*255))

    hnew = np.asarray(cdf)

    #Equalize Image based on CDF results
    #----Modifiy Images of video----
    hsv[:,:,2] = hnew[hsv[:,:,2]]

    color = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)

    # cv2.imshow('HSV Equalized',color)

    return hist, color

def conductAdaptiveHistogramEqualization(image):
    # img = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    # image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    # print("img.shape: ",img.shape)
    # img=image.copy

    '''Define Clip value and search window'''
    clipLimit=0.001
    nrBins=256

    kernel_size = tuple([max(s // 8, 1) for s in image.shape])
    # kernel_size = tuple([max(s // 8, 1) for s in img.shape])
    # print("kernel size: ", kernel_size) #60,80, 1

    kernel_size = [int(k) for k in kernel_size]
    # print("kernel size: ", kernel_size) #60,80, 1

    # grayscaleLevels=7800   #as many grayscale levels as possible; this gave me best results
    grayscaleLevels=2**14   #as many grayscale levels as possible; this gave me best results
    # grayscaleLevels=height*width
    ndim = image.ndim
    dtype = image.dtype

    # pad the image such that the shape in each dimension
    # - is a multiple of the kernel_size and
    # - is preceded by half a kernel size
    pad_start_per_dim = [k // 2 for k in kernel_size]

    pad_end_per_dim = [(k - s % k) % k + int(np.ceil(k / 2.))
                       for k, s in zip(kernel_size, image.shape)]

    image = np.pad(image, [[p_i, p_f] for p_i, p_f in
                           zip(pad_start_per_dim, pad_end_per_dim)],
                   mode='reflect')

    # determine gray value bins
    bin_size = 1 + grayscaleLevels // nrBins
    lut = np.arange(grayscaleLevels, dtype=np.min_scalar_type(grayscaleLevels))
    lut //= bin_size

    image = lut[image]

    # calculate graylevel mappings for each contextual region
    # rearrange image into flattened contextual regions
    ns_hist = [int(s / k) - 1 for s, k in zip(image.shape, kernel_size)]
    hist_blocks_shape = np.array([ns_hist, kernel_size]).T.flatten()
    hist_blocks_axis_order = np.array([np.arange(0, ndim * 2, 2),
                                       np.arange(1, ndim * 2, 2)]).flatten()

    hist_slices = [slice(k // 2, k // 2 + n * k)
                   for k, n in zip(kernel_size, ns_hist)]

    hist_blocks = image[tuple(hist_slices)].reshape(hist_blocks_shape)
    hist_blocks = np.transpose(hist_blocks, axes=hist_blocks_axis_order)
    hist_block_assembled_shape = hist_blocks.shape
    hist_blocks = hist_blocks.reshape((np.product(ns_hist), -1))

    # Calculate actual clip limit
    if clipLimit > 0.0:
        clim = int(np.clip(clipLimit * np.product(kernel_size), 1, None))
    else:
        # largest possible value, i.e., do not clip (AHE)
        clim = np.product(kernel_size)

    # smallestClip=np.product(kernel_size)
    # print("smallest clip, ", smallestClip)
    # print("current clip is ", int(np.clip(clipLimit * np.product(kernel_size), 1, None)))
    # clim=40 #openCV is 40 by default, supposedly

    hist = np.apply_along_axis(np.bincount, -1, hist_blocks, minlength=nrBins)

    #Clip_histogram
    clipped_hist = np.apply_along_axis(clipHistogram, -1, hist, clip_limit=clim)

    '''Create look-up table (LUT) is used to convert the dynamic range
    of the input image into the desired output dynamic range.'''
    #Map Histogram
    hist_map = createLUT(clipped_hist, 0, grayscaleLevels - 1, np.product(kernel_size))
    hist_map = hist_map.reshape(hist_block_assembled_shape[:ndim] + (-1,))

    # duplicate leading mappings in each dimension
    map_array = np.pad(hist_map,
                       [[1, 1] for _ in range(ndim)] + [[0, 0]],
                       mode='edge')

    '''Perform multilinear interpolation of graylevel mappings'''
    '''To remove artifacts after Adaptive Histogram Equalization'''
    # rearrange image into blocks for vectorized processing
    ns_proc = [int(s / k) for s, k in zip(image.shape, kernel_size)]
    blocks_shape = np.array([ns_proc, kernel_size]).T.flatten()
    blocks_axis_order = np.array([np.arange(0, ndim * 2, 2),
                                  np.arange(1, ndim * 2, 2)]).flatten()
    blocks = image.reshape(blocks_shape)
    blocks = np.transpose(blocks, axes=blocks_axis_order)
    blocks_flattened_shape = blocks.shape
    blocks = np.reshape(blocks, (np.product(ns_proc),
                                 np.product(blocks.shape[ndim:])))

    # calculate interpolation coefficients
    coeffs = np.meshgrid(*tuple([np.arange(k) / k
                                 for k in kernel_size[::-1]]), indexing='ij')
    coeffs = [np.transpose(c).flatten() for c in coeffs]
    inv_coeffs = [1 - c for dim, c in enumerate(coeffs)]

    # sum over contributions of neighboring contextual
    # regions in each direction
    result = np.zeros(blocks.shape, dtype=np.float32)
    for iedge, edge in enumerate(np.ndindex(*([2] * ndim))):

        edge_maps = map_array[tuple([slice(e, e + n)
                                     for e, n in zip(edge, ns_proc)])]
        edge_maps = edge_maps.reshape((np.product(ns_proc), -1))

        # apply map
        edge_mapped = np.take_along_axis(edge_maps, blocks, axis=-1)

        # interpolate
        edge_coeffs = np.product([[inv_coeffs, coeffs][e][d]
                                  for d, e in enumerate(edge[::-1])], 0)

        result += (edge_mapped * edge_coeffs).astype(result.dtype)

    result = result.astype(dtype)

    # rebuild result image from blocks
    result = result.reshape(blocks_flattened_shape)
    blocks_axis_rebuild_order =\
        np.array([np.arange(0, ndim),
                  np.arange(ndim, ndim * 2)]).T.flatten()
    result = np.transpose(result, axes=blocks_axis_rebuild_order)
    result = result.reshape(image.shape)

    # undo padding
    unpad_slices = tuple([slice(p_i, s - p_f) for p_i, p_f, s in
                          zip(pad_start_per_dim, pad_end_per_dim,
                              image.shape)])
    result = result[unpad_slices]

    # result=(img_CLAHE).astype(np.uint8)
    # color = cv2.cvtColor(result, cv2.COLOR_HSV2BGR)

    return hist, clipped_hist, result
    # return hist, clipped_hist, color
    # return result

def clipHistogram(hist, clip_limit):
    """Perform clipping of the histogram and redistribution of bins.
    The histogram is clipped and the number of excess pixels is counted.
    Afterwards the excess pixels are equally redistributed across the
    whole histogram
    """
    # calculate total number of excess pixels
    excess_mask = hist > clip_limit
    excess = hist[excess_mask]
    n_excess = excess.sum() - excess.size * clip_limit
    hist[excess_mask] = clip_limit

    # Second part: clip histogram and redistribute excess pixels in each bin
    bin_incr = n_excess // hist.size  # average binincrement
    upper = clip_limit - bin_incr  # Bins larger than upper set to cliplimit

    low_mask = hist < upper
    n_excess -= hist[low_mask].size * bin_incr
    hist[low_mask] += bin_incr

    mid_mask = np.logical_and(hist >= upper, hist < clip_limit)
    mid = hist[mid_mask]
    n_excess += mid.sum() - mid.size * clip_limit
    hist[mid_mask] = clip_limit

    while n_excess > 0:  # Redistribute remaining excess
        prev_n_excess = n_excess
        for index in range(hist.size):
            under_mask = hist < clip_limit
            step_size = max(1, np.count_nonzero(under_mask) // n_excess)
            under_mask = under_mask[index::step_size]
            hist[index::step_size][under_mask] += 1
            n_excess -= np.count_nonzero(under_mask)
            if n_excess <= 0:
                break
        if prev_n_excess == n_excess:
            break

    return hist

def createLUT(histogram, min_value, max_value, pixels):
    '''Cumulutative sum of histogram bins'''
    out = np.cumsum(histogram, axis=-1).astype(float)
    out *= (max_value - min_value) / pixels
    out += min_value
    np.clip(out, a_min=None, a_max=max_value, out=out)

    return out.astype(int)

'''Problem 3 Functions'''
def solveHomographyAndWarp(img):
    source = np.array([[560, 50], [145, 220],[1180, 220], [725, 50]])#main

    dest = np.array([[0, 0], [0, 500], [200, 500],[200, 0]])

    H , status = cv2.findHomography(source, dest)

    new_img = cv2.warpPerspective(img, H, (200,500))

    return new_img

#Uses inverse homography to unwarp
def unwarpImage(img, s0, s1):

    source = np.array([[560, 50], [145, 220],[1180, 220], [725, 50]])#main

    dest = np.array([[0, 0], [0, 500], [200, 500],[200, 0]])

    H , status = cv2.findHomography(source, dest)

    new_img = cv2.warpPerspective(img, np.linalg.inv(H), (s1,s0))

    return new_img

###--Solves for histogram and max of each column/lane---###
def histogram(img):

    hist_vals = list()
    index = list()

    for i in range(img.shape[1]):
        z = np.where(img[:,i] > 0)
        hist_vals.append(len(z[0]))
        index.append(i)

    tmp_1 = hist_vals[:120]
    tmp_2 = hist_vals[120:]
    max1 = max(tmp_1)
    max2 = max(tmp_2)
    col1 = hist_vals.index(max1)
    col2 = hist_vals.index(max2)

    # bins=200
    # plt.plot(index,hist_vals, bins)
    # plt.show()
    # plt.savefig("prob3_histogram.png")
    return col1, col2
    # return col1, col2, index, hist_vals, bins

def solvePolygon(left, right):
    x = np.arange(500)
    x_sqr = np.square(x)
    ones = np.ones(500)

    x_pts = np.stack((x_sqr,x,ones))

    #calculating y = dot product of the coefficients and x
    points_left = np.dot(left,x_pts).astype(np.uint8)
    points_right = np.dot(right,x_pts).astype(np.uint8)

    pnts_left = np.vstack((points_left,x)).T
    pnts_right = np.vstack((points_right,x)).T

    #reversing the right lane y points in order to plot using polylines
    pnts_right[:,0] = pnts_right[::-1,0]
    pnts_right[:,1] = pnts_right[::-1,1]

    points = np.concatenate((pnts_left,pnts_right), axis = 0)

    return points, pnts_left, pnts_right

def addCurveDirectionText(center, left, right, img, curve):
    # def direction(img_center,left_max,right_max,res_img,radius_dir):

    l_center = left + (right - left)/2
    dev = l_center - center

    #Straight
    if ( -14 < dev < -9.5):
        img = cv2.putText(img,'Straight',(50,50),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,255),2,cv2.LINE_AA)
        img = cv2.putText(img,"ROC {}".format(curve),(50,80),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,255),2,cv2.LINE_AA)
    #Right
    elif ( -9.5 < dev < -3):
        img = cv2.putText(img,'Right',(50,50),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,255),2,cv2.LINE_AA)
        img = cv2.putText(img,"ROC {}".format(curve),(50,80),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,255),2,cv2.LINE_AA)
    #Left
    else:#( 6 < dev )
        img = cv2.putText(img,'Left',(50,50),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,255),2,cv2.LINE_AA)
        img = cv2.putText(img,"ROC {}".format(curve),(50,80),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,255),2,cv2.LINE_AA)


r"""
STB dataset
A Hand joint Tracking Benchmark from Stereo Matching, ICIP 2017
"""

import math
import os
import pickle

import PIL
import cv2
import matplotlib.pyplot as plt
import numpy as np
import scipy.io as sio
import torch.utils.data
from PIL import Image
from termcolor import colored
from tqdm import tqdm

import config as cfg
import utils.handutils as handutils

CACHE_HOME = os.path.expanduser(cfg.DEFAULT_CACHE_DIR)

# some globals, ugly but work
sk_fx_color = 607.92271
sk_fy_color = 607.88192
sk_tx_color = 314.78337
sk_ty_color = 236.42484

bb_fx = 822.79041
bb_fy = 822.79041
bb_tx = 318.47345
bb_ty = 250.31296

sk_rot_vec = [0.00531, -0.01196, 0.00301]
sk_trans_vec = [-24.0381, -0.4563, -1.2326]  # mm

snap_joint_name2id = {w: i for i, w in enumerate(cfg.snap_joint_names)}
stb_joint_name2id = {w: i for i, w in enumerate(cfg.stb_joints)}

stb_to_snap_id = [snap_joint_name2id[joint_name] for joint_name in cfg.stb_joints]

def sk_rot_mx(rot_vec):
    """
    use Rodrigues' rotation formula to transform the rotation vector into rotation matrix
    :param rot_vec:
    :return:
    """
    theta = np.linalg.norm(rot_vec)
    vector = np.array(rot_vec) * math.sin(theta / 2.0) / theta
    a = math.cos(theta / 2.0)
    b = -vector[0]
    c = -vector[1]
    d = -vector[2]
    return np.array(
        [
            [
                a * a + b * b - c * c - d * d,
                2 * (b * c + a * d),
                2 * (b * d - a * c)
            ],
            [
                2 * (b * c - a * d),
                a * a + c * c - b * b - d * d,
                2 * (c * d + a * b)
            ],
            [
                2 * (b * d + a * c),
                2 * (c * d - a * b),
                a * a + d * d - b * b - c * c
            ]
        ]
    )

def sk_xyz_depth2color(depth_xyz, trans_vec, rot_mx):
    """
    in the STB dataset: 'rotation and translation vector can transform the coordinates
                         relative to color camera to those relative to depth camera'.
    however here we want depth_xyz -> color_xyz
    a inverse transformation happen:
    T = [rot_mx | trans_vec | 0  1], Tinv = T.inv, then output Tinv * depth_xyz

    :param depth_xyz: N x 21 x 3, trans_vec: 3, rot_mx: 3 x 3
    :return: color_xyz: N x 21 x 3
    """
    color_xyz = depth_xyz - np.tile(trans_vec, [depth_xyz.shape[0], depth_xyz.shape[1], 1])
    return color_xyz.dot(rot_mx)

def stb_palm2wrist(joint_xyz):
    root = snap_joint_name2id['loc_bn_palm_L']  # 0

    index = snap_joint_name2id['loc_bn_index_L_01']  # 5
    mid = snap_joint_name2id['loc_bn_mid_L_01']  # 9
    ring = snap_joint_name2id['loc_bn_ring_L_01']  # 13
    pinky = snap_joint_name2id['loc_bn_pinky_L_01']  # 17

    def _new_root(joint_xyz, id, root_id):
        return joint_xyz[:, id, :] + \
               2.25 * (joint_xyz[:, root_id, :] - joint_xyz[:, id, :])  # N x K x 3

    joint_xyz[:, root, :] = \
        _new_root(joint_xyz, index, root) + \
        _new_root(joint_xyz, mid, root) + \
        _new_root(joint_xyz, ring, root) + \
        _new_root(joint_xyz, pinky, root)
    joint_xyz[:, root, :] = joint_xyz[:, root, :] / 4.0

    return joint_xyz

def _stb_palm2wrist(joint_xyz):
    root_id = snap_joint_name2id['loc_bn_palm_L']  # 0
    mid_root_id = snap_joint_name2id['loc_bn_mid_L_01']  # 9
    joint_xyz[:, root_id, :] = \
        joint_xyz[:, mid_root_id, :] + \
        2.2 * (joint_xyz[:, root_id, :] - joint_xyz[:, mid_root_id, :])  # N x K x 3
    return joint_xyz

def ge_palm2wrist(pose_xyz):
    root_id = snap_joint_name2id['loc_bn_palm_L']
    ring_root_id = snap_joint_name2id['loc_bn_ring_L_01']
    pose_xyz[:, root_id, :] = pose_xyz[:, ring_root_id, :] + \
                              2.0 * (pose_xyz[:, root_id, :] - pose_xyz[:, ring_root_id, :])  # N x K x 3
    return pose_xyz

class STBDataset(torch.utils.data.Dataset):
    def __init__(
            self,
            data_root,
            data_split='train',
            hand_side='right',
            njoints=21,
            use_cache=True,
            visual=False
    ):
        if not os.path.exists(data_root):
            raise ValueError("data_root: %s not exist" % data_root)
        self.name = 'stb'
        self.data_split = data_split
        self.hand_side = hand_side
        self.img_paths = []
        self.dep_paths = []
        self.joints = []
        self.kp2ds = []
        self.centers = []
        self.my_scales = []
        self.njoints = njoints  # total 21 hand parts
        self.visual = visual

        self.root_id = snap_joint_name2id['loc_bn_palm_L']
        self.mid_mcp_id = snap_joint_name2id['loc_bn_mid_L_01']
        ann_base = os.path.join(data_root, "labels")
        img_base = os.path.join(data_root, "images")
        sk_rot = sk_rot_mx(sk_rot_vec)

        self.sk_intr = np.array([
            [sk_fx_color, 0.0, sk_tx_color],
            [0.0, sk_fy_color, sk_ty_color],
            [0.0, 0.0, 1.0],
        ], dtype=np.float32)  # (3,3)

        self.sequence = []
        if data_split == 'train':
            self.sequence = [
                "B2Counting",
                "B2Random",
                "B3Counting",
                "B3Random",
                "B4Counting",
                "B4Random",
                "B5Counting",
                "B5Random",
                "B6Counting",
                "B6Random"
            ]
        elif data_split == 'test':
            self.sequence = [
                "B1Counting",
                "B1Random"
            ]
        elif data_split == 'val':
            self.sequence = [
                "B2Counting",
                "B2Random"
            ]
        elif data_split == "train_val":
            self.sequence = [
                "B3Counting",
                "B3Random",
                "B4Counting",
                "B4Random",
                "B5Counting",
                "B5Random",
                "B6Counting",
                "B6Random"
            ]
        elif data_split == "all":
            self.sequence = [
                "B1Counting",
                "B1Random",
                "B2Counting",
                "B2Random",
                "B3Counting",
                "B3Random",
                "B4Counting",
                "B4Random",
                "B5Counting",
                "B5Random",
                "B6Counting",
                "B6Random"
            ]
        else:
            raise ValueError("split {} not in [train|test|val|train_val|all]")

        self.cache_folder = os.path.join(CACHE_HOME, "my-{}".format(data_split), "stb")
        os.makedirs(self.cache_folder, exist_ok=True)
        cache_path = os.path.join(
            self.cache_folder, "{}.pkl".format(self.data_split)
        )
        if os.path.exists(cache_path) and use_cache:
            with open(cache_path, "rb") as fid:
                annotations = pickle.load(fid)
                self.img_paths = annotations["img_paths"]
                self.dep_paths = annotations["dep_paths"]
                self.joints = annotations["joints"]
                self.kp2ds = annotations["kp2ds"]
                self.centers = annotations["centers"]
                self.my_scales = annotations["my_scales"]
            print("stb {} gt loaded from {}".format(self.data_split, cache_path))
            return

        self.imgpath_list = [
            os.path.join(img_base, seq) for seq in self.sequence
        ]

        imgsk_prefix = "SK_color"
        depsk_prefix = "SK_depth_seg"

        annsk_list = [
            os.path.join(
                ann_base,
                "{}_{}.mat".format(seq, imgsk_prefix[:2])
            ) for seq in self.sequence
        ]

        self.ann_list = annsk_list

        for imgpath, ann in zip(self.imgpath_list, self.ann_list):
            ''' we only use SK image '''
            assert "SK" in ann
            ''' 1. load joint '''
            rawmat = sio.loadmat(ann)
            rawjoint = rawmat["handPara"].transpose((2, 1, 0))  # N x K x 3
            num = rawjoint.shape[0]  # N

            rawjoint = sk_xyz_depth2color(rawjoint, sk_trans_vec, sk_rot)
            # reorder idx
            joint = rawjoint[:, stb_to_snap_id, :]
            # scale to meter
            joint = joint / 1000.0
            # root from palm to wrist
            # joint = _stb_palm2wrist(joint)  # N x K x 3 # yang lixin
            joint = ge_palm2wrist(joint)  # N x K x 3  #liu hao ge // vae//
            self.joints.append(joint)

            ''' 4. load images pth '''
            for idx in range(joint.shape[0]):
                self.img_paths.append(os.path.join(
                    imgpath, "{}_{}.png".format(imgsk_prefix, idx)
                ))
                self.dep_paths.append(os.path.join(
                    imgpath, "{}_{}.png".format(depsk_prefix, idx)
                ))

        self.joints = np.concatenate(self.joints, axis=0).astype(np.float32)  ##(30000, 21, 3)

        for i in tqdm(range(len(self.img_paths))):
            joint = self.joints[i]
            kp2d_homo = self.sk_intr.dot(joint.T).T
            kp2d = kp2d_homo / kp2d_homo[:, 2:3]
            kp2d = kp2d[:, :2]
            center = handutils.get_annot_center(kp2d)

            # caculate my_scale
            dep = Image.open(self.dep_paths[i]).convert("RGB")
            rel_dep = self.real_dep_img(dep)
            mask_rel_dep = np.argwhere(rel_dep > 1e-6)
            # my_scale = handutils.get_ori_crop_scale(mask_rel_dep, side=0, kp2d=kp2d) # ori
            my_scale = handutils.get_ori_crop_scale(mask_rel_dep, side=0, kp2d=kp2d,
                                                    mask_flag=False)  # get bbx only from kp2d ,比起ori差距不大,略好一点点一点点
            my_scale = (np.atleast_1d(my_scale))[np.newaxis, :]
            self.my_scales.append(my_scale)

            self.kp2ds.append(kp2d[np.newaxis, :, :])
            self.centers.append(center[np.newaxis, :])
            # self.scales.append((np.atleast_1d(scale))[np.newaxis, :])

        self.kp2ds = np.concatenate(self.kp2ds, axis=0).astype(np.float32)  # (N, 21, 2)
        self.centers = np.concatenate(self.centers, axis=0).astype(np.float32)  # (N, 2)
        # self.scales = np.concatenate(self.scales, axis=0).astype(np.float32)  # (N, 1)
        self.my_scales = np.concatenate(self.my_scales, axis=0).astype(np.float32)  # (N, 1)
        if use_cache:
            full_info = {
                "img_paths": self.img_paths,
                "dep_paths": self.dep_paths,
                "joints": self.joints,
                "kp2ds": self.kp2ds,
                "centers": self.centers,
                # "scales": self.scales,
                "my_scales": self.my_scales,
            }
            with open(cache_path, "wb") as fid:
                pickle.dump(full_info, fid)
                print("Wrote cache for dataset stb {} to {}".format(
                    self.data_split, cache_path
                ))
        return

    def __len__(self):
        """for STB dataset total (1,500 * 2) * 2 * 6 = 36,000 samples

        :return - if is train: 30,000 samples
        :return - if is eval:   6,000 samples
        """
        return len(self.img_paths)

    def __str__(self):
        info = "STB {} set. lenth {}".format(
            self.data_split, len(self.img_paths)
        )
        return colored(info, 'blue', attrs=['bold'])

    def _is_valid(self, clr, index):
        valid_data = isinstance(clr, (np.ndarray, PIL.Image.Image))

        if not valid_data:
            raise Exception("Encountered error processing stb[{}]".format(index))
        return valid_data

    def get_sample(self, index):  # replace __getitem__
        flip = True if self.hand_side != 'left' else False

        intr = self.sk_intr

        # prepare color image
        clr = Image.open(self.img_paths[index]).convert("RGB")
        self._is_valid(clr, index)

        # prepare joint
        joint = self.joints[index].copy()  # (21, 3)

        # prepare kp2d
        kp2d = self.kp2ds[index].copy()

        center = self.centers[index].copy()
        # scale = self.scales[index].copy()

        my_scale = self.my_scales[index].copy()

        if self.dep_paths[index]:
            dep = Image.open(self.dep_paths[index]).convert("RGB")
            ### dep values now are stored as |mod|div|0| (RGB)
            self._is_valid(dep, index)
            valid_dep = True
        else:
            dep = None
            valid_dep = False

        if flip:
            clr = clr.transpose(Image.FLIP_LEFT_RIGHT)
            center[0] = clr.size[0] - center[0]
            kp2d[:, 0] = clr.size[0] - kp2d[:, 0]
            joint[:, 0] = -joint[:, 0]
            if valid_dep:
                dep = dep.transpose(Image.FLIP_LEFT_RIGHT)

            # visualization
        if self.visual:
            clr_ = np.array(clr)
            dep_ = np.array(dep)

            fig = plt.figure(figsize=(20, 20))

            plt.subplot(2, 4, 1)
            clr1 = clr_.copy()
            rel_dep = self.real_dep_img(dep_)
            mask_rel_dep = np.argwhere(rel_dep > 1e-6)
            rmin, cmin = mask_rel_dep.min(0)
            rmax, cmax = mask_rel_dep.max(0)
            cv2.rectangle(clr1, (cmin, rmin), (cmax, rmax), (255), thickness=3)
            plt.imshow(clr1)
            plt.title('Color+BounduingBox')

            plt.subplot(2, 4, 2)
            dep1 = dep_.copy()
            plt.imshow(dep1)
            plt.title('Depth')

            clr_dep = clr_ + dep_
            plt.subplot(2, 4, 3)
            plt.imshow(clr_dep)
            plt.title('Color+Depth')

            rel_dep_ = rel_dep.copy()
            plt.subplot(2, 4, 4)
            plt.imshow(rel_dep_)
            plt.title('real_Depth')

            plt.subplot(2, 4, 5)
            plt.imshow(clr.copy())
            plt.title('Color')

            plt.subplot(2, 4, 6)
            plt.imshow(clr.copy())
            plt.plot(kp2d[:, :1], kp2d[:, 1:], 'ro')
            plt.title('Color+2D annotations')

            ax = fig.add_subplot(247, projection='3d')
            plt.plot(joint[:, 0], joint[:, 1], joint[:, 2], 'yo', label='keypoint')
            plt.plot(joint[:5, 0], joint[:5, 1],
                     joint[:5, 2],
                     'r',
                     label='thumb')
            plt.plot(joint[[0, 5, 6, 7, 8, ], 0], joint[[0, 5, 6, 7, 8, ], 1],
                     joint[[0, 5, 6, 7, 8, ], 2],
                     'b',
                     label='index')
            plt.plot(joint[[0, 9, 10, 11, 12, ], 0], joint[[0, 9, 10, 11, 12], 1],
                     joint[[0, 9, 10, 11, 12], 2],
                     'b',
                     label='middle')
            plt.plot(joint[[0, 13, 14, 15, 16], 0], joint[[0, 13, 14, 15, 16], 1],
                     joint[[0, 13, 14, 15, 16], 2],
                     'b',
                     label='ring')
            plt.plot(joint[[0, 17, 18, 19, 20], 0], joint[[0, 17, 18, 19, 20], 1],
                     joint[[0, 17, 18, 19, 20], 2],
                     'b',
                     label='pinky')
            # snap convention
            plt.plot(joint[4][0], joint[4][1], joint[4][2], 'rD', label='thumb')
            plt.plot(joint[8][0], joint[8][1], joint[8][2], 'ro', label='index')
            plt.plot(joint[12][0], joint[12][1], joint[12][2], 'ro', label='middle')
            plt.plot(joint[16][0], joint[16][1], joint[16][2], 'ro', label='ring')
            plt.plot(joint[20][0], joint[20][1], joint[20][2], 'ro', label='pinky')
            # plt.plot(joint [1:, 0], joint [1:, 1], joint [1:, 2], 'o')

            plt.title('3D annotations')
            ax.set_xlabel('x')
            ax.set_ylabel('y')
            ax.set_zlabel('z')
            plt.legend()
            ax.view_init(-90, -90)
            plt.show()

        sample = {
            'index': index,
            'clr': clr,
            # 'dep': dep,  # if has renturn PIL image
            'kp2d': kp2d,
            'center': center,
            # 'scale': scale,
            'my_scale': my_scale,
            'joint': joint,
            'intr': intr,
            # 'valid_dep': valid_dep,
        }

        return sample

    def norm_dep_img(self, dep_, joint_z):
        if isinstance(dep_, PIL.Image.Image):
            dep_ = np.array(dep_)
            assert (dep_.shape[-1] == 3)  # used as "RGB"

        ''' Converts a RGB-coded depth into float valued depth. '''
        ''' dep values now are stored as |mod|div|0| (RGB) '''
        dep = (dep_[:, :, 1] * 2 ** 8 + dep_[:, :, 0]).astype('float32')
        dep /= 1000.0  # depth now in meter

        lower_bound = joint_z.min() - 0.05  # meter
        upper_bound = joint_z.max() + 0.05

        np.putmask(dep, dep <= lower_bound, upper_bound)
        min_dep = dep.min() - 1e-3  # slightly compensate
        np.putmask(dep, dep >= upper_bound, 0.0)
        max_dep = dep.max() + 1e-3
        np.putmask(dep, dep <= min_dep, max_dep)
        range_dep = max_dep - min_dep
        dep = (-1 * dep + max_dep) / range_dep
        return dep

    def real_dep_img(self, dep_):
        if isinstance(dep_, PIL.Image.Image):
            dep_ = np.array(dep_)
            assert (dep_.shape[-1] == 3)  # used as "RGB"

        ''' Converts a RGB-coded depth into float valued depth. '''
        ''' dep values now are stored as |mod|div|0| (RGB) '''
        dep = (dep_[:, :, 1] * 2 ** 8 + dep_[:, :, 0]).astype('float32')
        dep /= 1000.0  # depth now in meter

        return dep

def main():
    # go through the whole dataset
    data_split = "test"
    stb = STBDataset(
        data_root="/home/chen/datasets/STB",
        data_split=data_split,
        hand_side="right",
        visual=True
    )
    print("len(stb)=", len(stb))

    for i in tqdm(range(len(stb))):
        print("i=", i)
        data = stb.get_sample(i)

if __name__ == "__main__":
    main()


import base64
import glob
from typing import Dict

import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
from pathlib import Path
from .utils import get_dataset_info, generate_kpi_card, get_reuses, filter_reuses, generate_badge, slugify, \
    MLJAR_INFO_DICT
import json
with open("conf.json", "r") as f:
    URL_MAIN = json.load(f)["URL_MAIN"]
# Path

DATA_PATH = Path("./assets/datasets")
encoded_image_validated = base64.b64encode(open(DATA_PATH.parent.joinpath("quality.png"), 'rb').read()).decode()

def generate_etalab_cards(experiment_path: Path):
    notebook_html = [Path(p) for p in glob.glob(experiment_path.as_posix() + "/*.html")]

    if not notebook_html:
        return html.P("Aucune expÃ©rience disponible pour ce jeu de donnÃ©es ðŸ˜ž")
    list_cards = []
    for notebook in notebook_html:
        reuse_card = dbc.Card(
            [
                dbc.CardImg(src="./assets/jupyter_logo.png", top=True),
                dbc.CardBody(
                    [
                        html.H4(notebook.stem, className="card-title"),
                        html.P("A complete ML pipeline."
                               ),
                        dbc.Button("Voir expÃ©rience", color="primary", href=notebook.as_posix(), target="_blank",
                                   external_link=True),
                    ]
                ),
            ],

        )
        list_cards.append(reuse_card)
    return dbc.CardDeck(list_cards, className="w-25")

def generate_reuses_cards(resuses_dict: Dict):
    ml_reuses_dict = filter_reuses(resuses_dict)
    if not ml_reuses_dict:
        return html.P(
            "Aucune rÃ©utilisation disponible pour ce jeu de donnÃ©es ðŸ˜ž Ajoutez votre rÃ©utilisation sur data.gouv.fr !")
    list_cards = []
    for reuse in ml_reuses_dict:
        reuse_card = dbc.Card(
            [
                dbc.CardImg(src=reuse["image_thumbnail"], top=True),
                dbc.CardBody(
                    [
                        html.H4(reuse["title"], className="card-title"),
                        html.P(f"{reuse['description'][:100]}[...]", className="card-text",
                               ),
                        dbc.Button("Voir rÃ©utilisation", color="primary", href=reuse["url"], target="_blank"),
                    ]
                ),
            ],

        )
        list_cards.append(reuse_card)
    return dbc.CardDeck(list_cards, className="w-25")

def generate_table(dataset_id: str, table_type: str = "dict_data.csv"):
    display_table_path = DATA_PATH.joinpath(f"resources/{dataset_id}/{table_type}")
    if not display_table_path.exists():
        html_table = html.H5("AperÃ§u du dictionnaire des variables non disponible")
    else:
        table_df = pd.read_csv(display_table_path)
        if "leaderboard" in table_type:
            # add links to mljar table
            table_df["name"] = table_df[["name", "url"]].apply(lambda row: html.A(html.P(row["name"]), href=row["url"],
                                                                                target="_blank"), axis=1)
            table_df = table_df.drop(["url"], axis=1)
        html_table = html.Div(dbc.Table.from_dataframe(table_df, striped=True, size="sm", borderless=True),
                              style={"height": "300px", "overflow": 'auto'})
    return html_table

def generate_mljar_table(dataset_id: str, target_variable: str, base_url: str):
    display_table_path = DATA_PATH.joinpath(f"resources/{dataset_id}/automl_{slugify(target_variable)}/leaderboard.csv")
    experiment_path = display_table_path.parent
    if not display_table_path.exists():
        html_table = html.H5("MLJAR profile preview not available")
    else:
        table_df = pd.read_csv(display_table_path)
        table_df["metric_value"] = table_df["metric_value"].round(decimals=3)
        algorithm_urls = [html.A(html.P(n), href=experiment_path.joinpath(f"{n}/README.html").as_posix(),
                                 target="_blank")
                          for n in table_df.name]
        table_df["name"] = algorithm_urls
        html_table = html.Div(dbc.Table.from_dataframe(table_df, striped=True, size="sm", borderless=True),
                              style={"height": "300px", "overflow": 'auto'})
    return html_table, display_table_path.parent.joinpath("README.html")

def generate_stats_df(dataset_id: str, table_type: str = "statistics_summary.csv"):
    display_stats_path = DATA_PATH.joinpath(f"resources/{dataset_id}/{table_type}")
    if not display_stats_path.exists():
        statistics_df = html.H5("RÃ©sumÃ© statistique non disponible")
    else:
        statistics_df = pd.read_csv(display_stats_path)
    return statistics_df

def generate_dataset_page(dataset_url: str, datasets_df: pd.DataFrame):
    dataset_id = dataset_url.split("/")[-1]
    dataset_row = datasets_df[datasets_df["dgf_resource_id"] == dataset_id].iloc[0]
    if dataset_row.empty:
        return dbc.Container(html.H2("This dataset was not found in our catalog."))
    dataset_dict = get_dataset_info(dataset_row)
    dictionary_table = generate_table(dataset_dict["dgf_resource_id"], table_type="dict_data.csv")
    target_vars = list(MLJAR_INFO_DICT[dataset_id].keys())
    statistics_df = generate_stats_df(dataset_dict["dgf_resource_id"], table_type="statistics_summary.csv")
    pandas_profile_url = DATA_PATH.joinpath(f"resources/{dataset_id}/{dataset_id}_pandas_profile.html")
    experiments_url = DATA_PATH.joinpath(f"resources/{dataset_id}/our_experiments/")
    container = dbc.Container([
        # html.H4(generate_badge("Go back", url="/openml/", background_color="red")),
        html.H5(generate_badge("Accueil", url=URL_MAIN, background_color="#cadae6", new_tab=False)),
        html.Title("DGML: Data Gouv pour le Machine Learning"),
        html.H2([dataset_dict["title"],
                 html.Img(id="validated-img2",
                          src="data:image/png;base64,{}".format(encoded_image_validated),
                          style={'height': '3%', 'width': '3%', "float": "right"},
                          hidden=not dataset_dict["is_validated"]),
                 dbc.Tooltip("Ce jeu de donnÃ©es a Ã©tÃ© sÃ©lectionnÃ© et analysÃ© manuellement.",
                             target="validated-img2",
                             style={'font-size': 13}
                             )
                 ]),
        html.P(dataset_dict["description"]),
        # html.H4(generate_badge("Dataset in data.gouv.fr", url=dataset_dict['dgf_dataset_url'], background_color="#5783B7")),
        html.H4(
            generate_badge("Jeu de donnÃ©es sur data.gouv.fr", url=dataset_dict['dgf_dataset_url'],
                           background_color="#6d92ad")),
        html.Hr(style={"marginBottom": "20px"}),
        html.H3("Dictionnaire des variables"),
        dictionary_table,
        html.H4(generate_badge("Dictionnaire des variables complet", url=dataset_dict['dict_url'],
                               background_color="#6d92ad")),
        html.Hr(style={"marginBottom": "20px"}),
        html.H3("Statistiques Descriptives"),

        dbc.CardDeck(
            [
                generate_kpi_card("Nombre de colonnes", statistics_df['Number of variables']),
                generate_kpi_card("Nombre de lignes", statistics_df['Number of lines']),
                generate_kpi_card("Valeurs manquantes",
                                  f"{round(float(statistics_df['Percentage of missing cells']), 2)} %"),
                generate_kpi_card("Variables numÃ©riques", statistics_df['Numeric']),
                generate_kpi_card("Variables catÃ©gorielles", statistics_df['Categorical']),
                generate_kpi_card("Haute CardinalitÃ©", statistics_df['High cardinality variables']),
                generate_kpi_card("Haute Correlation", statistics_df['High correlation variables']),
                # generate_kpi_card("Skewed", 10),
            ]
        ),
        html.H4(
            generate_badge("Pandas Profile complet", url=pandas_profile_url.as_posix(), background_color="#6d92ad")),
        html.Hr(style={"marginBottom": "20px"}),
        html.H3("Auto Machine Learning"),
        html.Div([html.P(children=f"ModÃ¨les entraÃ®nÃ©s en utilisant comme target variable : "),
                  # dcc.Dropdown(
                  #     id="task-model-select",
                  #     options=[{"label": i, "value": i} for i in ["Classification", "Regression"]],
                  #     multi=False,
                  #     value="Classification",
                  #     clearable=False,
                  #     style={"min-width": "120px", "marginLeft": "3px"}
                  # ),
                  # html.P("using ", style={"marginLeft": "6px"}),
                  dcc.Dropdown(
                      id="target-var-model-select",
                      options=[{"label": i, "value": i} for i in target_vars],
                      multi=False,
                      value=target_vars[0],
                      clearable=False,
                      style={"min-width": "250px", "width": "auto", "marginLeft": "3px"}

                  ),
                  # html.P("as target variable.", style={"marginLeft": "6px"})

                  ], style={"display": 'flex'}),
        html.Div(id="mljar-div", style={"height": "300px", "overflow": 'auto'}),
        html.H4(id="mljar-link-badge", children=None),
        html.Hr(style={"marginBottom": "20px"}),
        html.H3("RÃ©utilisations Machine Learning (data.gouv.fr)"),
        #generate_reuses_cards(get_reuses(dataset_dict["dgf_dataset_id"])),
        html.Hr(style={"marginBottom": "20px"}),
        html.H3("Nos ExpÃ©riences"),
        # html.P("Check out our experiments on this dataset : "),
        generate_etalab_cards(experiments_url),
        # html.H4(generate_badge("See notebook", url=dataset_dict['etalab_xp_url'], background_color="#cadae6")),
        html.Hr(style={"marginBottom": "20px"}),
        # html.H3("Load Data"),
        # html.Hr(style={"marginBottom": "20px"}),
    ])

    return container