import torch
import torch.nn as nn
from torch import Tensor

class TotalLoss:
    """
    Computes total loss as described in paper: https://arxiv.org/abs/1508.06576

    ``total_loss = alpha * content_loss + beta * style_loss``

    Args:
        content_features (dict): Dictionary where key is layer index in vgg19 and value is feature maps obtained at that
                                 index for content image.
        style_features (dict): Dictionary where key is layer index in vgg19 and value is feature maps obtained at that
                               index for style image.
        alpha (float): Coefficient for content loss.
        beta (float): Coefficient for style loss.
        normalize_gram_matrix (bool): Default to True.
    """

    def __init__(self, content_features: dict[int, Tensor], style_features: dict[int, Tensor], alpha: float = 1.,
                 beta: float = 1000., normalize_gram_matrix: bool = True):
        super(TotalLoss, self).__init__()

        self.alpha = alpha
        self.beta = beta
        self.normalize_gram_matrix = normalize_gram_matrix

        self.content_losses = {
            layer_idx: ContentLoss(feature) for layer_idx, feature in content_features.items()
        }
        self.style_losses = {
            layer_idx: StyleLoss(feature, normalize_gram_matrix=self.normalize_gram_matrix)
            for layer_idx, feature in style_features.items()
        }

    def __call__(self, input_content_features: dict[int, Tensor], input_style_features: dict[int, Tensor]) \
            -> dict[str, float | Tensor]:
        """
        Computes total loss for generated image.

        Args:
            input_content_features (dict): Dictionary where key is layer index in vgg19 and value is feature maps
                                           obtained at that index for generated image.
            input_style_features (dict): Dictionary where key is layer index in vgg19 and value is feature maps obtained
                                         at that index for generated image.

        Returns:
            Tensor: Sum of weighted style and content loss
        """
        assert len(self.content_losses) == len(input_content_features), \
            f"Mismatched lengths of content features: Expected {len(self.content_losses)} got {len(input_content_features)}"
        assert len(self.style_losses) == len(input_style_features), \
            f"Mismatched lengths of style features: Expected {len(self.style_losses)} got {len(input_style_features)}"

        losses = {
            'total_content_loss': 0,
            'total_style_loss': 0,
        }

        for content_layer_idx in input_content_features:
            content_loss = self.content_losses[content_layer_idx]
            input_content_feature = input_content_features[content_layer_idx]

            loss = content_loss(input_content_feature)
            losses['total_content_loss'] += loss
            losses[f'content_loss_{content_layer_idx}'] = loss.item()

        for style_layer_idx in input_style_features:
            style_loss = self.style_losses[style_layer_idx]
            input_style_feature = input_style_features[style_layer_idx]

            loss = style_loss(input_style_feature)
            losses['total_style_loss'] += loss
            losses[f'style_loss_{style_layer_idx}'] = loss.item()

        total_content_loss = losses['total_content_loss']
        total_style_loss = losses['total_style_loss'] / len(input_style_features)  # Normalization factor w

        losses['total_loss'] = self.alpha * total_content_loss + self.beta * total_style_loss

        return losses

class ContentLoss:
    """
    Computes content loss for one (conv) layer.

    Args:
        content_feature (Tensor): Feature map from i-th conv layer of content image.
    """

    def __init__(self, content_feature: Tensor):
        super(ContentLoss, self).__init__()

        self.mse = nn.MSELoss()
        self.content_feature = content_feature.detach()

    def __call__(self, input_feature: Tensor) -> Tensor:
        """
        Computes mean-squared error between outputs of i-th layer from content image and generated image.

        Args:
            input_feature (Tensor): Feature maps from i-th conv layer of generated image.

        Returns:
            Tensor: Mean-squared error/loss
        """
        return self.mse(input_feature, self.content_feature)

class StyleLoss:
    """
    Computes style loss for one (conv) layer.

    Args:
        style_feature (Tensor): Feature maps from i-th conv layer of style image.
    """

    def __init__(self, style_feature: Tensor, normalize_gram_matrix=False):
        super(StyleLoss, self).__init__()

        self.normalize_gram_matrix = normalize_gram_matrix
        self.mse = nn.MSELoss()
        self.style_gram = gram_matrix(style_feature.detach(), normalize=self.normalize_gram_matrix)

    def __call__(self, input_feature: Tensor) -> Tensor:
        """
        Computes mean-squared error between:

        `style_feature`: Gram matrix of feature maps from i-th conv layer of style image
        and
        `input_feature`: Gram matrix of feature maps from i-th conv layer of generated image

        Args:
            input_feature: Feature maps from i-th conv layer of generated image.

        Returns:
            Tensor: Mean-squared error/loss
        """
        input_gram = gram_matrix(input_feature, normalize=self.normalize_gram_matrix)
        return self.mse(input_gram, self.style_gram)

def gram_matrix(feature_maps: Tensor, normalize: bool = False) -> Tensor:
    """
    Computes Gram matrix as inner product of feature maps (F) as F * F^T.

    Args:
        feature_maps (Tensor): Output tensor from conv layer of shape (B=batch, C=channel, H=height, W=width)
        normalize (bool): Normalize Gram matrix by its number of elements.

    Returns:
        Tensor: Gram matrix
    """
    assert isinstance(feature_maps, torch.Tensor), f"Input tensor should be a torch tensor. Got {type(feature_maps)}"
    assert feature_maps.is_floating_point(), f"Input  tensor should be a float tensor. Got {feature_maps.dtype}"
    assert feature_maps.ndim >= 3, f"Expected tensor to be a tensor image of size (..., C, H, W), got " \
                                   f"tensor.size()={feature_maps.size()}"

    if feature_maps.ndim == 4:
        B, C, H, W = feature_maps.size()
        assert B == 1, f'Batch size must be 1! Got B={B}'
    elif feature_maps.ndim == 3:
        C, H, W = feature_maps.size()

    features = feature_maps.view(C, H * W)
    g = torch.mm(features, features.t())

    if normalize:
        g = g / g.numel()

    return g


import argparse
import asyncio
import json
import pickle
from typing import Counter, Dict, List, Literal, Tuple

import aiohttp
import aiohttp.client_ws
from loguru import logger

LUOGU = "https://www.luogu.com.cn"
LUOGU_WS = "wss://ws.luogu.com.cn"

WS_ADDRESS = f"{LUOGU_WS}/ws"
POST_ADDRESS = f"{LUOGU}/paintboard/paint?token={{token}}"
GET_ADDRESS = f"{LUOGU}/paintboard/board"
USER_AGENT = (
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:96.0) Gecko/20100101 Firefox/96.0"
)

INTERVAL = 0.2

async def write(
    token: str,
    session: aiohttp.ClientSession,
    error: Dict[Tuple[int, int], int],
    history: Counter[Tuple[int, int]],
):
    await asyncio.sleep(10)
    ADDR = POST_ADDRESS.format(token=token)
    while True:
        if error:
            (x, y), c = error.popitem()
            resp = await session.post(
                ADDR, data={"x": x, "y": y, "color": data[(x, y)]}
            )
            logger.info(
                f"Posted to {(x, y)} with color {data[(x, y)]}. Code: {resp.status}"
            )
            if resp.status == 200:
                await asyncio.sleep(INTERVAL)
        else:
            await asyncio.sleep(0)

async def update(
    session: aiohttp.ClientSession,
    current: Dict[Tuple[int, int], int],
    error: Dict[Tuple[int, int], int],
    data: Dict[Tuple[int, int], int],
):
    while True:
        logger.info("Fetching data...")
        init_data = await session.get(GET_ADDRESS)
        for x, line in enumerate((await init_data.text()).split("\n")):
            for y, char in enumerate(line):
                current[(x, y)] = int(char, base=32)

        for k, v in data.items():
            if current[k] != v:
                error[k] = v
            else:
                if k in error:
                    del error[k]
        logger.warning(
            f"\nError: {len(error)} points\nCorrect: {len(data) - len(error)} points\nPercentage: {(len(data) - len(error)) / len(data) :.2%}"
        )

        logger.info("Scheduled update in 10s.")

        await asyncio.sleep(10.0)

async def ws_update(
    session: aiohttp.ClientSession,
    current: Dict[Tuple[int, int], int],
    error: Dict[Tuple[int, int], int],
    data: Dict[Tuple[int, int], int],
):
    while True:
        try:
            async with session.ws_connect(WS_ADDRESS) as ws_session:
                logger.info("Websocket online.")

                await ws_session.send_json(
                    {
                        "type": "join_channel",
                        "channel": "paintboard",
                        "channel_param": "",
                    }
                )

                while True:
                    json_data = await ws_session.receive_json()
                    if json_data["type"] == "paintboard_update":
                        x, y, c = json_data["x"], json_data["y"], json_data["color"]
                        current[(x, y)] = c
                        if (x, y) in data:
                            if c != data[(x, y)]:
                                error[(x, y)] = c
                            else:
                                if (x, y) in error:
                                    del error[(x, y)]
        except Exception:
            pass

async def main(data: Dict[Tuple[int, int], int], tokens: List[str]):

    async with aiohttp.ClientSession(headers={"User-Agent": USER_AGENT}) as session:
        current: Dict[Tuple[int, int], int] = {}
        history: Counter[Tuple[int, int]] = Counter()
        error: Dict[Tuple[int, int], int] = {}

        logger.info("Initializing connection...")

        asyncio.create_task(update(session, current, error, data))

        asyncio.create_task(ws_update(session, current, error, data))

        write_tasks = []

        for token in tokens:
            write_tasks.append(
                asyncio.create_task(write(token, session, error, history))
            )

        await asyncio.gather(*write_tasks)

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--type",
        "-t",
        choices=["json", "pickle"],
        default="pickle",
        help="File format.",
    )
    parser.add_argument(
        "--file", "-f", default="./output.pickle", help="File location."
    )
    parser.add_argument("--token-file", "--token", default="./token.json")

    nbsp = parser.parse_args()

    data: Dict[Tuple[int, int], int] = {}

    f_type: Literal["json", "pickle"] = nbsp.type
    file_loc: str = nbsp.file
    token_loc: str = nbsp.token_file

    with open(file_loc, "rb" if f_type == "pickle" else "r") as f:
        if f_type == "json":
            for [x, y, c] in json.load(f):
                data[(x, y)] = c
        else:
            data = pickle.load(f)

    with open(token_loc) as f:
        tokens = json.load(f)

    logger.info(f"Loaded from {file_loc}!")
    logger.info(f"Loaded {len(tokens)} tokens from {token_loc}!")
    logger.info(f"Painting from {min(data.keys())} to {max(data.keys())}")

    asyncio.run(main(data, tokens))


import json
from difflib import get_close_matches

data = json.load(open('data.json'))
data = dict(zip(map(str.lower,data.keys()),data.values()))

def get_meaning(word):
    word = word.lower()
    try:
        meaning = data[word]
        display(meaning)
    except KeyError:
        probable_word = get_close_matches(word, data.keys())
        if len(probable_word) > 0:
            yn = input('Do you mean: %s \nEnter Y for yes, or N for no : '%probable_word[0])
            if yn in'Yy':
                meaning = data[probable_word[0]]
                display(meaning)
            elif yn in 'Nn':
                print("Word doesn't exist. Please check the spelling.")
            else:
                print("We don't understand the word.")
        else:
            print("Word does't exist. Please check for spelling errors.")

def display(meaning):
    for i in range(len(meaning)):
        print(i+1,".", meaning[i])

word=input("Enter word : ")
get_meaning(word)


# -*- coding: utf-8 -*-
'''
input: videos
output: extracted images
      format: ".jpg" & ".pt"
      Note: extract 10 frames from each video clip aligned with a makeup step in all videos
'''
import os
import shutil
import json
import pickle
import cv2
import numpy as np
from collections import OrderedDict
import PIL
from PIL import Image
import torch
import torchvision
from tqdm import tqdm

def TimeToFrameIndex(t,fps, max_frame):
    #the format of input time e.g.00:02:22
    hour = int(t[0:2])
    minute = int(t[3:5])
    second = int(t[6:8])
    frame_index = int((second + minute*60 + hour*60*60)* fps)
    if frame_index > max_frame:
        frame_index = max_frame
    return frame_index

def ExtractFrame(frame,n,gap=5,flag=False):
    frames = []
    if flag == True: # +
        for i in range(n):
            frames.append(frame+i*gap)
    else:# -
        for i in range(n):
            frames.append(frame-(n-i-1)*gap)
    return frames

# save json data function
def json_data_save(path, data):
    jsdata = json.dumps(data)
    jsfile = open(path, 'w')
    jsfile.write(jsdata)
    jsfile.close()

# get fps of video
def GetVideoFps(video_path):
    vidcap = cv2.VideoCapture(video_path)
    (major_ver, minor_ver, subminor_ver) = (cv2.__version__).split('.') # Find OpenCV version
    fps = 0
    if int(major_ver)  < 3 :
        fps = vidcap.get(cv2.cv.CV_CAP_PROP_FPS)
    else:
        fps = vidcap.get(cv2.CAP_PROP_FPS)
    FrameNumber = int(vidcap.get(7))-1
    vidcap.release()
    return fps,FrameNumber

#convert img to the tensor format
def ConvertToTensor(image):
    transform=torchvision.transforms.Compose([
            torchvision.transforms.Resize(224),
            torchvision.transforms.CenterCrop(224),
            torchvision.transforms.ToTensor(),
            torchvision.transforms.Normalize([0.485, 0.456, 0.406],
                                             [0.229, 0.224, 0.225])
        ])
    image = Image.fromarray(cv2.cvtColor(image,cv2.COLOR_BGR2RGB))
    image = image.convert('RGB')
    img = transform(image)
    return img

def GetSplitVideoName(train_id_path,test_id_path,train_videos_path,test_videos_path):
    f = open(train_id_path, "r")
    train_ids = []
    for x in f:
        train_ids.append(x[:-1])

    f = open(test_id_path, "r")
    test_ids = []
    for x in f:
        test_ids.append(x[:-1])
    #maybe some videos are missing(can't be downloaded),filter these video ids
    exist_train_videos = os.listdir(train_videos_path) #".mp4 foramt"
    exist_test_videos = os.listdir(test_videos_path)
    exist_train_videos = [v[:-4] for v in exist_train_videos]
    exist_test_videos = [v[:-4] for v in exist_test_videos]
    train_ids = list( set(exist_train_videos) & set(train_ids) )
    test_ids = list( set(exist_test_videos) & set(test_ids) )
    return train_ids,test_ids

'''
input：
---- captions_path
---- videos_path
---- movie_names
---- save_path
---- n

output：
----img_index2info : save a img id related info:[video id，video index，frame index,caption index,saved path]
----video_info     : save processing information of each video, including extracted frame ids，effective caption ids
    {'vid':
            {
                'frames':   list() type
                'captions': list() type
                'areas':    list() type
            }
     ……
    }
----split_images_num : the total number of images in train/test set

'''

def ExtractImagesFromFullData(caption_data_path,video_data_path,movie_names,save_img_path,split,n):
    img_index2info = {}
    video_info = {}
    videos_fps = []

    vnum = 0  #the processed video num
    image_index = 0
    gap = 5   #the interval of two extracted frames

    with open(caption_data_path, "r") as file:
        for index,f in enumerate(file):
            img_frame2capt_id = {}
            #read a line，include all caption annotations of a video
            line  = json.loads(f,object_pairs_hook=OrderedDict)
            #read video id
            vid = line['video_id']
            #filter video does't exist
            if vid not in movie_names:
                continue
            video_info[vid] = {}
            video_info[vid]['areas'] = []
            areas = []
            #get fps of the video
            this_video_path = video_data_path + vid + ".mp4"
            fps,max_frame = GetVideoFps(this_video_path)
            videos_fps.append(fps)

            #get captions set of the video
            vsteps = line['step']

            #calculate the frame index of images to be extracted
            extract_frame_index = []
            step_period = {}

            vnum += 1
            cur_frame_index = []
            first_idx = 0
            for idx,key in enumerate(vsteps):
                #each caption noted as d
                d  = vsteps[key]
                caption = d['caption']
                startime = d['startime']
                endtime = d['endtime']
                areas.append(d['area'])
                #convert timestamp to frame index
                startframe = TimeToFrameIndex(startime,fps,max_frame)
                endframe = TimeToFrameIndex(endtime,fps,max_frame)
                duration = endframe - startframe

                #filter steps that are wrong annotated
                if endframe <= startframe:
                    #print(vid,"caption ",idx," error:endframe <= startframe",startime,endtime)
                    continue

                if duration>int(10*fps): #if duration video clip>10s，extract a frame per 5 frames
                    gap = 5
                else: # <10s, extract frames continuously
                    gap = 1

                cur_frame_index = ExtractFrame(endframe,n,gap,False)
                extract_frame_index.extend(cur_frame_index)
                step_period_name = vid + "_" + str(startframe) + "_" + str(endframe)
                for f in cur_frame_index:
                    img_frame2capt_id[f] = idx
                    step_period[f] = step_period_name

            #-------------------------------------read videos------------------------------------
            #get extracted image useful info
            video_info[vid]['frames'] = []
            video_info[vid]['captions'] = set()

            this_video_path = video_data_path + vid + ".mp4"
            video = cv2.VideoCapture(this_video_path)
            times = 0  #frame index
            while True:
                res, image = video.read()
                if not res:
                    print(index," finish reading video ",vid)
                    break
                if times in extract_frame_index:   #this frame need to be extracted
                    cid = img_frame2capt_id[times] #this frame belongs to caption cid
                    image_dir = step_period[times] # e.g. 3L-C3lsV2_w_6813_7819
                    img_file_path = save_img_path+image_dir+'/'
                    if not os.path.exists(img_file_path):
                        os.makedirs(img_file_path)

                    #save img as jpg
                    output_image_path = img_file_path + vid + "_" + str(times) + ".jpg" #e.g.3L-C3lsV2_w_6813_7819/3L-C3lsV2_w_7819.pt
                    cv2.imwrite(output_image_path, image)

                    #convert and save img to tensor format
                    output_image_tensor_path = img_file_path + vid + "_" + str(times) + ".pt"
                    img_tensor = ConvertToTensor(image)
                    torch.save(img_tensor, output_image_tensor_path)

                    #obtain each extracted image information
                    path = image_dir+'/'+vid+'_'+str(times)+'.pt' #3L-C3lsV2_w_6813_7819/3L-C3lsV2_w_7819.pt
                    img_index2info[image_index] = [vid,vnum-1,times,cid, path]
                    video_info[vid]['frames'].append(times)
                    video_info[vid]['captions'].add(cid)
                    image_index += 1

                    if times == max(extract_frame_index):
                        print(index," finish reading video ",vid)
                        break
                times += 1
            video.release()
            video_info[vid]['captions'] = list(video_info[vid]['captions'])
            video_info[vid]['areas'] = [areas[video_info[vid]['captions'][i]] for i in range(0,len(video_info[vid]['captions'])-1)]

    print("**********************Finished**********************")
    print(split)
    print(vnum," videos processed in total")
    print(image_index," images extracted in total")
    return  img_index2info,video_info,split_images_num,videos_fps

if __name__ == '__main__':

    #video saved path
    videos_path = {}
    videos_path['train'] = "../../YouMakeup/data/train/videos/"
    videos_path['test'] = "../../YouMakeup/data/valid/videos/"
    #path of caption annotations
    captions_path = {}
    captions_path['train'] = "../../YouMakeup/data/train/train_steps.json"
    captions_path['test'] = "../../YouMakeup/data/valid/valid_steps.json"
    #the save path of extracted train/test imgs
    save_img_path = {}
    save_img_path['train'] = "./shared_data/train_images/"
    save_img_path['test'] = "./shared_data/val_images/"
    #get train/test video ids (filter videos that doesn't exist)
    train_id_path = "../../YouMakeup/data/train/train_id"
    test_id_path = "../../YouMakeup/data/valid/valid_id"
    movie_names = {}
    movie_names['train'],movie_names['test'] = GetSplitVideoName(train_id_path,test_id_path,videos_path['train'],videos_path['test'])
    #save train/test movie_names
    np.save("./shared_data/train_vids.npy",movie_names['train'])
    np.save("./shared_data/test_vids.npy",movie_names['test'])

    n = 10 #each video clip extract 10 frames
    img_index2info = {}
    video_info = {}
    split_images_num = {}
    fps = {}
    for split in ['train','test']:
        img_index2info[split],video_info[split],split_images_num[split], fps[split] = ExtractImagesFromFullData(captions_path[split],videos_path[split],movie_names[split],save_img_path[split],split,n)

    #save useful information about extracted img
    #img_index2info,video_info
    json_data_save("./shared_data/img_index2info.json", img_index2info)
    json_data_save("./shared_data/video_info.json", video_info)
    json_data_save("./shared_data/fps.json", fps)


import warnings
warnings.filterwarnings("ignore")
import itertools
import random
import os
import numpy as np
import pickle

from sklearn import linear_model, svm, ensemble
from sklearn.metrics import accuracy_score, f1_score, confusion_matrix, roc_auc_score, recall_score, precision_score
from multiprocessing import Pool
import statsmodels.api as sm
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from data import DataLoaderForFeature

class MLModel(object):
    def __init__(self, data_loader, model_path, model_name, import_metric='f1_score', metrics_list=['accuracy', 'f1_score', 'recall', 'roc_auc', 'precision'], multi_processing=True, load_model=False, verbose=False):
        self._model_path = model_path
        self._model_name = model_name
        if not os.path.exists(model_path):
            os.makedirs(model_path)
        self._metrics_list = metrics_list
        self._best_model = {'metrics': dict(), 'hyper_parameters': dict()}
        self._generate_hyper_parameters(model_name)
        self._load_data(data_loader)
        self._multi_processing = multi_processing
        self.load_model_mark = load_model
        self._verbose = verbose
        self._metric = import_metric

        self._window = data_loader.window
        self._gap = data_loader.gap

    def fit(self, processing_number=1, random_number=3):
        if self.load_model_mark and os.path.exists(os.path.join(self._model_path, self._model_name + '_model')):
            change_mark = False
            self.load_model(from_best=True)
            self._best_model['metrics'] = self._valid()
        for index, hyper_parameters in enumerate(self._hyper_parameters_list):
            results = []
            temp_best_acc = 0
            if self._multi_processing and processing_number > 1 and random_number > 1:
                with Pool(processes=processing_number) as pool:
                    for _ in range(random_number):
                        result = pool.apply_async(func=self._helper_function, args=(
                            hyper_parameters, self._data))
                        results.append(result)
                    pool.close()
                    pool.join()
            else:
                self._multi_processing = False
                for _ in range(random_number):
                    result = self._helper_function(
                        hyper_parameters, self._data)
                    results.append(result)
            for result in results:
                if self._multi_processing:
                    metrics, model, random_seed = result.get()
                else:
                    metrics, model, random_seed = result
                if metrics is None:
                    continue
                temp_best_acc = max(
                    metrics[self._metric], temp_best_acc)
                if self._metric not in self._best_model['metrics'] or metrics[self._metric] >= self._best_model['metrics'][self._metric]:
                    change_mark = True
                    self.model = model
                    if self._verbose:
                        self.test()
                    for key, value in metrics.items():
                        self._best_model['metrics'][key] = value
                    for key, value in hyper_parameters.items():
                        self._best_model['hyper_parameters'][key] = value
                    self._best_model['hyper_parameters']['random_seed'] = random_seed
                    self._save_model()

    def _train_model(self, data):
        try:
            self.model.fit(data[0], data[1])
        except ValueError:
            self.model = None

    def _valid(self, data=None):
        if data is None:
            data = self._data.valid_data
        feature, label = data
        label_pred = self.model.predict(feature)
        label_pred_socre = self.model.predict_proba(feature)
        return self._calculate_metrics(label_pred, label_pred_socre, label)

    def test(self, data=None):
        if data is None:
            data = self._data.test_dataset
        feature, label = data
        label_pred = self.model.predict(feature)
        label_pred_socre = self.model.predict_proba(feature)
        metrics = self._calculate_metrics(label_pred, label_pred_socre, label)
        for key, value in metrics.items():
            self._best_model['metrics'][key] = value
        # print('%s is  %.3f' % (self._metric, metrics[self._metric]))
        return metrics

    def _generate_hyper_parameters(self):
        pass

    def _build_model(self, hyper_parameters, random_state):
        pass

    def _calculate_metrics(self, pred, pred_score, ground):
        _metrics = dict()
        if 'accuracy' in self._metrics_list:
            _metrics['accuracy'] = accuracy_score(ground, pred)
        if 'f1_score' in self._metrics_list:
            if len(pred_score[0]) > 2:
                _metrics['f1_score'] = f1_score(ground, pred, average='macro')
            else:
                _metrics['f1_score'] = f1_score(ground, pred)
        if 'confusion' in self._metrics_list:
            _metrics['confusion_matrix'] = confusion_matrix(ground, pred).tolist()
        if 'roc_auc' in self._metrics_list:
            if len(pred_score[0]) > 2:
                try:
                    _metrics['auc'] = roc_auc_score(ground, pred_score, multi_class='ovr')
                except ValueError:
                    ground.append(2)
                    pred_score = np.append(pred_score, np.array([np.array([0, 0, 1.0, 0])]), axis=0)
                    _metrics['auc'] = roc_auc_score(ground, pred_score, multi_class='ovr')
                    ground = ground[:-1]
            else:
                _metrics['auc'] = roc_auc_score(ground, pred_score[:, 1])
        if 'recall' in self._metrics_list:
            if len(pred_score[0]) > 2:
                _metrics['recall'] = recall_score(ground, pred, average='macro')
            else:
                _metrics['recall'] = recall_score(ground, pred)
        if 'precision' in self._metrics_list:
            if len(pred_score[0]) > 2:
                _metrics['precision'] = precision_score(ground, pred, average='macro')
            else:
                _metrics['precision'] = precision_score(ground, pred)
        return _metrics

    def _load_data(self, data_loader):
        self._data = data_loader

    def load_model(self, model_path='', from_best=False):
        if model_path =='':
            if self._window != 0 and self._gap != 0 and from_best==False:
                model_path = os.path.join(self._model_path, str(self._window) + '_' + str(self._gap))
            else:
                model_path = self._model_path
        else:
            model_path = model_path

        with open(os.path.join(model_path, self._model_name+'_model'), "rb") as fp:
            self.model = pickle.load(fp)

    def _save_model(self):
        model_path = self._model_path
        if not os.path.exists(model_path):
            os.makedirs(model_path)
        json_file = os.path.join(model_path, self._model_name + '_result')

        model_file = os.path.join(model_path, self._model_name + '_model')

        with open(json_file, mode='w', encoding='utf8') as fp:
            for key, value in self._best_model['metrics'].items():
                fp.write(key + ' : ' + str(value) + '\n')
            for key, value in self._best_model['hyper_parameters'].items():
                fp.write(key + ' : ' + str(value) + '\n')
            # fp.write('window : ' + str(self._window) + '\n')
            # fp.write('gap : ' + str(self._gap) + '\n')
            with open(model_file, mode='wb') as fp:
                pickle.dump(self.model, fp, protocol=4)

    def _helper_function(self, hyper_parameters, data):
        random_seed = random.randint(1, 20)
        self._build_model(hyper_parameters, random_seed)
        self._train_model(data.data)
        if self.model is not None:
            metrics = self._valid()
        else:
            metrics = None
        return (metrics, self.model, random_seed)

    def _build_analysis_model(self):
        pass

    def analysis(self):
        self._build_analysis_model()
        if self._window != 0 and self._gap != 0:
            model_path = os.path.join(self._model_path, str(self._window) + '_' + str(self._gap))
        else:
            model_path = self._model_path
        if not os.path.exists(model_path):
            os.makedirs(model_path)

        train_feature, train_label = self._data.train_dataset
        valid_feature, valid_label = self._data.valid_dataset
        test_feature, test_label = self._data.test_dataset

        train_dataset = pd.DataFrame(train_feature)
        train_dataset['label'] = np.array(train_label)
        valid_dataset = pd.DataFrame(valid_feature)
        valid_dataset['label'] = np.array(valid_label)
        test_dataset = pd.DataFrame(test_feature)
        test_dataset['label'] = np.array(test_label)

        # train_dataset = pd.concat(self._data.train_dataset, keys=['feature','label'], axis=1)
        # valid_dataset = pd.concat(self._data.train_dataset, keys=['feature','label'], axis=1)
        # test_dataset = pd.concat(self._data.test_dataset, keys=['feature','label'], axis=1)

        data = pd.concat([train_dataset, valid_dataset, test_dataset])
        data = data.sample(frac=1)

        label = data[['label']]
        feature = data.drop(columns=['label'])
        feature = sm.add_constant(feature, has_constant='add')
        model = self._analysis_model(label, feature.astype(float)).fit(maxiter=200)

        summary = model.summary2()
        summary = summary.tables[1]
        importance = np.array(summary['P>|z|'])[1:]
        importance = np.where(importance > 0.05,1,importance)
        # importance =  1 - importance
        importance = importance.reshape((17, 17))
        sns.heatmap(importance, vmin=0, vmax=1)
        plt.show()

        report_file = os.path.join(model_path, self._model_name + '_analysis')
        with open(report_file, mode='w') as fp:
            fp.write(model.summary().as_text())

class LogisticRegressionCV(MLModel):

    def _generate_hyper_parameters(self):
        penalty_list = ['l1', 'l2']
        solver_list = ['newton-cg', 'lbfgs', 'sag', 'saga']
        multi_class_list = ['ovr', 'multinomial']

        self._hyper_parameters_list = list()

        for data in itertools.product(penalty_list, solver_list, multi_class_list):
            hyper_parameters = {'penalty': data[0], 'solver': data[1], 'multi_class': data[2]}
            self._hyper_parameters_list.append(hyper_parameters)

    def _build_model(self, hyper_parameters, random_state):
        self.model=linear_model.LogisticRegressionCV(
            random_state=random_state, max_iter=1000, **hyper_parameters)

    def _build_analysis_model(self):
        self._analysis_model = sm.Logit

class SVM(MLModel):
    def _generate_hyper_parameters(self):
        kernel_list = ['linear', 'poly', 'rbf', 'sigmoid']
        gamma_list = ['scale', 'auto']
        decision_function_shape_list = ['ovo', 'ovr']

        self._hyper_parameters_list = list()

        for data in itertools.product(kernel_list, gamma_list, decision_function_shape_list):
            hyper_parameters = {'kernel': data[0], 'gamma': data[1], 'decision_function_shape': data[2]}
            self._hyper_parameters_list.append(hyper_parameters)

    def _build_model(self, hyper_parameters, random_state):
        self.model = svm.SVC(**hyper_parameters)

class RandomForest(MLModel):
    def _generate_hyper_parameters(self, model_name):
        criterion_list = ['gini', 'entropy']
        max_features_list = ['auto', 'log2']
        if model_name == 'all-emotion':
            estimator_num_list = [i * 10 for i in range(5, 25)]
        else:
             estimator_num_list = [100]

        self._hyper_parameters_list = list()

        for data in itertools.product(criterion_list, max_features_list, estimator_num_list):
            hyper_parameters = {'criterion': data[0], 'max_features': data[1],'n_estimators':data[2]}
            self._hyper_parameters_list.append(hyper_parameters)

    def _build_model(self, hyper_parameters, random_state):
        self.model = ensemble.RandomForestClassifier(**hyper_parameters, class_weight='balanced')

def test():
    data_train = DataLoaderForFeature('tfidf', '2016-2016', '2016', exlusice_time='', valid=True)
    data_test = DataLoaderForFeature('tfidf', '2016-2017', '2017', exlusice_time='2016', valid=False)
    model = RandomForest(data_train, model_path= './log/RF/bipolar_depression_anxiety_background', model_name='tf-idf',
                    load_model=False, multi_processing=True)
    # data_train = DataLoaderForFeature('state_trans', '2016', '2016', exlusice_time='', valid=True)
    # data_test = DataLoaderForFeature('state_trans', '2017', '2017', exlusice_time='2016', valid=False)
    # model = RandomForest(data_train, model_path= './log/RF/bipolar_depression_anxiety_background', model_name='all_emotion',
    #                    load_model=False, multi_processing=True)
    # model.fit(processing_number=5, random_number=10)
    model.load_model(model_path='./log/RF/bipolar_depression_anxiety_background')
    model.test(data_test.data)
    print('\n')

if __name__ == '__main__':
    test()


import matplotlib.pyplot as plt
import numpy as np
import scipy.constants
import time
import scipy.integrate as integrate
import scipy as sp
from scipy.integrate import odeint
from matplotlib.pyplot import cm
import matplotlib as mpl
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.transforms import Bbox
from mpl_toolkits.mplot3d import axes3d
from scipy.optimize import curve_fit

def my_max_by_weight(sequence):
    if not sequence:
        raise ValueError('empty sequence')

    maximum = sequence[0]

    for item in sequence:
        # Compare elements by their weight stored
        # in their second element.
        if item[1] > maximum[1]:
            maximum = item
    return maximum

N = 10 # no of eggs per brooder

def F(N,r_o,alpha):
    #f=  (1/(1+ np.exp(-r_o) ) )
    #print(r_o)
    f = np.power(r_o,alpha)
    #print (f)
    return(f)

def S(M,b,gamma,r_i):  ### brooding period
    s = np.exp(-(M*b)/(1+(gamma*r_i)))
    #print('r_i is', r_i)
    #print ('s is', s)
    return (s)

def S_future(M,gamma,r_i):
    s_fut = np.exp(-(M)/(1+(gamma*r_i)))
    return (s_fut)

def W_prime(r_prime):
    #print (i_prime)
    w=Fofr[ r_range.index(r_prime) ]
    return(w)

def g_func(time):
    g = (0.3/(2+ 4*np.exp(-1/2*time) ) ) #1 logistic
    g = g*100
    g = np.floor(g)
    g = int(g)
    #print ('g is',g)
    return g

pop = 200

#end time
TT= 21 #use odd numbers for proper plotting
T = 15
#start time
#t=1

#the i_critical/min and max values
r_min =0

C=20 # no. of categories

r_max = 1

#########

M = 4.0 # Factors causing mortality
gamma = 2 #amount of decreasing/increases mortality. Controld mortality or its rate

#g = 10#int(C/4) ### gain in reserves in the non-brooding period until the next brooding season

alpha = 0.5

phi_max = 100 # maximum number of offspring produced (on average for a species)

##sigma and g### #prob_gaussian##

g = np.array([6,7,8,9,10,11,12,13,14])
#g = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17])
l = len(g)
g_mean= np.mean(g)
#g_func = g/20 ### normalisation to keep gE[0,1.0]
#g_func_mean = np.mean(g_func)

sigma = 8

prob= np.arange(l,dtype=float)

for p in range (0,l):
    prob[p] = np.exp( (-1 * np.power(g[p]-g_mean,2)  ) / ( 2* sigma * sigma ) )

prob_sum = np.sum(prob) ###
prob = prob/prob_sum ### ensure all probs all to 1
#print(prob)

brooding_period = np.array([0.1,0.5,0.9])  ### brooding period array [0.0,1.0]; ## brooding period; months or days. Proportion of brooding period at a time t. 1-b would be non-brooding period in a time period t.
lim =len(brooding_period)

Res = np.zeros((pop,lim),dtype=float)
ROO = np.zeros((pop,lim),dtype=float)
RII = np.zeros((pop,lim),dtype=float)
alive = np.zeros((lim,T-1),dtype=float)### no. of alive individuals at a certain time for different brooding periods

for B in range (0,lim):
    b = brooding_period[B]
    print ('b is', b)

    np.random.seed(200)

    ### initializing arrays for forward dynamics ####
    opt_ro = np.zeros((pop,T-1),dtype=float)
    opt_ri = np.zeros((pop,T-1),dtype=float)
    state = np.zeros((pop,T-1),dtype=float)

    ### initializing arrays for rerserves and functions forward dynamics ####
    roo = np.zeros((pop,T-1),dtype=float)   # gives fecundity
    rii = np.zeros((pop,T-1),dtype=float)  # immune system , proxy for immunocompetence
    rr = np.zeros((pop,T-1),dtype=float)   # total reserves

    fertility_current = np.zeros((pop,T-1),dtype=float)
    Cum_fertility = np.zeros((pop,T-1),dtype=float)
    survivability_current = np.zeros((pop,T-1),dtype=float)
    survivability_future = np.zeros((pop,T-1),dtype=float)
    Cum_survivability = np.zeros((pop,T-1),dtype=float)

    s = np.ones((pop,T-1),dtype=float)### checks if the individual is alive or not; s=1 means alive by default; updates can cause s =0 meaning dead
    #print ('s is', s)

    #the range of values of the state variable inclusively between the critical value and the capacity value
    r_range=range(r_min,C+1)
    #range function acts like interval notation [m,n) w/ defalt step size 1 (an optional 3rd argument can be added to specify the step size)

    #initializing the fittness function at each state x
    Fofr=[]
    #print ('Fofr is' , Fofr)
    #filling Fofx with the End condition (t=T) fittness values
    for r in r_range:
        Fofr.append(0)

    #printing t=T fitnesses
    #print('')
    #print('________ t=%2d ________________'%T)
    #print('State   F(x,t)      r_i*  r_o*')
    counter=0
    for endfitness in Fofr: #I use the counter to index into the the x_rangre list at the appropriate place
        #print ('%1.4f     %1.4f      %s  %s'%(r_range[counter]*( r_max /C), endfitness,'N/A', 'N/A') )
        counter=counter+1

    subPltIndex=1
    #Fofr is a list of fitnesses based on a particular state the fitness list is in the same order as the state list

    R_I = np.zeros((l,TT-1,C),dtype=float)
    R_O = np.zeros((l,TT-1,C),dtype=float)

    #### BACKWARD
    #iterating from t=T-1 to t=1 in steps of -1
    for t in range(TT-1, 0, -1):
        #print ('t',t)
        time = t

        #print('g is', g)

        maxW=[]

        for r in r_range[1:]:
            #print('r',r)

            MAX = np.zeros((l,C+1,C+1),dtype=float)
            for ri in range (0,r+1):
                #print('ri',ri)
                R = r - ri
                #print('R',R)

                for ro in range(0,R+1):
                    #print('ro',ro)
                    rt = r- ro -ri
                    #print ('rt is', rt)

                    r_prime = np.arange(l,dtype=float) # r' for each g in gaussian distribution
                    r_prime = rt + g

                    #print(r_prime)
                    for p in range(0,l):
                        if r_prime[p] >C: r_prime[p] = C
                        if r_prime[p] <0: r_prime[p] = 0

                    #print ('r_prime is ', r_prime)
                    #print('r',r)
                    #print('ri',ri)
                    #print('ro',ro)
                    RO = ro * r_max /C
                    RI = ri * r_max /C
                    RT = rt * r_max /C
                    R_PRIME =  r_prime * r_max /C

                    Max = np.arange(l,dtype=float) # Max value for each g in gaussian distribution
                    for p in range (0,l):
                        Dri=[]
                        Dro=[]
                        MAX[p,ri,ro] =  ( ( phi_max* F(N,RO,alpha) * S(M,b,gamma,RI) )  +  S_future(M,gamma,RI) * W_prime(r_prime[p]-1)   )
                        #print('MAX is',MAX)
                        ind = np.unravel_index(np.argmax(MAX[p,:,:], axis=None), MAX.shape)
                        #print('ind is',ind)
                        dro = ind[2]
                        dri = ind[1]
                        DRO = dro * r_max /C
                        DRI = dri * r_max /C
                        R_I[p][t-1][r-1] = DRI
                        R_O[p][t-1][r-1] = DRO
                        #print (t-1)
                        #print(r-1)
                        Max[p] =  np.max(MAX[p,:,:])

            W = 0
            Max = prob * Max
            W = np.sum(Max)
            #print('W is', W)
            maxW.append(W)
            #print('maxW',maxW)

            #print(t)
            #print(r)
        #housekeeping to keep the indicies of the updated version of Fofx the same as the original version
        #print('Fofr0',Fofr)
        Fofr=maxW
        #print('Fofr is',Fofr)

    ##### FORWARD ##########
    for i in range (0,pop):  ### for every nth individual
        #print('i or ind is ',i)

        time = np.arange(T-1)+1  ### time range;  reproductive lifetime
        ### assigning inital reserves STATES to initial time.
        init_res = g_func(0) ### initial reserves
        state[:,0] = init_res
        #### start of forward routine #####
        for t in range(0,T-1):
            #print('t is', t)
            #print('t-1 is', t-1)
            #print ('s[i,t] is', s[i,t])
            if(s[i,t]==1.0):
                #print ('g is', g)
                prob_random = np.random.random()  ### generates a random number in range [0,1] which gives the prob to go to g_h
                #print ('prob_random is', prob_random)

                prob_gen = np.cumsum(prob)

                for p in range(1,l):
                    #print (p-1, p)
                    if((prob_random>prob_gen[p-1])and(prob_random<prob_gen[p])):
                        g_gain= g[p]
                        p_g = p

                if(t>0): state[i,t] = state[i,t-1] - opt_ro[i,t-1] - opt_ri[i,t-1]  + g_gain

                if (state[i,t]>C):
                    state[i,t] = C

                if (state[i,t]<0):
                    state[i,t] = 0

                #print('state[i,t] is', state[i,t])

                #print('opt_ro[i,t] is', opt_ro[i,t])
                #print('opt_ri[i,t] is', opt_ri[i,t])

                rr[i,t] = state[i,t] *r_max/C
                #print('r[i,t] is',rr[i,t])

                R = int(rr[i,t] *C/r_max)
                #print ('R is', R)

                roo[i,t] = R_O[p_g][t][R-1]
                rii[i,t] = R_I[p_g][t][R-1]
                #print('ro[i,t] is',roo[i,t])
                #print('ri[i,t] is ',rii[i,t])

                survivability_current[i,t] = S(M,b,gamma,rii[i,t])
                survivability_future[i,t] = S_future(M,gamma,rii[i,t])
                Cum_survivability[i,t] = np.power(survivability_future[i,t],t)

                fertility_current[i,t] = F(N,roo[i,t],alpha) * S(M,b,gamma,rii[i,t])
                Cum_fertility[i,0] = Cum_survivability[i,0] * F(N,roo[i,0],alpha)
                Cum_fertility[i,t] = Cum_fertility[i,t-1] + ( Cum_survivability[i,t] * F(N,roo[i,t],alpha) )

                opt_ro[i,t] = roo[i,t] * C/r_max
                opt_ri[i,t] = rii[i,t] * C/r_max
                #print('opt_ro[i,t] updated is', opt_ro[i,t])
                #print('opt_ri[i,t] updated is', opt_ri[i,t])

                #print ('survivability_current[i,t] is ', survivability_current[i,t])
                x = np.random.random()  ### generates a random number in range [0,1] which gives the survival prob
                #print ('x is', x)
                if (survivability_future[i,t]<x):  ### individual is dead; will not perform any funtions like resource allocation etc
                    s[i,t+1:] = 0

        #print ('s is',s)
        Res[i][B] = rr[i][1]
        ROO[i][B] = roo[i][1]
        RII[i][B] = rii[i][1]

    #print(s)

    for t in range(0,T-1):
        alive[B][t] =  np.sum(s[:,t])

    m = rii.mean(0)
    v = rii.var(0)
    stdv= rii.std(0)
    upper = m+v
    lower = m-v
    plt.figure()
    #for nn in range (0,pop):
        #plt.plot(time,rii[nn,:],color='darkorange')

    #plt.plot(time,upper,lw = 6,color='lightgrey',zorder=1)
    #plt.plot(time,lower,lw = 6,color='lightgrey',zorder=2)
    #plt.fill_between(time,upper,lower,color='lightgrey',zorder=3)
    #plt.scatter(time,m,lw = 0.2,color='darkorange',zorder=4)
    plt.errorbar(time,m,color='darkorange',yerr=stdv, fmt='o',ecolor='black',markersize=5.5, capsize=7)#uplims=True, lolims=True)
    plt.xticks([2,4,6,8,10,12,14] , fontsize = 20)
    plt.yticks([0.0,0.2,0.4,0.6,0.8,1.0] ,fontsize = 20)
    #plt.legend()
    plt.title('M = %s, gamma=%s,b=%0.1f'%(M,gamma,b))
    plt.ylim([-0.05,0.65])
    plt.xlabel('time',fontsize=18)
    plt.ylabel('$r_i$',fontsize=18)
    save = '/Users/vandana/Dimorphism/figures/Stochastic_ri_b_%s_AllAlive.pdf' %(b)
    plt.savefig(save,format='pdf')
    #plt.show()

    plt.figure()
    for nn in range (0,pop):
        plt.scatter(time,rii[nn,:])
    plt.xticks([2,4,6,8,10,12,14] , fontsize = 20)
    plt.yticks([0.0,0.2,0.4,0.6,0.8,1.0] ,fontsize = 20)
    #plt.legend()
    plt.title('M = %s, gamma=%s,b=%0.1f'%(M,gamma,b))
    plt.ylim([-0.05,0.65])
    plt.xlabel('time',fontsize=18)
    plt.ylabel('$r_i$',fontsize=18)
    #save = '/Users/vandana/Dimorphism/figures/Stochastic_ri_b_%s_individuals.pdf' %(b)
    #plt.savefig(save,format='pdf')
    #plt.show()

####### plots#########

for i in range (0,pop):
    #alphas = i/(10) +0.5
    #print(alphas)
    #plt.plot(brooding_period,Res[i,:],color='blue',alpha = alphas,label='r,ind=%0.1f'%i)
    #plt.plot(brooding_period,Res[i,:],label='r,ind=%0.1f'%i)
    #plt.plot(brooding_period,RII[i,:],color='darkorange',alpha = alphas,label='ri,ind=%0.1f'%i)
    plt.plot(brooding_period,RII[i,:],label='ri,ind=%0.1f'%i)
    #plt.plot(brooding_period,ROO[i,:],color='green',alpha = alphas,label='ro,ind=%0.1f'%i)
#plt.legend()
plt.title('M = %s, gamma=%s'%(M,gamma))
plt.xlabel('brooding period',fontsize=18)
plt.ylabel('reserves for immunity $r_i(r(t=1),t=1$)',fontsize=18)
save = '/Users/vandana/Dimorphism/figures/Stochastic_b_ri_ro_Mortality_%s.pdf' %M
plt.savefig(save,format='pdf')
plt.show()

#########  PLOTS ########

hue = []
hue = ['deepskyblue','royalblue', 'blue']
markers = ['.', '+', 'x']
period = np.array(['short brooding period', 'intermediate brooding period', 'long brooding period'])
##########
def func2(x, a, c):
    return (a  * x) + c
expo =[]

for i in range (0,lim):
    b = brooding_period[i]
    alphas = b+0.1#((b*10-1)/(2*(brooding_period[i]-brooding_period[0]))) + 0.5
    plt.scatter(time,np.log(alive[i,:]),color=hue[i],marker=markers[i],s=30,label=period[i])#label='$f $ = %0.1f'%b)
plt.legend()
plt.yscale('log')
plt.title('M = %s, gamma=%s'%(M,gamma))
plt.xlabel('time',fontsize=18)
plt.ylabel('# alive individuals',fontsize=18)
plt.xticks( fontsize = 20)
plt.yticks(fontsize = 20)
#save = '../vandana/Dimorphism/figures/Stochastic_alive_Mortality_%s_gamma_%s_AllAlive.pdf' %(M,gamma)
save = '/Users/vandana/Dimorphism/figures/Stochastic_alive_Mortality_%s_gamma_%s.pdf' %(M,gamma)
plt.savefig(save,format='pdf')
plt.show()

#########   ########

def func1(x, a, b, c):
    return a * np.exp(-b * x) + c

expo =[]

for i in range (0,lim):
    b = brooding_period[i]
    #alphas = b+0.1#((b*10-1)/(2*(brooding_period[i]-brooding_period[0]))) + 0.5
    #plt.scatter(time,np.log(alive[i,:]),color=hue[i],alpha = alphas,label='$f $ = %0.1f'%b)
    #plt.scatter(time,np.log(alive[i,:]),color=hue[i],alpha = alphas,label='$f $ = %0.1f'%b)
    #plt.scatter(time,np.log(alive[i,:]),color='black',marker=markers[i],label='$f $ = %0.1f'%b)
    xdata= time
    ydata = alive[i,:]/pop
    popt, pcov = curve_fit(func1, xdata, ydata)
    plt.scatter(time,((alive[i,:])/pop),color=hue[i],marker=markers[i],s=30,label='$M_{emergent}$ for '+""+period[i]+'=%0.2f'%popt[1])#label='$f $ = %0.1f'%b)
    #plt.plot(xdata, func(xdata, *popt), color=hue[i],lw=0.8,label='%0.2f*exp(-%0.2f*time)'%(popt[0],popt[1]) )
plt.legend()
plt.title('M = %s, gamma=%s'%(M,gamma))
plt.xlabel('time',fontsize=18)
plt.ylabel('Fraction of individuals alive',fontsize=18)
plt.xticks( fontsize = 20)
plt.yticks(fontsize = 20)
#save = '/Users/vandana/Dimorphism/figures/Stochastic_alive_Mortality_%s_gamma_%s_AllAlive.pdf' %(M,gamma)
save = '/Users/vandana/Dimorphism/figures/Stochastic_alive_Mortality_Scatter_%s_gamma_%s.pdf' %(M,gamma)
plt.savefig(save,format='pdf')
plt.show()


import backtrader as bt
from application.api.backtest.strategies.BaseStrategy import BaseStrategy, get_common_params

class RateOfChangeStrategy(BaseStrategy):

    params = (
        ('period', 9),
    )

    def __init__(self):
        self.roc = bt.indicators.RateOfChange(self.data.close, period=self.params.period)
        super(RateOfChangeStrategy, self).__init__()

    def next(self):
        print('self.roc[0]', self.roc[0])
        # print('self.roc[1]', self.roc[1])
        print('self.roc[-1]', self.roc[-1])
        super(RateOfChangeStrategy, self).next()

    def should_buy(self):
        return self.roc[0] > 0 and self.roc[-1] < 0

    def should_sell(self):
        return self.roc[0] < 0 and self.roc[-1] > 0

def get_RateOfChangeStrategy_params(config):
    strategy_params = config.get('strategy_params')
    period = strategy_params.get('period') or 9
    result = {
        'period': period,
    }
    result = get_common_params(strategy_params, result)
    return result


import math

from scipy.io import loadmat
import numpy as np
import cv2
import glob
import os
# İsmail Çetin
# 150180065
path = 'C:/Users/nitec/Desktop/BSR_bsds500/images/test/images' # Path to save images

def calc_precision(img_canny, ground_truth):
    t_p = np.count_nonzero(np.logical_and((img_canny == 255), (ground_truth == 255))) # if both img_canny and ground_truth
    # find the value as 1 then this value is true positive
    f_p = np.count_nonzero(np.logical_and((img_canny == 255), (ground_truth == 0))) # if canny found but ground_truth
    # does not contain that pixel
    return t_p / (t_p + f_p)  # True positives / total positives

# Apply canny edge filter and make edges 255. Then find the total_positives and true_positives. True_positive (where
# both ground truth and canny returns 1). total_positives is all 1 s in canny detector
my_images = []
for file in glob.glob("*.mat"): # for each matrix file reach the file
    f_name = file.split('.')[0] # get its name for future use
    mat = loadmat(file) # load the file into numpy array
    ph_sum = np.zeros_like(mat['groundTruth'][0][0][0][0][1]) # create empty img which is in the same form with groundTruth
    photo_num = mat['groundTruth'][0].shape[0] # Count how many boundary is given in MATLAB file.
    for j in range(photo_num): # traverse the boundaries just for one image
        ph_sum = ph_sum + mat['groundTruth'][0][j][0][0][1] # sum and at the end obtain ground truth
    ph_sum[ph_sum > 0] = 255 # thresholding
    my_images.append(ph_sum) # add to python array to compare later

    # In the end we have ground truth correctly, compare this with the canny version later in the second for loop
    cv2.imwrite(os.path.join(path, f"{f_name}groundTruth.png"), ph_sum) # also save the image into images folder
    # which is in the same location with code

precision = 0
k = 0  # array counter for my_images
for file in glob.glob("*.jpg"):
    f_name = file.split('.')[0]
    img = cv2.imread(file, 0)
    upper, thresh_img = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) # Optimal threshold among my trials
    lower = .5 * upper
    blur = cv2.GaussianBlur(img, (7, 7), 0) # blur the image for better edge detection
    canny = cv2.Canny(blur, lower, upper) # apply canny filter
    canny[canny > 120] = 255 # do thresholding
    cv2.imwrite(os.path.join(path, f"{f_name}canny.png"), canny) # Save canny version of the img again to some folder

    precision += calc_precision(canny, my_images[k]) # Obtain the precision for the k'th image and accumulate the results
    k += 1 # holds how many images (200 for our case)

print("{:.4f}".format(precision / (k+1))) # This is the correct result until 4th decimal place.


import os
import yaml
import subprocess
from datetime import datetime, time

def qb_config():
	"""
	Top level config function.
	Set options from config.yml, find defaults in defaults.py (:config-write-py -d defaults.py to refresh).

	Base16 schemes are loaded from .Xresources or a base16 yaml file via the 'custom.base16.{color_scheme}.file' option,
	uses the default qutebrowser color scheme if this option is null or empty.
	"""
	config.load_autoconfig(False)

	with (config.configdir / 'config.yml').open() as f:
		yaml_data = yaml.safe_load(f)

		# STANDARD
		for k, v in filter(lambda i: not i[0].startswith('custom.'), yaml_data.items()):
			config.set(k, v)

		# CUSTOM
		for key, action in yaml_data['custom.keybinds'].items():
			config.bind(key, action)
		color_scheme = get_color_scheme_daynight()
		set_theme_base16(yaml_data[f'custom.base16.{color_scheme}.file'])
		c.colors.webpage.preferred_color_scheme = color_scheme
		c.colors.webpage.darkmode.enabled = color_scheme == 'dark' # fallback for websites that don't offer a dark theme

def get_color_scheme_daynight():
	timenow = datetime.now().time()
	timeday = datetime.strptime(os.getenv("TIMEDAY"), "%H:%M").time()
	timenight = datetime.strptime(os.getenv("TIMENIGHT"), "%H:%M").time()
	return 'dark' if (timenow >= timenight or timenow < timeday) else 'light'

def set_theme_base16(chosen):
	if (chosen):
		if ('.Xresources' in chosen):
			xpfx = '*.'
			base16 = dict(filter(lambda i: 'color' in i[0], read_xresources(xpfx).items()))
		else:
			with open(chosen) as base16_file:
				base16 = yaml.safe_load(base16_file)
		qb_config_base16_load({k:'#'+v for k,v in base16.items()})

def read_xresources(prefix):
	"""
	Get ~/.Xresources file properties.
	Source: https://www.qutebrowser.org/doc/help/configuring.html
	"""
	props = {}
	x = subprocess.run(['xrdb', '-query'], stdout=subprocess.PIPE)
	lines = x.stdout.decode().split('\n')
	for line in filter(lambda l : l.startswith(prefix), lines):
		prop, _, value = line.partition(':\t')
		props[prop] = value
	return props

def qb_config_base16_load(colors):
	"""
	Set qutebrowser colors via base16 dictionary
	Base16 qb Template by theova: https://github.com/theova/base16-qutebrowser

	Args:
		colors (dict): dictionary of base16 hex colors

	Returns:
		None
	"""
	# Text color of the completion widget. May be a single color to use for
	# all columns or a list of three colors, one for each column.
	c.colors.completion.fg = colors['base05']

	# Background color of the completion widget for odd rows.
	c.colors.completion.odd.bg = colors['base03']

	# Background color of the completion widget for even rows.
	c.colors.completion.even.bg = colors['base00']

	# Foreground color of completion widget category headers.
	c.colors.completion.category.fg = colors['base0A']

	# Background color of the completion widget category headers.
	c.colors.completion.category.bg = colors['base00']

	# Top border color of the completion widget category headers.
	c.colors.completion.category.border.top = colors['base00']

	# Bottom border color of the completion widget category headers.
	c.colors.completion.category.border.bottom = colors['base00']

	# Foreground color of the selected completion item.
	c.colors.completion.item.selected.fg = colors['base01']

	# Background color of the selected completion item.
	c.colors.completion.item.selected.bg = colors['base0A']

	# Top border color of the completion widget category headers.
	c.colors.completion.item.selected.border.top = colors['base0A']

	# Bottom border color of the selected completion item.
	c.colors.completion.item.selected.border.bottom = colors['base0A']

	# Foreground color of the matched text in the completion.
	c.colors.completion.match.fg = colors['base0B']

	# Color of the scrollbar handle in the completion view.
	c.colors.completion.scrollbar.fg = colors['base05']

	# Color of the scrollbar in the completion view.
	c.colors.completion.scrollbar.bg = colors['base00']

	# Background color for the download bar.
	c.colors.downloads.bar.bg = colors['base00']

	# Color gradient start for download text.
	c.colors.downloads.start.fg = colors['base00']

	# Color gradient start for download backgrounds.
	c.colors.downloads.start.bg = colors['base0D']

	# Color gradient end for download text.
	c.colors.downloads.stop.fg = colors['base00']

	# Color gradient stop for download backgrounds.
	c.colors.downloads.stop.bg = colors['base0C']

	# Foreground color for downloads with errors.
	c.colors.downloads.error.fg = colors['base08']

	# Font color for hints.
	c.colors.hints.fg = colors['base00']

	# Background color for hints. Note that you can use a `rgba(...)` value for transparency.
	c.colors.hints.bg = colors['base0A']

	# Font color for the matched part of hints.
	c.colors.hints.match.fg = colors['base05']

	# Text color for the keyhint widget.
	c.colors.keyhint.fg = colors['base05']

	# Highlight color for keys to complete the current keychain.
	c.colors.keyhint.suffix.fg = colors['base05']

	# Background color of the keyhint widget.
	c.colors.keyhint.bg = colors['base00']

	# Foreground color of an error message.
	c.colors.messages.error.fg = colors['base00']

	# Background color of an error message.
	c.colors.messages.error.bg = colors['base08']

	# Border color of an error message.
	c.colors.messages.error.border = colors['base08']

	# Foreground color of a warning message.
	c.colors.messages.warning.fg = colors['base00']

	# Background color of a warning message.
	c.colors.messages.warning.bg = colors['base0E']

	# Border color of a warning message.
	c.colors.messages.warning.border = colors['base0E']

	# Foreground color of an info message.
	c.colors.messages.info.fg = colors['base05']

	# Background color of an info message.
	c.colors.messages.info.bg = colors['base00']

	# Border color of an info message.
	c.colors.messages.info.border = colors['base00']

	# Foreground color for prompts.
	c.colors.prompts.fg = colors['base05']

	# Border used around UI elements in prompts.
	c.colors.prompts.border = colors['base00']

	# Background color for prompts.
	c.colors.prompts.bg = colors['base00']

	# Background color for the selected item in filename prompts.
	c.colors.prompts.selected.bg = colors['base0A']

	# Foreground color of the statusbar.
	c.colors.statusbar.normal.fg = colors['base0A']

	# Background color of the statusbar.
	c.colors.statusbar.normal.bg = colors['base00']

	# Foreground color of the statusbar in insert mode.
	c.colors.statusbar.insert.fg = colors['base00']

	# Background color of the statusbar in insert mode.
	c.colors.statusbar.insert.bg = colors['base0A']

	# Foreground color of the statusbar in passthrough mode.
	c.colors.statusbar.passthrough.fg = colors['base00']

	# Background color of the statusbar in passthrough mode.
	c.colors.statusbar.passthrough.bg = colors['base0A']

	# Foreground color of the statusbar in private browsing mode.
	c.colors.statusbar.private.fg = colors['base00']

	# Background color of the statusbar in private browsing mode.
	c.colors.statusbar.private.bg = colors['base03']

	# Foreground color of the statusbar in command mode.
	c.colors.statusbar.command.fg = colors['base05']

	# Background color of the statusbar in command mode.
	c.colors.statusbar.command.bg = colors['base00']

	# Foreground color of the statusbar in private browsing + command mode.
	c.colors.statusbar.command.private.fg = colors['base05']

	# Background color of the statusbar in private browsing + command mode.
	c.colors.statusbar.command.private.bg = colors['base00']

	# Foreground color of the statusbar in caret mode.
	c.colors.statusbar.caret.fg = colors['base00']

	# Background color of the statusbar in caret mode.
	c.colors.statusbar.caret.bg = colors['base0E']

	# Foreground color of the statusbar in caret mode with a selection.
	c.colors.statusbar.caret.selection.fg = colors['base00']

	# Background color of the statusbar in caret mode with a selection.
	c.colors.statusbar.caret.selection.bg = colors['base0D']

	# Background color of the progress bar.
	c.colors.statusbar.progress.bg = colors['base0D']

	# Default foreground color of the URL in the statusbar.
	c.colors.statusbar.url.fg = colors['base05']

	# Foreground color of the URL in the statusbar on error.
	c.colors.statusbar.url.error.fg = colors['base08']

	# Foreground color of the URL in the statusbar for hovered links.
	c.colors.statusbar.url.hover.fg = colors['base05']

	# Foreground color of the URL in the statusbar on successful load
	# (http).
	c.colors.statusbar.url.success.http.fg = colors['base0C']

	# Foreground color of the URL in the statusbar on successful load
	# (https).
	c.colors.statusbar.url.success.https.fg = colors['base09']

	# Foreground color of the URL in the statusbar when there's a warning.
	c.colors.statusbar.url.warn.fg = colors['base0E']

	# Background color of the tab bar.
	c.colors.tabs.bar.bg = colors['base00']

	# Color gradient start for the tab indicator.
	c.colors.tabs.indicator.start = colors['base0D']

	# Color gradient end for the tab indicator.
	c.colors.tabs.indicator.stop = colors['base0C']

	# Color for the tab indicator on errors.
	c.colors.tabs.indicator.error = colors['base08']

	# Foreground color of unselected odd tabs.
	c.colors.tabs.odd.fg = colors['base05']

	# Background color of unselected odd tabs.
	c.colors.tabs.odd.bg = colors['base03']

	# Foreground color of unselected even tabs.
	c.colors.tabs.even.fg = colors['base05']

	# Background color of unselected even tabs.
	c.colors.tabs.even.bg = colors['base00']

	# Foreground color of selected odd tabs.
	c.colors.tabs.selected.odd.fg = colors['base00']

	# Background color of selected odd tabs.
	c.colors.tabs.selected.odd.bg = colors['base05']

	# Foreground color of selected even tabs.
	c.colors.tabs.selected.even.fg = colors['base00']

	# Background color of selected even tabs.
	c.colors.tabs.selected.even.bg = colors['base05']

	# Background color for webpages if unset (or empty to use the theme's color).
	c.colors.webpage.bg = colors['base00']

qb_config()


import numpy as np
from sklearn.cluster import KMeans as kmeans
import time

def k_means_tree(data, branch_factor=5, leaf_size=50, max_iter=7):
    ndata, ndim = np.shape(data)
    tree = []
    if ndata < branch_factor:
        tree.append((data, 0, data.mean(axis=0)))
    else:
        km = kmeans(n_clusters=branch_factor, n_init=1, max_iter=max_iter).fit(data)
        # Stack is to-do list, (data, parentnumber, node number, leaf)
        tree.append((None, 0, km.cluster_centers_))
        stack = []
        for i in range(branch_factor):
            stack.append((data[km.labels_ == i, :], i+1, np.sum(km.labels_ == i) < leaf_size))
        while stack:
            data, node, leaf = stack.pop()
            if leaf:
                tree.append((data, node, None))
            else:
                km = km.fit(data)
                tree.append((None, node, km.cluster_centers_))
                for i in range(branch_factor):
                    stack.append((data[km.labels_ == i, :], node*branch_factor+i+1,
                                  np.sum(km.labels_ == i) < leaf_size))

    return tree

X = np.load('A18.npy')
X = X[:10000, 3:]
n, m = np.shape(X)
X = (X-np.outer(np.ones(n), np.mean(X, axis=0)))/np.sqrt(np.var(X, axis=0))
u, s, v = np.linalg.svd(X, full_matrices=False, compute_uv=True)  # Singular Value Decomposition (for PCs)
X = np.dot(X, v[:, :2])  # Matrix transformation with dim. limit
t = time.time()
Tree = k_means_tree(X, branch_factor=3, leaf_size=50)
buildtime = time.time() - t
print('Tree size: %.0f, found in %.3f s' % (len(Tree), buildtime))
print('All done')


import os
import requests as r

current_dir = os.path.dirname(os.path.realpath(__file__))
old_events_path = os.path.join(current_dir, 'data/old.json')

response = r.get('http://eventlist.mk/events')

with open(old_events_path, 'w') as f:
	f.write(response.content)


#!/usr/bin/env python

"""
Uses orientation data from `/imu/data` and position data from
`/piksi/navsatfix_best_fix` and creates an odometry message that is published
to `/tractor_odom`. Also broadcasts this odometry message as the transform
between `/base_link` and `/odom`
"""

import rospy
from sensor_msgs.msg import Imu
from nav_msgs.msg import Odometry
import tf

class TractorOdom:
    def __init__(self):
        rospy.init_node("tractor_odom")
        self.imu_sub = rospy.Subscriber('/imu/data', Imu, self.imuCB)
        self.gps_sub = rospy.Subscriber('/gps_odom', Odometry, self.gpsCB)
        self.odom_pub = rospy.Publisher('/tractor_odom', Odometry, queue_size=1)
        self.update_rate = rospy.Rate(10)

        self.odom_broadcaster = tf.TransformBroadcaster()

        self._imu_msg = Imu()
        self._gps_msg = Odometry()

    def imuCB(self, msg):
        self._imu_msg = msg

    def gpsCB(self, msg):
        self._gps_msg = msg

    def computeTractorOdom(self):
        """Creates an Odometry message from imu orientation data and gps
        position data. Also broadcasts this data as a transform between
        /base_link and /odom
        """
        msg = Odometry()
        msg.header.frame_id='/odom'
        msg.header.stamp = rospy.Time.now()
        msg.child_frame_id='/base_link'
        msg.pose.pose.position = self._gps_msg.pose.pose.position
        msg.pose.pose.orientation = self._imu_msg.orientation
        self.odom_pub.publish(msg)

        # Broadcast message as tf
        self.odom_broadcaster.sendTransform((msg.pose.pose.position.x,
                                             msg.pose.pose.position.y,
                                             msg.pose.pose.position.z),
                                            (msg.pose.pose.orientation.w,
                                             msg.pose.pose.orientation.x,
                                             msg.pose.pose.orientation.y,
                                             msg.pose.pose.orientation.z),
                                            rospy.Time.now(),
                                            "/base_link",
                                            "/odom")

    def run(self):
        rospy.loginfo("Starting Tractor Odom")
        while not rospy.is_shutdown():
            self.computeTractorOdom()
            self.update_rate.sleep()

if __name__=="__main__":
    tOdom = TractorOdom()
    tOdom.run()


from code import app
from flask import request
from code.sql_query_builder import SQLQueryBuilder as query
from code.database import Database as database
from code.post import Post as post
from code.image import Image as image
from code.video import Video as video
from code.thread import Thread as thread
from code.react import React as react
from code.observer import Observer

blogColor = ""
blogFont = ""
blogUrlName = ""

class BlogView(Observer):
    def __init__(self):
        super().__init__()

    #abstract, inherited
    def buildContent(self):
        return """

<title>{blogName}</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap-theme.min.css">
<link href="https://afeld.github.io/emoji-css/emoji.css" rel="stylesheet">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Lato">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

<link rel="stylesheet" type="text/css" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.7.1/themes/base/jquery-ui.css"/>

<link rel="stylesheet" href="static/blogEditingStyle.css" />

            Home
            Logout
            Login
            Sign-up

            <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenu2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Toolbar</button>

        <form class="px-4 py-3">

            <button type="button" id="addText" class="btn btn-default">Add Post</button>
            <button type="button" id="addImage" class="btn btn-default">Add Image</button>
            <button type="button" id="addVideo" class="btn btn-default">Add Video</button>

            Page Background Colour:
              <input type="color" class="form-control" id="changeBackground" value="#000000">

            Page Font:
            <select id="changeFont" class="form-control">
              <option style="font-family: Arial;" value="arial">Arial</option>
              <option style="font-family: Times;" value="times">Times New Roman</option>
              <option style="font-family: Courier New;" value="courier new">Courier New</option>
              <option style="font-family: Verdana;" value="verdana">Verdana</option>
              <option style="font-family: Georgia;" value="georgia">Georgia</option>
              <option style="font-family: Garamond;" value="garamond">Garamond</option>
              <option style="font-family: Comic Sans MS;" value="comic sans ms">Comic Sans MS</option>
              <option style="font-family: Trebuchet MS;" value="trebuchet ms">Trebuchet MS</option>
              <option style="font-family: Arial Black;" value="arial black">Arial Black</option>
              <option style="font-family: Impact;" value="impact">Impact</option>
            </select>

        </form>

            Login
            Sign-up

      {blogContent}

Edit

        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          ×
        </button>

        Error

        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        <button id="saveChanges" type="button" class="btn btn-primary">Save changes</button>

  <form>
  </form>

    {editButton}
    <button type="button" style="display:none; position: absolute; left: 20px;" id="disableEditing" class="btn btn-default">Exit Edit Mode</button>
    Statistics
    <button type="button" style="display:inline; position: absolute; right: 20px;" id="save" class="btn btn-success">Save Changes</button>

</footer
"""

@app.route("/uploadComment", methods=['GET', 'POST'])

def uploadComment():
    global blogUrlName
    if request.method == 'POST':
        requestData = request.get_json()
        db = database()
        queryBuilder = query("comments")
        queryString = queryBuilder.insertRow("'{blogName}', '{attachedToId}', '{currentUser}', '{comment}'".format(blogName=blogUrlName,
                attachedToId=requestData.get("attachedToId"), currentUser=request.cookies.get('userId'), comment=requestData.get("comment")))
        db.execute(True, queryString)
        db.disconnect()
        return str(requestData)
    else:
        db.disconnect()
        return "error"

@app.route("/uploadReaction", methods=['GET', 'POST'])

def uploadReaction():
    global blogUrlName
    if request.method == 'POST':
        requestData = request.get_json()
        db = database()
        queryBuilder = query("reactions")
        #need to check if user has reacted to that element before; if so, update instead of insert
        queryString = queryBuilder.selectCountFilter("blogName='{blogName}' and attachedToId='{id}' and username='{currentUser}'".format(
                blogName=blogUrlName, id=requestData.get("attachedToId"), currentUser=request.cookies.get('userId')));
        result = db.execute(False, queryString);
        if result[0][0] == 0:
            queryString = queryBuilder.insertRow("'{blogName}', '{attachedToId}', '{currentUser}', '{emote}'".format(
                    blogName=blogUrlName, attachedToId=requestData.get("attachedToId"), currentUser=request.cookies.get('userId'), emote=requestData.get("emote")))
        else:
            queryString = queryBuilder.update("emote='{emote}'".format(emote=requestData.get("emote")),
                                              "blogName='{blogName}' and attachedToId='{id}' and username='{currentUser}'".format(blogName=blogUrlName, id=requestData.get("attachedToId"), currentUser=request.cookies.get('userId')))
        db.execute(True, queryString)
        db.disconnect()
        return str(requestData)
    else:
        db.disconnect()
        return "error"

@app.route("/blogView", methods=['GET', 'POST'])

def blogView():
    global blogUrlName
    if request.method == 'POST':
        requestData = request.get_json()#this is a dictionary
        db = database()
        for key, value in requestData.items():
            #check if action is present, if not, must be blog update
            if "not present" in value.get("action", "not present"):
                queryBuilder = query("blog")
                queryString = queryBuilder.update("backgroundColor='{color}', font='{font}'".format(
                    color=value.get("backgroundColor"), font=value.get("font")),
                                                  "blogName='{blogName}'".format(blogName=blogUrlName))
                db.execute(True, queryString)
            elif "insert" in value.get("action"):
                if "post" in key:
                    queryBuilder = query("posts")
                    queryString = queryBuilder.insertRow("'{blogName}', '{id}', {top}, {left}, {width}, {height}, {depth}, '{title}', '{body}', '{backgroundColor}', '{fontColor}', {hasThread}".format(
                                    blogName=blogUrlName, id=key, top=value.get("top"), left=value.get("left"), width=value.get("width"),
                                    height=value.get("height"), depth=value.get("depth"), title=value.get("title"),
                                    body=value.get("content"), backgroundColor=value.get("backgroundColor"), fontColor=value.get("fontColor"), hasThread=value.get("hasThread")))
                    db.execute(True, queryString)
                elif "image" in key:
                    queryBuilder = query("images")
                    queryString = queryBuilder.insertRow("'{blogName}', '{id}', {top}, {left}, {width}, {height}, {depth}, '{source}', {hasThread}".format(
                                    blogName=blogUrlName, id=key, top=value.get("top"), left=value.get("left"), width=value.get("width"),
                                    height=value.get("height"), depth=value.get("depth"), source=value.get("source"), hasThread=value.get("hasThread")))
                    db.execute(True, queryString)
                elif "video" in key:
                    queryBuilder = query("videos")
                    queryString = queryBuilder.insertRow("'{blogName}', '{id}', {top}, {left}, {width}, {height}, {depth}, '{source}', {hasThread}".format(
                                    blogName=blogUrlName, id=key, top=value.get("top"), left=value.get("left"), width=value.get("width"),
                                    height=value.get("height"), depth=value.get("depth"), source=value.get("source"), hasThread=value.get("hasThread")))
                    db.execute(True, queryString)
                else:
                    return "error"
            elif "update" in value.get("action"):
                if value.get("hasThread") == 0:
                    queryBuilder = query("comments")
                    queryString = queryBuilder.delete("blogName='{blogName}' AND attachedToId='{id}'".format(blogName=blogUrlName, id=key))
                    db.execute(True, queryString)
                if "post" in key:
                    queryBuilder = query("posts")
                    queryString = queryBuilder.update("topVal={top}, leftVal={left}, width={width}, height={height}, depth={depth}, title='{title}', body='{body}', backgroundColor='{backgroundColor}', fontColor='{fontColor}', hasThread={hasThread}".format(
                                    top=value.get("top"), left=value.get("left"), width=value.get("width"),
                                    height=value.get("height"), depth=value.get("depth"), title=value.get("title"),
                                    body=value.get("content"), backgroundColor=value.get("backgroundColor"), fontColor=value.get("fontColor"), hasThread=value.get("hasThread")),
                                                     "blogName='{blogName}' AND id='{id}'".format(blogName=blogUrlName, id=key))
                    db.execute(True, queryString)
                elif "image" in key:
                    queryBuilder = query("images")
                    queryString = queryBuilder.update("topVal={top}, leftVal={left}, width={width}, height={height}, depth={depth}, imageSource='{source}', hasThread={hasThread}".format(
                                    top=value.get("top"), left=value.get("left"), width=value.get("width"),
                                    height=value.get("height"), depth=value.get("depth"), source=value.get("source"), hasThread=value.get("hasThread")),
                                                     "blogName='{blogName}' AND id='{id}'".format(blogName=blogUrlName, id=key))
                    db.execute(True, queryString)
                elif "video" in key:
                    queryBuilder = query("videos")
                    queryString = queryBuilder.update("topVal={top}, leftVal={left}, width={width}, height={height}, depth={depth}, videoSource='{source}', hasThread={hasThread}".format(
                                    top=value.get("top"), left=value.get("left"), width=value.get("width"),
                                    height=value.get("height"), depth=value.get("depth"), source=value.get("source"), hasThread=value.get("hasThread")),
                                                     "blogName='{blogName}' AND id='{id}'".format(blogName=blogUrlName, id=key))
                    db.execute(True, queryString)
                else:
                    return "error"
            elif "delete" in value.get("action"):
                if value.get("hasThread") == 1:
                    queryBuilder = query("comments")
                    queryString = queryBuilder.delete("blogName='{blogName}' AND attachedToId='{id}'".format(blogName=blogUrlName, id=key))
                    db.execute(True, queryString)
                if "post" in key:
                    queryBuilder = query("posts")
                    queryString = queryBuilder.delete("blogName='{blogName}' AND id='{id}'".format(blogName=blogUrlName, id=key))
                    db.execute(True, queryString)
                    #delete all comments for a deleted element
                    queryBuilder = query("reactions")
                    queryString = queryBuilder.delete("blogName='{blogName}' AND attachedToId='{id}'".format(blogName=blogUrlName, id=key))
                    db.execute(True, queryString)
                elif "image" in key:
                    queryBuilder = query("images")
                    queryString = queryBuilder.delete("blogName='{blogName}' AND id='{id}'".format(blogName=blogUrlName, id=key))
                    db.execute(True, queryString)
                    #delete all comments for a deleted element
                    queryBuilder = query("reactions")
                    queryString = queryBuilder.delete("blogName='{blogName}' AND attachedToId='{id}'".format(blogName=blogUrlName, id=key))
                    db.execute(True, queryString)
                elif "video" in key:
                    queryBuilder = query("videos")
                    queryString = queryBuilder.delete("blogName='{blogName}' AND id='{id}'".format(blogName=blogUrlName, id=key))
                    db.execute(True, queryString)
                    #delete all comments for a deleted element
                    queryBuilder = query("reactions")
                    queryString = queryBuilder.delete("blogName='{blogName}' AND attachedToId='{id}'".format(blogName=blogUrlName, id=key))
                    db.execute(True, queryString)
                else:
                    return "error"
            else:
                return "error"
        db.disconnect()
        return str(requestData)
    else:
        viewObject = BlogView()
        blogUrlName = request.args.get("blogName", "error")
        buildBlogSpecs()
        #if current user token is not owner of blog, don't display edit
        editBlogButton = ""
        currentUser = request.cookies.get('userId', "")
        if currentUser != "":
            db = database()
            queryBuilder = query("blog")
            queryString = queryBuilder.selectAllFilter("blogName='{blogName}' AND username='{username}'".format(blogName=blogUrlName, username=currentUser))
            result = db.execute(False, queryString)
            db.disconnect()
            if result != []:
                editBlogButton = """
<button type="button" id="enableEditing" style="position: absolute; left: 20px;" class="btn btn-default">Enable Edit Mode</button>
"""
        return viewObject.html.format(blogName=blogUrlName,
                  blog=blogUrlName,
                  blogContent=buildBlogContent(),
                  backgroundColor=blogColor,
                  font=blogFont,
                  editButton=editBlogButton)

def buildBlogSpecs():
    global blogUrlName
    global blogColor
    global blogFont
    db = database()
    queryBuilder = query("blog")
    queryString = queryBuilder.selectAllFilter("blogName='{blogName}'".format(blogName=blogUrlName))
    result = db.execute(False, queryString)
    db.disconnect()
    if result == []:
        blogColor = "rgb(255, 255, 255)"
        blogFont = "arial"
    else:
        for row in result:
            blogColor = row[4]
            blogFont = row[5].replace('"', '')

def buildBlogContent():
    db = database()
    content = ""
    content += buildElement(db, "posts")
    content += buildElement(db, "images")
    content += buildElement(db, "videos")
    db.disconnect()
    return content

def buildElement(db, tableName):
    global blogUrlName
    content = ""
    addThreadButton = """<button type="button" class="dropdown-item addThread">Add Thread</button>"""
    removeThreadButton = """<button type="button" class="dropdown-item removeThread">Remove Thread</button>"""
    queryBuilder = query(tableName)
    queryString = queryBuilder.selectAllFilter("blogName='{blogName}'".format(blogName=blogUrlName))
    result = db.execute(False, queryString)
    if result == []:
        return ""
    else:
        for row in result:
            if tableName == "posts":
                currentElement = post(row)
                #if has thread, format with content, otherwise ""
                if row[11] == 1:
                    content += currentElement.buildHtml().format(thread=buildThread(db, row[1]),
                                                                 addRemoveThread=removeThreadButton,
                                                                 react=buildReactions(db, row[1]))
                else:
                    content += currentElement.buildHtml().format(thread="",
                                                                 addRemoveThread=addThreadButton,
                                                                 react=buildReactions(db, row[1]))
            elif tableName == "images":
                currentElement = image(row)
                if row[8] == 1:
                    content += currentElement.buildHtml().format(thread=buildThread(db, row[1]),
                                                                 addRemoveThread=removeThreadButton,
                                                                 react=buildReactions(db, row[1]))
                else:
                    content += currentElement.buildHtml().format(thread="",
                                                                 addRemoveThread=addThreadButton,
                                                                 react=buildReactions(db, row[1]))
            elif tableName == "videos":
                currentElement = video(row)
                if row[8] == 1:
                    content += currentElement.buildHtml().format(thread=buildThread(db, row[1]),
                                                                 addRemoveThread=removeThreadButton,
                                                                 react=buildReactions(db, row[1]))
                else:
                    content += currentElement.buildHtml().format(thread="",
                                                                 addRemoveThread=addThreadButton,
                                                                 react=buildReactions(db, row[1]))
            else:
                content += "error"
        return content

def buildThread(db, key):
    global blogUrlName
    queryBuilder = query("comments")
    queryString = queryBuilder.selectAllFilter("blogName='{blogName}' and attachedToId='{elementId}'".format(blogName=blogUrlName, elementId=key))
    result = db.execute(False, queryString)
    obj = thread(result)
    return obj.buildHtml()

def buildReactions(db, key):
    global blogUrlName
    queryBuilder = query("reactions")
    obj = react(db, queryBuilder, blogUrlName, key)
    return obj.buildHtml()


from typing import Optional

from notebook.notebookapp import NotebookApp
from prometheus_client import Gauge

from empty_trash.metrics import TrashMetricsLoader

try:
    # Traitlets >= 4.3.3
    from traitlets import Callable
except ImportError:
    from .utils import Callable

class PrometheusHandler(Callable):
    def __init__(self, metricsloader: TrashMetricsLoader):
        super().__init__()
        self.metricsloader = metricsloader
        self.config = metricsloader.config
        self.session_manager = metricsloader.nbapp.session_manager

        gauge_names = ["total_home", "max_home"]
        for name in gauge_names:
            phrase = name + "_usage"
            gauge = Gauge(phrase, "counter for " + phrase.replace("_", " "), [])
            setattr(self, phrase.upper(), gauge)

    async def __call__(self, *args, **kwargs):

        # two values
        disk_metric_values = self.metricsloader.disk_metrics()
        self.TOTAL_HOME_USAGE.set(disk_metric_values["disk_usage"])
        self.MAX_HOME_USAGE.set(self.apply_disk_limit(disk_metric_values))

    def apply_disk_limit(self, disk_metric_values) -> Optional[str]:
        if disk_metric_values is None:
            return None
        else:
            if callable(self.config.disk_limit):

                return self.config.disk_limit(disk_usage=disk_metric_values["disk_usage"])
            elif self.config.disk_limit > 0:  # disk_limit is an Int
                return self.config.disk_limit
            else:
                return disk_metric_values["disk_total"]


import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import math

def eulerMatrix(theta):
    return np.array([[math.cos(theta),-math.sin(theta)],[math.sin(theta),math.cos(theta)]])

a,b,theta=[float(x) for x in input().split()]
slices=100
x=math.cos(theta)*a
y=math.sin(theta)*a
dphi=2*math.pi/slices
r=np.array([x,y]).reshape((2,1))
R=eulerMatrix(theta)
A=np.array([[math.cos(dphi),-a/b*math.sin(dphi)],[b/a*math.sin(dphi),math.cos(dphi)]])
# be careful with the transpose
M=np.dot(R,np.dot(A,R.T))

pointList=[]
plt.scatter(*r)
for phi in np.linspace(0,2*math.pi,slices):
    r=np.dot(M,r)
    pointList.append(np.round(r))
    plt.scatter(*pointList[-1])
plt.show()
# print(pointList)
# print(M)

# Another version:

# r=np.array([a,0]).reshape((2,1))
# plt.scatter(*np.dot(R,r))
# for phi in np.linspace(0,2*math.pi,slices):
#     r=np.dot(A,r)
#     plt.scatter(*np.dot(R,r))
# plt.show()

# draw a filled a polygon.

# def fill(pointCloud):
#     """
#     pass in a N*2 point array as an ordered polygon.
#     """
#     for y in range(np.min(pointCloud(:,1)),np.max(pointCloud(:,1))+1):
#         for x in activeRange()


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""dslr/DescriberClass.py:
    - class Describe
    - tests for the class

    Class Describe reproduces the behavior of pandas library
    describe() function for the mandatory part of 42's subject.

    Bonus:
    More statistics lines are provided if bonus=True
    for self.agg_describe() method.
"""
__authors__ = ['jmouaike, ebremond']

import numpy as np
import pandas as pd

from utils import describe_stats as dum

class Describe:
    """ Reproduces the behavior of pandas pd.describe() function
    Parameter : a pandas dataframe
    Output :
        displays information for all numerical features of the dataframe
    """
    def __init__(self, df: pd.DataFrame):
        self.df_num = df[df.select_dtypes(include=np.number).columns]
        self.funcs = [dum.count, dum.mean, dum.std, dum.min,
                      dum.quantile_25, dum.quantile_50,
                      dum.quantile_75, dum.max]
        self.bonus_funcs = [dum.count_nan]

    def agg_describe(self, bonus=False):
        """ using custom functions and counting NaN
        [9 rows x 13 columns]"""
        new_idx_names = {'quantile_25': '25%',
                         'quantile_50': '50%',
                         'quantile_75': '75%'}
        if self.df_num.empty:
            return None
        if bonus:
            self.funcs += self.bonus_funcs
        self.description = self.df_num.agg(self.funcs)
        self.description.rename(index=new_idx_names, inplace=True)
        print(self.description.map(lambda x: f"{x:0.6f}"))
        return self.description

def test_describe_class():
    """  """
    df = pd.DataFrame({'categorical': pd.Categorical(['d', 'e', 'f', 'g']),
                       'feature1': [1, 22, 21, 42],
                       'feature2': [50, 17, 42, 23]})
    print("TEST : Describe class")
    pandas_stats = df.describe()
    print("pandas describe() :")
    print(df.describe())
    description = Describe(df)
    print("dslr project describe() :")
    stats = description.agg_describe(False)
    print("Results :")
    result = (stats == pandas_stats)
    print(result)

if __name__ == "__main__":
    test_describe_class()

"""
pd.describe() describes numeric columns including Index

count
mean
std
min
25%
50%
75%
max

empty_dataframe.describe()

count   0
unique  0
top     NaN
freq    NaN

https://inside-machinelearning.com/skewness-et-kurtosis/
    Skewness
    Kurtosis
    No. of 3 Sigma Outliers
"""