"""
This code contains the results of the occlusion testing as well as functions to plot the results.

This code was written and designed by Christopher du Toit.
"""
import os.path
import numpy as np
import matplotlib.pyplot as plt
import pickle
import torch
from timesformer.visualization.utils import get_confusion_matrix, plot_confusion_matrix

percentage = [0, 10, 20, 30, 40, 50]
frames = [i for i in range(5)]

TIBAV_mix_max = [
    [81.02, 80.48, 79.41, 78.61, 73.53],
    [65.24, 61.23, 59.09, 56.42, 53.21],
    [51.60, 47.59, 42.51, 36.36, 31.55],
    [42.51, 39.04, 37.70, 36.63, 35.56],
    [36.90, 33.96, 34.49, 32.89, 35.56],
    [31.55, 31.82, 32.09, 32.89, 33.69]
                 ]
TIBAV_mix_max = np.array(TIBAV_mix_max)

TIBAV_mix_min = [
    [81.02, 80.21, 81.55, 78.88, 78.34],
    [80.21, 77.81, 79.14, 77.54, 73.50],
    [75.40, 75.40, 76.20, 72.46, 68.98],
    [74.87, 73.26, 74.33, 71.66, 66.84],
    [72.46, 71.12, 70.05, 66.84, 60.96],
    [71.39, 70.05, 67.65, 64.97, 59.89]
]
TIBAV_mix_min = np.array(TIBAV_mix_min)

GradCAM_mix_max =[
    [81.02, 79.14, 78.34, 77.27, 71.66],
    [67.91, 67.38, 63.64, 63.10, 58.56],
    [52.14, 57.49, 56.68, 56.15, 49.73],
    [40.91, 52.41, 52.14, 50.27, 47.59],
    [33.69, 41.71, 41.71, 45.45, 41.71],
    [24.87, 30.75, 31.55, 36.10, 38.77]
]
GradCAM_mix_max = np.array(GradCAM_mix_max)

GradCAM_mix_min =[
    [81.02, 81.55, 81.82, 79.95, 79.14],
    [72.73, 71.12, 69.52, 66.31, 63.37],
    [66.04, 61.50, 57.49, 48.40, 41.44],
    [71.39, 65.78, 60.43, 54.28, 45.72],
    [64.44, 60.70, 56.68, 51.60, 47.06],
    [59.36, 57.75, 54.01, 50.53, 47.33]
]
GradCAM_mix_min = np.array(GradCAM_mix_min)

Rollout_mix_max = [
    [81.02, 81.82, 81.82, 80.75, 72.19],
    [64.17, 63.90, 62.03, 54.28, 50.53],
    [52.67, 43.58, 40.37, 29.68, 28.34],
    [46.52, 37.70, 30.21, 25.13, 21.66],
    [37.43, 36.10, 30.09, 33.42, 32.62],
    [31.82, 27.27, 18.18, 19.58, 16.58]
]
Rollout_mix_max = np.array(Rollout_mix_max)

Rollout_mix_min = [
    [81.02, 79.95, 80.48, 79.95, 76.47],
    [77.27, 77.27, 76.74, 73.26, 68.72],
    [76.20, 75.67, 74.03, 69.79, 65.24],
    [71.39, 72.46, 70.59, 65.51, 59.63],
    [68.72, 69.25, 67.91, 64.71, 56.15],
    [67.38, 66.58, 67.38, 60.43, 51.60]
]
Rollout_mix_min = np.array(Rollout_mix_min)

Rollout_grad_mix_max = [
    [81.02, 78.88, 79.95, 79.41, 71.39],
    [67.91, 66.04, 62.30, 55.88, 47.86],
    [60.43, 56.42, 53.21, 44.92, 37.97],
    [40.64, 34.49, 32.35, 28.88, 27.81],
    [29.41, 26.47, 27.54, 26.74, 27.27],
    [27.27, 29.14, 28.88, 31.02, 31.02]
]
Rollout_grad_mix_max = np.array(Rollout_grad_mix_max)

Rollout_grad_mix_min = [
    [81.02, 79.95, 80.48, 80.21, 78.61],
    [78.07, 78.61, 77.54, 75.67, 71.12],
    [74.87, 76.20, 74.87, 71.66, 69.25],
    [74.60, 73.53, 72.46, 71.39, 65.51],
    [72.46, 70.86, 70.05, 66.84, 62.83],
    [63.90, 65.24, 64.71, 63.64, 58.29]
]
Rollout_grad_mix_min = np.array(Rollout_grad_mix_min)

def plot_mix():
    for i, percent in enumerate(percentage):
        fig = plt.figure()
        ax = plt.subplot(111)
        plt.title(f"{percent}% Spacial Occlusion")
        ax.plot(frames, TIBAV_mix_max[i], marker='x', color='b', linestyle='dashed', label="TIBAV MAX")
        ax.plot(frames, GradCAM_mix_max[i], marker='x', color='r', linestyle='dashed', label="GradCAM MAX")
        ax.plot(frames, Rollout_mix_max[i], marker='x', color='g', linestyle='dashed', label="Rollout MAX")
        ax.plot(frames, Rollout_grad_mix_max[i], marker='x', color='black', linestyle='dashed', label="Rollout Grad MAX")

        ax.plot(frames, TIBAV_mix_min[i], marker='+', color='b', linestyle='dashed', label="TIBAV MIN")
        ax.plot(frames, GradCAM_mix_min[i], marker='+', color='r',linestyle='dashed', label="GradCAM MIN")
        ax.plot(frames, Rollout_mix_min[i], marker='+', color='g', linestyle='dashed', label="Rollout MIN")
        ax.plot(frames, Rollout_grad_mix_min[i], marker='+', color='black', linestyle='dashed', label="Rollout Grad MIN")

        ax.plot(frames, TIBAV_mix_min[i] - TIBAV_mix_max[i], marker='o', color='b', label="TIBAV DIFF")
        ax.plot(frames, GradCAM_mix_min[i] - GradCAM_mix_max[i], marker='o', color='r', label="GradCAM DIFF")
        ax.plot(frames, Rollout_mix_min[i] - Rollout_mix_max[i], marker='o', color='g', label="Rollout DIFF")
        ax.plot(frames, Rollout_grad_mix_min[i] - Rollout_grad_mix_max[i], marker='o', color='black', label="Rollout Grad DIFF")

        plt.legend(["TIBAV MAX", "GradCAM MAX", "Rollout MAX", "Rollout Grad MAX", "TIBAV MIN", "GradCAM MIN", "Rollout MIN", "Rollout Grad MIN", "TIBAV DIFF", "GradCAM DIFF", "Rollout DIFF", "Rollout Grad MAX Diff"], loc='upper right')
        plt.xlabel("Number of frames occluded")
        plt.ylabel("Model accuracy (%)")
        box = ax.get_position()
        ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])

        # Put a legend to the right of the current axis
        ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        plt.show()

def plot_diff():
    for i, percent in enumerate(percentage):
        fig = plt.figure()
        ax = plt.subplot(111)
        plt.title(f"{percent}% Spacial Occlusion")

        ax.plot(frames, TIBAV_mix_min[i] - TIBAV_mix_max[i], marker='o', color='b', label="TIBAV DIFF")
        ax.plot(frames, GradCAM_mix_min[i] - GradCAM_mix_max[i], marker='o', color='r', label="GradCAM DIFF")
        ax.plot(frames, Rollout_mix_min[i] - Rollout_mix_max[i], marker='o', color='g', label="Rollout DIFF")
        ax.plot(frames, Rollout_grad_mix_min[i] - Rollout_grad_mix_max[i], marker='o', color='black', label="Rollout Grad DIFF")

        plt.legend(["GradCAM DIFF", "Rollout DIFF", "Rollout Grad MAX Diff"], loc='upper right')
        plt.xlabel("Number of frames occluded")
        plt.ylabel("Difference in accuracies (%)")
        plt.ylim(0, 50)
        box = ax.get_position()
        ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])

        # Put a legend to the right of the current axis
        ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        plt.show()

def check_accuracy(true_labels, preds_labels):
    pred_labels = torch.argmax(preds_labels, dim=1)
    count = 0
    for i in range(pred_labels.shape[0]):
        if pred_labels[i] == true_labels[i]:
            count += 1
    return count/pred_labels.shape[0] * 100

Eyes = 62.30
Eyes_Mouth = 35.83
Eyes_Mouth_Nose = 28.88
Eyes_Nose = 55.88
Mouth = 62.30
Nose = 76.47
Nose_Mouth = 60.96

# true_labels = []
# with open("CREMA_D/avi_videos/test.csv") as r:
#     csv_file = csv.reader(r, delimiter=' ')
#     for index, row in enumerate(csv_file):
#         true_labels.append(int(row[1]))
# true_labels = np.array(true_labels)

def confusion_matrix(face_occ):
    file = os.path.join(r"C:\Users\Gebruiker\Documents\GitHub\Research_internship\CREMA_D\Occlusion\Face_parts\preds_labels", face_occ)
    with open(file, "rb") as f:
        outputs = pickle.load(f)

    preds = outputs[0]
    true_labels = outputs[1]
    class_names = ['happy', 'sad', 'anger', 'fear', 'disgust', 'neutral']
    print(check_accuracy(true_labels, preds))

    cmtx = get_confusion_matrix(preds, true_labels, 6)
    figure, plt = plot_confusion_matrix(cmtx, 6, class_names, title="Parts occluded = " + face_occ)
    plt.show()
    return figure

# import matplotlib; matplotlib.use("TkAgg")
facial_parts = ['No_Occ', 'Eyes', 'Eyes_Mouth', 'Eyes_Mouth_Nose', 'Eyes_Nose', 'Mouth', 'Nose', 'Nose_Mouth']

for part in facial_parts:
    confusion_matrix(part)

# plot_diff()


import os

from django.shortcuts import render, HttpResponse
from django import forms
from app01.utils.bootstrap import BootStrapForm, BootStrapModelForm
from app01 import models
from django.conf import settings

def upload_list(request):
    if request.method == "GET":
        return render(request, 'upload_list.html')
    # 获取文件对象
    file_object = request.FILES.get("avatar")
    # 根据获取文件名file_object.name
    f = open(file_object.name, mode='wb')
    # 获取文件内容
    for chunk in file_object.chunks():
        f.write(chunk)
    f.close()
    return HttpResponse("....")

class UpForm(BootStrapForm):
    bootstrap_exclude_fields = ['img']

    name = forms.CharField(label="姓名")
    age = forms.IntegerField(label="年龄")
    img = forms.FileField(label="头像")

def upload_form(request):
    title = "Form上传"
    if request.method == "GET":
        form = UpForm()
        return render(request, 'upload_form.html', {"form": form, "title": title})
    # data表单，files文件
    form = UpForm(data=request.POST, files=request.FILES)
    if form.is_valid():
        # print(form.cleaned_data)
        # 读取到内容，处理每个字段的数据
        # 读取图片的内容，写入到文件将中并获取文件夹路径
        image_object = form.cleaned_data.get("img")
        # 路径的分隔符再windows和linux中是不一样的，我们就需要使用os拼接路径
        # 静态static:由于用户访问直接获取的是数据库图片路径，不是真正的图片路径(多了一个app01)，我们就把app01换成http://127.0.0.1:8000/
        # db_file_path = os.path.join("static", "img", image_object.name)  # 数据库存储路径
        # file_path = os.path.join("app01", db_file_path)  # 图片存储路径
        # 动态media,绝对路径:settings.MEDIA_ROOT
        media_path = os.path.join(settings.MEDIA_ROOT, image_object.name)  # 数据库存储路径
        # 动态media,相对路径:"media"
        media_path = os.path.join("media", image_object.name)  # 数据库存储路径
        f = open(media_path, mode='wb')
        for chunk in image_object.chunks():
            f.write(chunk)
        f.close()
        # 将图片路径存储到数据库中
        models.Boss.objects.create(
            name=form.cleaned_data['name'],
            age=form.cleaned_data['age'],
            # 存储img为图片路径
            img=media_path,
        )
        return HttpResponse("...")
    return render(request, 'upload_form.html', {"form": form, "title": title})

class UpModelForm(BootStrapModelForm):
    bootstrap_exclude_fields = ['img']

    class Meta:
        model = models.City
        fields = "__all__"

def upload_modal_form(request):
    """ 上传文件和数据（modelForm）"""
    title = "ModelForm上传文件"
    if request.method == "GET":
        form = UpModelForm()
        return render(request, 'upload_form.html', {"form": form, 'title': title})
    form = UpModelForm(data=request.POST, files=request.FILES)
    if form.is_valid():
        # 对于文件：自动保存(路径再创建的数据库中)
        # 字段 + 上传路径写入到数据库
        form.save()
        return HttpResponse("成功")
    return render(request, 'upload_form.html', {"form": form, 'title': title})


from bs4 import BeautifulSoup as bs
import requests
import selenium
import time
from splinter import Browser
import pandas as pd
import json

#############################
# Initialize selenium
#############################

executable_path = {'executable_path': '/usr/bin/chromedriver'}
browser = Browser('chrome', **executable_path, headless=True)

#############################
# Scrape NASA.gov
#############################

def nasa():
    try:
        NASAurl = 'https://mars.nasa.gov/news'
        browser.visit(NASAurl)

        html = browser.html
        soup = bs(html, 'html.parser')

        newsTitle = soup.find('div', class_='image_and_description_container')\
                        .find('div', class_='list_text')\
                        .find('div', class_='content_title')\
                        .find('a')\
                        .text

        newsP = soup.find('div', class_='image_and_description_container')\
                    .find('div', class_='list_text')\
                    .find('div', class_='article_teaser_body')\
                    .text

        return newsTitle, newsP
    except:
        return None, None

#############################
# Scrape JPL.NASA.gov
#############################

def jpl():
    try:
        JPLurl = 'https://www.jpl.nasa.gov/spaceimages/?search=&category=Mars'

        browser.visit(JPLurl)

        browser.click_link_by_partial_text('FULL IMAGE')

        time.sleep(1)

        html = browser.html
        soup = bs(html, 'html.parser')

        imageLink = soup.find('img', class_='fancybox-image')['src']
        featuredImageURL = 'https://www.jpl.nasa.gov' + imageLink
        return featuredImageURL
    except:
        return None

#############################
# Scrape Twitter
#############################

def twitter():
    try:
        Twitterurl = 'https://twitter.com/marswxreport?lang=en'

        browser.visit(Twitterurl)
        html = browser.html
        soup = bs(html, 'html.parser')

        weatherTweet = soup.find('p', class_='tweet-text').text
        return weatherTweet
    except:
        return None

#############################
# Scrape Space-Facts
#############################

def spacefacts():
    try:
        MarsFactsurl = 'https://space-facts.com/mars'
        tables = pd.read_html(MarsFactsurl)

        #earthcompare = tables[0]
        marsfacts    = tables[1]

        marsfactshtml = marsfacts.to_html()
        return marsfactshtml
    except:
        return None

#############################
# Scrape USGS
#############################

def usgs():
    try:
        USGSurl =\
            'https://astrogeology.usgs.gov/search/' + \
            'results?q=hemisphere+enhanced&c1=target&v1=Mars'

        browser.visit(USGSurl)
        html = browser.html
        soup = bs(html, 'html.parser')

        links = soup.find('div', class_='results').find_all('a')
        image_dict = {}

        lwt = [link for link in links if link.text]

        for link in lwt:
            text = link.text
            url  = 'https://astrogeology.usgs.gov' + link['href']

            browser.visit(url)
            html = browser.html
            soup = bs(html, 'html.parser')

            dl_links = soup.find('div', class_='downloads').find_all('a')

            for dl_link in dl_links:
                if dl_link.text == 'Original':
                    img_link = dl_link['href']
                    image_dict[text] = img_link

        return image_dict
    except:
        return None

def Scrape():
    newsTitle, newsP = nasa()
    featuredImageURL = jpl()
    weatherTweet = twitter()
    marsfactshtml = spacefacts()
    image_dict = usgs()

    scrape_dict = {
        'newsTitle': newsTitle,
        'newsP': newsP,
        'featuredImageURL': featuredImageURL,
        'weatherTweet': weatherTweet,
        'marsfactshtml': marsfactshtml,
        'image_dict': image_dict
    }

    return scrape_dict


import pygame as pg

class Button(pg.sprite.Sprite):

    def __init__(self, x, y, color):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface((30, 30))
        self.image.fill(color)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y


# -*- coding: utf-8 -*-
from unittest.mock import Mock, patch

import pytest

from paas_wl.networking.ingress.constants import AppDomainSource
from paas_wl.networking.ingress.entities.ingress import ingress_kmodel
from paas_wl.networking.ingress.exceptions import DefaultServiceNameRequired, EmptyAppIngressError, ValidCertNotFound
from paas_wl.networking.ingress.managers.domain import (
    CustomDomainIngressMgr,
    IngressDomainFactory,
    SubdomainAppIngressMgr,
    assign_custom_hosts,
)
from paas_wl.networking.ingress.models import AppDomain, AppDomainSharedCert, AutoGenDomain
from paas_wl.resources.base.kres import KNamespace
from paas_wl.resources.kube_res.exceptions import AppEntityNotFound
from paas_wl.resources.utils.basic import get_client_by_app
from tests.utils.app import create_app

pytestmark = [pytest.mark.django_db]

@pytest.mark.auto_create_ns
class TestAssignDomains:
    @pytest.fixture()
    def foo_shared_cert(self, app):
        AppDomainSharedCert.objects.create(
            region=app.region, name="foo", cert_data="", key_data="", auto_match_cns="*.foo.com"
        )

    @pytest.mark.parametrize(
        "domains",
        (
            [AutoGenDomain('foo.com'), AutoGenDomain('bar.com')],
            [AutoGenDomain('foo.com'), AutoGenDomain('www.foo.com')],
            [AutoGenDomain('foo.com'), AutoGenDomain('www.foo.com', https_enabled=True)],
        ),
    )
    def test_brand_new_domains(self, app, foo_shared_cert, domains):
        assign_custom_hosts(app, domains, 'foo-service')

        ingress_mgr = SubdomainAppIngressMgr(app)
        ingress = ingress_mgr.get()

        assert len(ingress.domains) == len(domains)
        assert {d.host for d in domains} == {d.host for d in ingress.domains}

    @pytest.mark.parametrize(
        "hostnames, domains_https_enabled",
        (
            (['www.foo.com', 'bar.com'], [True, False]),
            (['www.foo.com', 'bar.foo.com'], [True, True]),
        ),
    )
    def test_create_https_domains(self, app, foo_shared_cert, hostnames, domains_https_enabled):
        domains = [AutoGenDomain(hostname, https_enabled=True) for hostname in hostnames]
        assign_custom_hosts(app, domains, default_service_name='foo-service')
        domain_count = len(domains)
        ingress = SubdomainAppIngressMgr(app).get()

        assert [d.tls_enabled for d in ingress.domains] == domains_https_enabled
        assert AppDomain.objects.count() == domain_count

    def test_domain_transfer_partially(self, app):
        domains_app1 = [AutoGenDomain('foo.com'), AutoGenDomain('bar.com')]
        assign_custom_hosts(app, domains_app1, 'foo-service')
        app_2 = create_app()
        KNamespace(get_client_by_app(app_2)).get_or_create(app_2.namespace)

        # Transfer "bar.com" to app_2
        domains_app1 = [
            AutoGenDomain('bar.com'),
            AutoGenDomain('app-2.com'),
        ]
        assign_custom_hosts(app_2, domains_app1, 'foo-service')

        ingress = SubdomainAppIngressMgr(app).get()
        assert len(ingress.domains) == 1
        hosts = [d.host for d in ingress.domains]
        assert 'foo.com' in hosts
        assert 'bar.com' not in hosts

        ingress = SubdomainAppIngressMgr(app_2).get()
        assert len(ingress.domains) == 2
        hosts = [d.host for d in ingress.domains]
        assert 'bar.com' in hosts
        assert 'app-2.com' in hosts

    def test_domain_transfer_fully(self, app):
        domains = [AutoGenDomain('foo.com')]
        assign_custom_hosts(app, domains, 'foo-service')

        # Transfer all domains to app_2
        app_2 = create_app()
        KNamespace(get_client_by_app(app_2)).get_or_create(app_2.namespace)
        assign_custom_hosts(app_2, domains, 'foo-service')

        with pytest.raises(AppEntityNotFound):
            SubdomainAppIngressMgr(app).get()

        ingress = SubdomainAppIngressMgr(app_2).get()
        assert len(ingress.domains) == 1
        assert [d.host for d in ingress.domains] == ['foo.com']

@pytest.mark.auto_create_ns
class TestSubdomainAppIngressMgrCommon:
    """Test common interfaces for `SubdomainAppIngressMgr`"""

    @pytest.fixture(autouse=True)
    def _setup_data(self, app):
        AppDomain.objects.create(app=app, region=app.region, host='bar-2.com', source=AppDomainSource.AUTO_GEN)

    def test_sync_no_domains(self, app):
        AppDomain.objects.filter(app=app).delete()
        with pytest.raises(EmptyAppIngressError):
            ingress_mgr = SubdomainAppIngressMgr(app)
            ingress_mgr.sync(default_service_name='foo')

    def test_sync_creation_with_no_default_server_name(self, app):
        ingress_mgr = SubdomainAppIngressMgr(app)
        with pytest.raises(DefaultServiceNameRequired):
            ingress_mgr.sync()

    def test_sync_creation(self, app):
        ingresses = ingress_kmodel.list_by_app(app)
        assert len(ingresses) == 0

        ingress_mgr = SubdomainAppIngressMgr(app)
        ingress_mgr.sync(default_service_name='foo')
        ingresses = ingress_kmodel.list_by_app(app)

        assert len(ingresses) == 1
        ingress = ingresses[0]
        assert ingress.configuration_snippet != ''
        assert len(ingress.domains) > 0

    def test_sync_update(self, app):
        ingress_mgr = SubdomainAppIngressMgr(app)
        ingress_mgr.sync(default_service_name='foo')
        ingress_name = ingress_mgr.ingress_name
        assert len(ingress_kmodel.get(app, ingress_name).domains) == 1

        # Add an extra domain
        config = app.latest_config
        config.domain = 'bar.com'
        config.save()
        ingress_mgr.sync()

        assert len(ingress_kmodel.get(app, ingress_name).domains) == 2

    def test_delete_non_existed(self, app):
        ingress_mgr = SubdomainAppIngressMgr(app)
        ingress_mgr.delete()

    def test_integrated(self, app):
        ingress_mgr = SubdomainAppIngressMgr(app)
        ingress_mgr.sync(default_service_name='foo')
        assert len(ingress_kmodel.list_by_app(app)) == 1

        ingress_mgr.delete()
        assert len(ingress_kmodel.list_by_app(app)) == 0

    def test_update_target(self, app):
        ingress_mgr = SubdomainAppIngressMgr(app)
        ingress_mgr.sync(default_service_name='foo')
        ingress_mgr.update_target('foo-service', 'foo-port')

        ingress = ingress_kmodel.get(app, ingress_mgr.ingress_name)
        assert ingress.service_name == 'foo-service'
        assert ingress.service_port_name == 'foo-port'

    @pytest.mark.parametrize(
        'rewrite_to_root,expected_ret',
        [
            (True, True),
            (False, False),
        ],
    )
    def test_rewrite_ingress_path_to_root(self, rewrite_to_root, expected_ret, app):
        with patch.object(SubdomainAppIngressMgr, 'rewrite_ingress_path_to_root', new=rewrite_to_root):
            SubdomainAppIngressMgr(app).sync(default_service_name='foo')
            assert ingress_kmodel.list_by_app(app)[0].rewrite_to_root is expected_ret

class TestSubdomainAppIngressMgr:
    def test_list_desired_domains(self, app):
        ingress_mgr = SubdomainAppIngressMgr(app)
        domains = ingress_mgr.list_desired_domains()
        assert len(domains) == 0

    def test_list_desired_domains_with_extra(self, app):
        config = app.latest_config
        config.domain = 'bar.com'
        config.save()

        ingress_mgr = SubdomainAppIngressMgr(app)
        assert len(ingress_mgr.list_desired_domains()) == 1

        AppDomain.objects.create(app=app, region=app.region, host='bar-2.com', source=AppDomainSource.AUTO_GEN)
        assert len(ingress_mgr.list_desired_domains()) == 2

    def test_list_desired_domains_with_wrong_source(self, app):
        ingress_mgr = SubdomainAppIngressMgr(app)
        assert len(ingress_mgr.list_desired_domains()) == 0
        # SubDomain ingress should only include domains when their source is "CUSTOM"
        AppDomain.objects.create(app=app, region=app.region, host='foo.com', source=AppDomainSource.INDEPENDENT)
        assert len(ingress_mgr.list_desired_domains()) == 0

class TestCustomDomainIngressMgr:
    @pytest.mark.auto_create_ns
    @pytest.mark.parametrize(
        'path_prefix,expected_path_prefixes,customized_ingress_name',
        [
            ('/', ['/'], False),
            ('/foo/', ['/foo/'], True),
        ],
    )
    def test_create(self, path_prefix, expected_path_prefixes, customized_ingress_name, app):
        domain = AppDomain.objects.create(
            app=app,
            region=app.region,
            host='foo.example.com',
            path_prefix=path_prefix,
            source=AppDomainSource.INDEPENDENT,
        )
        mgr = CustomDomainIngressMgr(domain)

        mgr.sync(default_service_name=app.name)
        obj = ingress_kmodel.get(app, mgr.make_ingress_name())

        if customized_ingress_name:
            assert obj.name == f"custom-foo.example.com-{domain.id}"
        else:
            assert obj.name == "custom-foo.example.com"
        assert obj.domains[0].path_prefix_list == expected_path_prefixes
        assert obj.service_name == app.name

    def test_normal_delete(self, app):
        domain = AppDomain.objects.create(
            app=app, region=app.region, host='foo.example.com', source=AppDomainSource.INDEPENDENT
        )
        mgr = CustomDomainIngressMgr(domain)
        mgr.delete()

        with pytest.raises(AppEntityNotFound):
            ingress_kmodel.get(app, mgr.make_ingress_name())

@pytest.mark.auto_create_ns
class TestIntegratedDomains:
    """Test cases for some combined situations"""

    def test_assign_custom_hosts_affects_no_independent_domains(self, app):
        AppDomain.objects.create(
            app=app, region=app.region, host='foo-independent.com', source=AppDomainSource.INDEPENDENT
        )
        assert AppDomain.objects.filter(host='foo-independent.com').exists()
        assign_custom_hosts(app, [AutoGenDomain('foo.com')], 'foo-service')

        # Calling assign_custom_hosts should not remove AppDomain objects with source other than "CUSTOM"
        assert AppDomain.objects.filter(host='foo-independent.com').exists()

class TestIngressDomainFactory:
    def test_make_ingress_domain_with_http(self):
        factory = IngressDomainFactory()
        host = "example.com"
        domain = factory.create(AppDomain(https_enabled=False, host=host))
        assert domain.host == host
        assert domain.tls_enabled is False
        assert domain.tls_secret_name == ''

    def test_https_cert_not_found(self):
        cert_controller_mocker = Mock(return_value=Mock(get_cert=Mock(return_value=None)))
        factory = IngressDomainFactory(cert_controller_mocker)
        with pytest.raises(ValidCertNotFound):
            factory.create(AppDomain(https_enabled=True, host='example.com'))

    def test_https_cert_not_found_no_exception(self):
        cert_controller_mocker = Mock(return_value=Mock(get_cert=Mock(return_value=None)))
        factory = IngressDomainFactory(cert_controller_mocker)
        domain = factory.create(AppDomain(https_enabled=True, host='example.com'), raise_on_no_cert=False)
        assert domain.tls_enabled is False

    def test_https_cert_created(self):
        cert_controller_mocker = Mock(
            return_value=Mock(
                get_cert=Mock(return_value=object()),
                update_or_create_secret_by_cert=Mock(return_value=("test", True)),
            )
        )
        factory = IngressDomainFactory(cert_controller_mocker)
        host = "example.com"

        domain = factory.create(AppDomain(https_enabled=True, host=host))
        assert domain.host == host
        assert domain.tls_enabled is True
        assert domain.tls_secret_name == 'test'


# D - Cylinder
# https://atcoder.jp/contests/abc247/tasks/abc247_d
# ランレングス符号化

from collections import deque

que = deque()
Q = int(input())
for i in range(Q):
    query = list(map(int, input().split()))
    if query[0] == 1:
        que.append(query[1])
        que.append(query[2])
    else:
        ans = 0
        val = que.popleft()
        num = que.popleft()

        while query[1] != 0:
            if num > query[1]:
                num -= query[1]
                ans += val * query[1]
                query[1] = 0
                que.appendleft(num)
                que.appendleft(val)
            elif num == query[1]:
                ans += val * num
                query[1] = 0
            else:
                ans += val * num
                query[1] -= num
                val = que.popleft()
                num = que.popleft()
        print(ans)


import sys
sys.path.append(".")
from torch.utils.tensorboard import SummaryWriter
import os
import torch
import argparse
import numpy as np
import pandas as pd
from model import Model
from data.data import CellCropsDataset
from data.utils import load_crops
from data.transform import train_transform, val_transform
from torch.utils.data import DataLoader, WeightedRandomSampler
import json
from sklearn.model_selection import StratifiedKFold
torch.multiprocessing.set_sharing_strategy('file_system')

def train_epoch(model, dataloader, optimizer, criterion, epoch, writer, device=None):
    model.train()
    cells = []
    for i, batch in enumerate(dataloader):
        x = batch['image']
        m = batch.get('mask', None)
        if m is not None:
            x = torch.cat([x, m], dim=1)
        x = x.to(device=device)

        y = batch['label'].to(device=device)
        optimizer.zero_grad()
        y_pred = model(x)
        loss = criterion(y_pred, y)
        if i % 1 == 0:
            print(f"train epoch {epoch} | iterate {i} / {len(dataloader)} | {loss.item()}                         ", end='\r')
        writer.add_scalar('Loss/train', loss.item(), epoch * len(dataloader) + i)
        loss.backward()
        optimizer.step()
    return cells
def valid_epoch(model, dataloader, criterion, epoch, writer, device=None):
    total_loss = 0
    model.eval()
    with torch.no_grad():
        for i, batch in enumerate(dataloader):
            x = batch['image']
            m = batch.get('mask', None)
            if m is not None:
                x = torch.cat([x, m], dim=1)
            x = x.to(device=device)

            y = batch['label'].to(device=device)
            y_pred = model(x)
            loss = criterion(y_pred, y)
            total_loss += loss.item()
            if i % 1 == 0:
                print(f"valid epoch {epoch} | iterate {i} / {len(dataloader)} | {loss.item()}                         ", end='\r')
            writer.add_scalar('Loss/valid', loss.item(), epoch * len(dataloader) + i)
        total_loss = total_loss/i
    return total_loss

def val_epoch(model, dataloader, device=None):
    with torch.no_grad():
        model.eval()
        pred_labels = []
        pred_probs = []
        results = {'cell_id': [], 'image_id': [], 'gt_labels': [], 'pred_labels': [], 'pred_probs': []}
        for i, batch in enumerate(dataloader):
            x = batch['image']
            m = batch.get('mask', None)
            if m is not None:
                x = torch.cat([x, m], dim=1)
            x = x.to(device=device)
            # m = m.to(device=device)
            y_pred = model(x)

            pred_probs += y_pred.detach().cpu().numpy().tolist()
            pred_labels += y_pred.detach().cpu().numpy().argmax(1).tolist()

            results['cell_id'].extend(batch['cell_id'].detach().cpu().numpy().tolist())
            results['image_id'].extend(batch['image_id'])
            results['gt_labels'].extend(batch['label'].detach().cpu().numpy().tolist())
            results['pred_labels'].extend(np.argmax(y_pred.detach().cpu().numpy(), axis=1).tolist())
            results['pred_probs'].extend(y_pred.detach().cpu().numpy().tolist())

            print(f"Eval {i} / {len(dataloader)}        ", end='\r')
        return np.array(pred_labels), np.array(pred_probs), pd.DataFrame.from_dict(results)

def results_reformatting(result_dir, fold_id):
    class_df = pd.read_csv(os.path.join(result_dir, 'class_names.csv'))
    class_names = {id: name for id, name in enumerate(class_df['class_name'].tolist())}
    col_names = ["%s_prob" % class_names[key] for key in class_names.keys()]
    class_names = [class_names[key] for key in class_names.keys()]

    res = pd.read_csv(os.path.join(result_dir, fold_id, 'test_results.csv'))

    gt_labels = res['gt_labels'].tolist()
    pred_labels = res['pred_labels'].tolist()
    probs = res['pred_probs'].to_numpy()
    prob_matrix = np.zeros((probs.shape[0], len(class_names)))
    for i in range(probs.shape[0]):
        class_prob = np.array([np.float64(val) for val in probs[i][1:-1].split(',')])
        prob_matrix[i, :] += class_prob

    df = pd.DataFrame(prob_matrix, columns=col_names)
    df['pred_label'] = pred_labels
    df['gt_label'] = gt_labels
    os.makedirs(os.path.join(result_dir, fold_id), exist_ok=True)
    df.to_csv(os.path.join(result_dir, fold_id, 'results_test.csv'), index=False)

def subsample_const_size(crops, size):
    """
    sample same number of cell from each class
    """
    final_crops = []
    crops = np.array(crops)
    labels = np.array([c._label for c in crops])
    for lbl in np.unique(labels):
        indices = np.argwhere(labels == lbl).flatten()
        if (labels == lbl).sum() < size:
            chosen_indices = indices
        else:
            chosen_indices = np.random.choice(indices, size, replace=False)
        final_crops += crops[chosen_indices].tolist()
    return final_crops

def define_sampler(crops, hierarchy_match=None):
    """
    Sampler that sample from each cell category equally
    The hierarchy_match defines the cell category for each class.
    if None then each class will be category of it's own.
    """
    labels = np.array([c._label for c in crops])
    if hierarchy_match is not None:
        labels = np.array([hierarchy_match[str(l)] for l in labels])

    unique_labels = np.unique(labels)
    class_sample_count = {t: len(np.where(labels == t)[0]) for t in unique_labels}
    weight = {k: sum(class_sample_count.values()) / v for k, v in class_sample_count.items()}
    samples_weight = np.array([weight[t] for t in labels])
    samples_weight = torch.from_numpy(samples_weight)
    return WeightedRandomSampler(samples_weight.double(), len(samples_weight))

# CUDA_VISIBLE_DEVICES=1 python cHL_CODEX_training_validation_testing.py --fold_id fold_1
if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Arguments')
    parser.add_argument('--base_path', type=str, default='datasets/cHL_CODEX/', help='configuration_path')
    parser.add_argument('--result_path', type=str, default='results/cHL_CODEX/', help='configuration_path')
    parser.add_argument('--fold_id', type=str, default='fold_0', help='fold id to train model')
    args = parser.parse_args()

    os.makedirs(os.path.join(args.result_path, args.fold_id), exist_ok=True)
    writer = SummaryWriter(log_dir=os.path.join(args.result_path, 'logs', args.fold_id))
    config_path = os.path.join(args.base_path, "config.json")
    with open(config_path) as f:
        config = json.load(f)
    criterion = torch.nn.CrossEntropyLoss()
    train_crops, val_crops = load_crops(config["root_dir"],
                                        config["channels_path"],
                                        config["crop_size"],
                                        config["train_set"],
                                        config["val_set"],
                                        config["to_pad"],
                                        blacklist_channels=config["blacklist"])

    train_crops = np.array([c for c in train_crops if c._label >= 0])
    val_crops = np.array([c for c in val_crops if c._label >= 0])

    # creating data folds during run time
    labels = np.array([c._label for c in train_crops if c._label >= 0])
    skf_train_test = StratifiedKFold(n_splits=5, random_state=7325111, shuffle=True)
    for i, (train_index, test_index) in enumerate(skf_train_test.split(labels, labels)):
        if ("fold_%d" % i) == args.fold_id:
            print(f"Fold {i}, {len(train_index)}, {len(test_index)}:")
            test_crops = train_crops[test_index]
            train_crops = train_crops[train_index]
            labels = np.array([c._label for c in train_crops])
            skf_train_valid = StratifiedKFold(n_splits=5, random_state=7325111, shuffle=True)
            for j, (train_index, valid_index) in enumerate(skf_train_valid.split(labels, labels)):
                    print(f"Fold {j}, {len(train_index)}, {len(test_index)}:")
                    val_crops = train_crops[valid_index]
                    train_crops = train_crops[train_index]
                    break
            break

    sampler = define_sampler(train_crops)
    shift = 5
    crop_input_size = config["crop_input_size"] if "crop_input_size" in config else 100
    aug = config["aug"] if "aug" in config else True
    training_transform = train_transform(crop_input_size, shift) if aug else val_transform(crop_input_size)
    train_dataset = CellCropsDataset(train_crops, transform=training_transform, mask=True)
    val_dataset = CellCropsDataset(val_crops, transform=val_transform(crop_input_size), mask=True)
    test_dataset = CellCropsDataset(test_crops, transform=val_transform(crop_input_size), mask=True)
    train_dataset_for_eval = CellCropsDataset(train_crops, transform=val_transform(crop_input_size), mask=True)
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    num_channels = sum(1 for line in open(config["channels_path"])) + 1 - len(config["blacklist"])
    class_num = config["num_classes"]

    model = Model(num_channels + 1, class_num)

    model = model.to(device=device)
    optimizer = torch.optim.Adam(model.parameters(), lr=config["lr"])
    scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.85)

    train_loader = DataLoader(train_dataset, batch_size=128, num_workers=12, sampler=sampler, shuffle=False)
    val_loader = DataLoader(val_dataset, batch_size=128, num_workers=12, shuffle=False)
    test_loader = DataLoader(test_dataset, batch_size=128, num_workers=12, shuffle=False)
    print(len(train_loader), len(val_loader))
    min_loss = np.Inf
    best_epoch_id = -1
    patient = 0
    for i in range(config["epoch_max"]):
        train_epoch(model, train_loader, optimizer, criterion, device=device, epoch=i, writer=writer)
        total_loss = valid_epoch(model, val_loader, criterion, device=device, epoch=i, writer=writer)
        print(f"Epoch {i} done with valid loss: {total_loss}!")
        patient += 1

        if total_loss < min_loss:
            patient = 0
            min_loss = total_loss
            best_epoch_id = i
            print(f"Saving new best model at epoch {i} with valid loss: {total_loss}!")
            torch.save(model.state_dict(), os.path.join(args.result_path, args.fold_id, "weights.pth"))
            pred_labels, pred_probs, results_df = val_epoch(model, test_loader, device=device)
            results_df.to_csv(os.path.join(args.result_path, args.fold_id, "test_results.csv"), index=False)
            results_reformatting(args.result_path, args.fold_id)

        if i > 50 and patient >= 20:
            print('Loss has not decreased in last 20 epochs. Therefore, terminating training process.')
            break


# encoding:utf-8
from flask import Flask,request
import json
from threading import Thread
import threading
import time
import sys
import sqlite3
import os

app=Flask(__name__)
####回复文本格式##########
re={}
result={}
result["type"]="text"
result["content"]=""
re["error_code"]=0
re["error_msg"]=""
re["result"]=result
dic={'温度':'temperature','湿度':'humidity','光照':'light','二氧化碳':'co2_simulation','声音':'noise'}
##########意图对应的语音回复文本字典############
response={'AC1_OC_OPEN':'请稍等，正在为您打开空调',
'AC1_OC_CLOSE':'请稍等，正在为您关闭空调',
'AC1_TEMP_UP':'正在帮您升高空调温度，请稍等',
'AC1_TEMP_DOWN':'正在帮您降低空调温度，请稍等',
'AC1_WSPEED_UP':'正在帮您提高空调风速，请稍等',
'AC1_WSPEED_DOWN':'正在帮您降低空调风速，请稍等',
'AC1_SLEEP_OPEN':'好的，正在为您打开睡眠模式，请稍等',
'AC1_SLEEP_CLOSE':'好的，正在为您关闭睡眠模式，请稍等',
'AC1_TIMER_CLOSE':'好的，正在为您取消空调定时，请稍等'}
##############词槽标准化字典#############
normal={'高':'0','中':'1','低':'2','制冷':'0','制热':'1','送风':'2','自动':'3','除湿':'4','关':'close','开':'open','平衡':'0','环保':'1','极致':'2',
'16度':'16','17度':'17','18度':'18','19度':'19','20度':'20','21度':'21','22度':'22','23度':'23','24度':'24','25度':'25',
'26度':'26','27度':'27','28度':'28','29度':'29','30度':'30','降低':'lower','热':'lower','升高':'higher','冷':'higher',
'半小时':'0.5','一小时':'1.0','一个半小时':'1.5','两个小时':'2.0','两个半小时':'2.5','三个小时':'3.0','温度':'0','湿度':'1','声音':'2','光照':'3','二氧化碳':'4'}
class Response:
	def __init__(self,intent,nom_word):
		self.re=re
		self.intent=intent
		self.nom_word=nom_word
	def json_resp(self,intent,nom_word):
		if intent in response.keys():
			re["result"]["content"]=response[intent]
		elif intent=="AC1_TEMP_TO":
			re["result"]["content"]="好的，正在为您将空调设置为"+nom_word+"，请稍等"
		elif intent=="AC1_WSPEED_TO":
			re["result"]["content"]="好的，正在为您调节风速为"+nom_word+"，请稍等"
		elif intent=="AC1_TIMER_SET":
			if nom_word=="开"or nom_word=="":
				re["result"]["content"]="好的，正在为您设置空调定时，定时时间为默认值半小时"
			else:
				re["result"]["content"]="好的，正在为您设置空调定时，定时时间为"+nom_word
		elif intent=="AC1_COMMOD_SELECT"or intent=="AC1_SMARTMOD_SELECT":
			re["result"]["content"]="好的，正在为您调节到"+nom_word+"模式，请稍等"
		elif intent=="ROOM1_ENV_INFO_QUERY":
			conn = sqlite3.connect("db.sqlite3")
			c = conn.cursor()
			c.execute('SELECT '+dic[nom_word]+' FROM myhome_nodedata ORDER BY id desc')#选择查询信息的最新值
			query_result=c.fetchone()[0]					#取出查询项对应数据
			re["result"]["content"]="您当前的室内"+nom_word+"为"+str(query_result)
		else:
			re["result"]["content"]="请求失败，请重试"
		return re

@app.route("/unit/callback",methods=['POST'])
def callback():
	#print(request.headers)
	#print(request.data)
	dic=json.loads(str(request.data,encoding='utf-8'))
	intent=dic["response"]["schema"]["intent"]
	nom_word=dic["response"]["schema"]["slots"][0]["normalized_word"]
	exp1=Response(intent,nom_word)

	if os.path.exists("db.sqlite3"):
		conn = sqlite3.connect("db.sqlite3")
		c = conn.cursor()
	else:
		conn = sqlite3.connect("db.sqlite3")
		c = conn.cursor()
		c.execute('''CREATE TABLE myhome_commands(ID integer NOT NULL PRIMARY KEY AUTOINCREMENT,INTENT text NOT NULL ,SLOTS text NOT NULL)''')#若命令表单不存在则创建表单
		c.execute('INSERT INTO myhome_commands VALUES(1,"0","0")')				#插入意图和归一化词槽
	c.execute("UPDATE myhome_commands SET INTENT=?,SLOTS=? where ID=1",(intent,normal[nom_word]))
	conn.commit()
	conn.close()
	json_re=exp1.json_resp(intent,nom_word)#获得答复数据
	json_re=json.dumps(re)
	#print(json_re)
	return json_re

if __name__=='__main__':
	app.run(host='172.20.10.12',port=9999,debug=True)


from torch import nn
import torch

import numpy as np

class SIREN(nn.Module):

    def __init__(self, in_features, hidden_features, hidden_layers, first_omega_0, hidden_omega_0):
        super().__init__()

        self.net = []

        self.net.append(
            SineLayerLinear(
                in_features=in_features,
                out_features=hidden_features,
                is_first=True,
                omega_0=first_omega_0,
            )
        )

        for i in range(hidden_layers):
            self.net.append(
                SineLayerLinear(
                    in_features=hidden_features, out_features=hidden_features, is_first=False,
                    omega_0=hidden_omega_0
                )
            )

        self.net = nn.Sequential(*self.net)

    def forward(self, x):
        """ Propagate the coordinates through SIREN.
        """
        x = self.net(x)
        return x

class SineLayerBase(nn.Module):

    def __init__(self, in_features, out_features, bias, is_first, omega_0):
        super().__init__()

        self.omega_0 = omega_0
        self.is_first = is_first

        self.in_features = in_features
        self.out_features = out_features

        self.bias = bias
        self.is_first = is_first

    def init_weights(self):
        with torch.no_grad():
            if self.is_first:
                self.linear.weight.uniform_(-1 / self.in_features, 1 / self.in_features)
            else:
                self.linear.weight.uniform_(-np.sqrt(6 / self.in_features) / self.omega_0,
                                            np.sqrt(6 / self.in_features) / self.omega_0)
                # Important! Bias is not defined in original SIREN implementation
                if self.linear.bias is not None:
                    # self.linear.bias.data.uniform_(-1.0, 1.0)
                    self.linear.bias.data.fill_(0)

    def forward(self, x):
        return torch.sin(self.omega_0 * self.linear(x))

class SineLayerLinear(SineLayerBase):

    def __init__(self, in_features, omega_0, out_features, bias=True, is_first=False):
        super(SineLayerLinear, self).__init__(
            in_features=in_features,
            out_features=out_features,
            bias=bias,
            is_first=is_first,
            omega_0=omega_0
        )

        self.linear = nn.Linear(in_features, out_features, bias=bias)
        self.init_weights()


from django.test import TestCase
from django.urls import reverse
from final_exam_project.rent_a_car_web.models import Car

class CarsPageViewTest(TestCase):
    def test_cars_page_view(self):
        self.car1 = Car.objects.create(make='Toyota', car_model='Corolla', horsepower=200, image='toyota.jpg', price=50)
        self.car2 = Car.objects.create(make='Honda', car_model='Civic', horsepower=180, image='honda.jpg', price=45)

        response = self.client.get(reverse('catalogue_page'))

        self.assertEqual(response.status_code, 200)

        self.assertTemplateUsed(response, 'catalogue_page.html')

        self.assertIn('cars', response.context)

        cars_in_context = response.context['cars']

        self.assertQuerysetEqual(cars_in_context, Car.objects.all(), ordered=False)


from dotenv import load_dotenv
import datetime as dt
import os
import telebot
import json

load_dotenv()
BOT_TOKEN = os.environ.get('BOT_TOKEN')
bot = telebot.TeleBot(BOT_TOKEN)

COMMANDS = [
    {
        "name": 'start',
        "description": 'Restart the bot'
    },
    {
        "name": 'predict',
        "description": 'Get prediction for today'
    },
    {
        "name": 'day_prediction',
        "description": 'Get prediction for selected day'
    }
]

bot.set_my_commands(
    commands=[telebot.types.BotCommand(
        command["name"], command["description"]) for command in COMMANDS]
)

with open('probability_week.json', 'r') as prob_file:
    prob_data = json.load(prob_file)

weekdays = ['Monday', 'Tuesday', 'Wednesday',
            'Thursday', 'Friday', 'Saturday', 'Sunday']

@bot.message_handler(commands=[command["name"] for command in COMMANDS])
def exchange_command(message):
    if (message.text == '/start'):
        bot.send_message(
            message.chat.id, 'Glory to UkraineðŸ‡ºðŸ‡¦! I can predict air raid alerts in Kyiv for you!ðŸ¥°')

        commands_str = ''
        for command in COMMANDS:
            if (command["name"] == "start"):
                continue
            commands_str += f'/{command["name"]} - {command["description"]}\n'

        bot.send_message(
            message.chat.id,
            f'Here are the list of commands:\n{commands_str}',
            parse_mode='HTML')

    elif (message.text == '/predict'):
        curr_weekday = dt.datetime.now().weekday()

        keyboard = telebot.types.InlineKeyboardMarkup()
        keyboard.row(
            telebot.types.InlineKeyboardButton(
                'Show for hours', callback_data=f'hour_day-{curr_weekday}')
        )

        day = weekdays[curr_weekday]
        day_prob = "{:.2f}".format(
            round(prob_data[curr_weekday]["day_prob"] * 100, 2))

        bot.send_message(message.chat.id,
                         f'Alert probability for {day}: {day_prob}%',
                         reply_markup=keyboard, parse_mode='HTML')

    elif (message.text == '/day_prediction'):
        keyboard = telebot.types.InlineKeyboardMarkup()

        for weekday in weekdays:
            keyboard.row(
                telebot.types.InlineKeyboardButton(
                    weekday, callback_data=f'day-{weekdays.index(weekday)}')
            )

        bot.send_message(message.chat.id, 'Select a day:',
                         reply_markup=keyboard)

@bot.callback_query_handler(func=lambda call: True)
def iq_callback(query):
    keyboard = telebot.types.InlineKeyboardMarkup()
    data = query.data
    if (data.startswith('day-')):
        day_id = int(data[-1])
        day = weekdays[day_id]
        day_prob = "{:.2f}".format(
            round(prob_data[day_id]["day_prob"] * 100, 2))

        keyboard.row(
            telebot.types.InlineKeyboardButton(
                'Show for hours', callback_data=f'hour_day-{day_id}')
        )

        bot.send_message(query.message.chat.id, f'Alert probability for {day}: {day_prob}%',
                         reply_markup=keyboard, parse_mode='HTML')

    elif (data.startswith('hour_day-')):
        day_id = int(data[-1])
        day = weekdays[day_id]

        bot.send_message(query.message.chat.id,
                         f'Alert probability for {day} hours: ')

        str_hours = ''
        cnt = 0
        for hour_prob in prob_data[day_id]["hours_prob"]:
            if (hour_prob == 0):
                cnt += 1
                continue
            hour_string = '{:02d}:00'.format(cnt)
            hour_prob_string = "{:.2f}".format(round(hour_prob * 100, 2))
            str_hours += hour_string + \
                f': {hour_prob_string}%\n'
            cnt += 1
        bot.send_message(query.message.chat.id,
                         str_hours, parse_mode='HTML')

bot.infinity_polling()


# ---
# jupyter:
#   jupytext:
#     formats: ipynb,py:light
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.7.1
#   kernelspec:
#     display_name: Vigilance
#     language: python
#     name: vigilance
# ---

# # Laplacian Eigenmaps
#
# This notebook is desighned to observe and understand further the plots generated by the sklearn.manifold.SpectralEmbedding function. We do so by displaying two plots, one using the Euclidean metric and one using the distance correlation to compute the affinity matrix. We also provide selector widgets to choose a different eigen solver algorithum and n value for nearest neighbor calculation.
#
# Isabel Fernandez 3/1/2021

import os
import os.path as osp
import pandas as pd
import numpy as np
from sklearn.manifold  import SpectralEmbedding
from sklearn.neighbors import kneighbors_graph
import scipy
from scipy.spatial.distance import correlation as dis_corr
from sklearn.metrics import pairwise_distances
from scipy.sparse import save_npz, load_npz
from sklearn.datasets import load_digits
import holoviews as hv
from holoviews.operation.datashader import rasterize
import panel as pn
import plotly.express as px
from holoviews import dim, opts
hv.extension('bokeh')
pn.extension('plotly')

# +
n_cpus = 26 # Number of cpus

PRJDIR = '/data/SFIMJGC/PRJ_Manifold_Learning' # Project directory path

port_tunnel = int(os.environ['PORT2']) # Get port tunnel for gui display
print('++ INFO: Second Port available: %d' % port_tunnel)
# -

# ***
# ## Load Digits Data

# Load number data and print dimensions
data_df, num_df = load_digits(return_X_y=True,as_frame=True)
print('++ INFO: Data frame dimension ',data_df.shape)

# Make copy of original data
data_df_orig = data_df.copy()
num_df_orig  = num_df.copy()

# Sort data by number in ascending order
data_df['Number'] = num_df_orig
data_df = data_df.sort_values(by=['Number']).reset_index(drop=True)
num_df  = pd.DataFrame(data_df['Number'])
data_df = data_df.drop(['Number'], axis=1)

# +
# Segment data by number and only use 1, 3, 7, and 8
data_df['Number'] = num_df_orig

ones   = data_df[data_df['Number'] == 1][0:25]
threes = data_df[data_df['Number'] == 3][0:100]
sevens = data_df[data_df['Number'] == 7][0:160]
eights = data_df[data_df['Number'] == 8][0:55]
data_df = pd.concat([ones, threes, sevens, eights]).reset_index(drop=True)

num_df  = pd.DataFrame(data_df['Number'])
data_df = data_df.drop(['Number'], axis=1)

# +
# Small number of data points
data_df['Number'] = num_df_orig

twos  = data_df[data_df['Number'] == 2][0:15]
fives = data_df[data_df['Number'] == 5][0:22]
nines = data_df[data_df['Number'] == 9][0:7]
data_df = pd.concat([twos, fives, nines]).reset_index(drop=True)

num_df  = pd.DataFrame(data_df['Number'])
data_df = data_df.drop(['Number'], axis=1)
# -

# ***
# ## Save Affinity Matrix with Distance Correlation Metric
#
# These cells compute the affinity matrix using the scipy distance correlation metric for several n values (for computing nearest neighbor) and saves the matricies as npz files in a directory called "Affinity_Matrix" within the directory this notebook is located.
#
# Note: Thses cells do not need to be executed every time you wish to run this notbook. If the files already exist then you can skip these cells.

# Load affinity matrix for each n value using distance correlation
data_affinity_3   = kneighbors_graph(data_df, n_neighbors=3, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=3')
data_affinity_4   = kneighbors_graph(data_df, n_neighbors=4, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=4')
data_affinity_5   = kneighbors_graph(data_df, n_neighbors=5, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=5')
data_affinity_6   = kneighbors_graph(data_df, n_neighbors=6, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=6')
data_affinity_7   = kneighbors_graph(data_df, n_neighbors=7, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=7')
data_affinity_8   = kneighbors_graph(data_df, n_neighbors=8, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=8')
data_affinity_9   = kneighbors_graph(data_df, n_neighbors=9, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=9')
data_affinity_10  = kneighbors_graph(data_df, n_neighbors=10, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=10')
data_affinity_12  = kneighbors_graph(data_df, n_neighbors=12, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=12')
data_affinity_14  = kneighbors_graph(data_df, n_neighbors=14, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=14')
data_affinity_16  = kneighbors_graph(data_df, n_neighbors=16, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=16')
data_affinity_18  = kneighbors_graph(data_df, n_neighbors=18, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=18')
data_affinity_20  = kneighbors_graph(data_df, n_neighbors=20, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=20')
data_affinity_25  = kneighbors_graph(data_df, n_neighbors=25, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=25')
data_affinity_30  = kneighbors_graph(data_df, n_neighbors=30, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=30')
data_affinity_35  = kneighbors_graph(data_df, n_neighbors=35, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=35')
data_affinity_40  = kneighbors_graph(data_df, n_neighbors=40, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=40')
data_affinity_45  = kneighbors_graph(data_df, n_neighbors=45, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=45')
data_affinity_50  = kneighbors_graph(data_df, n_neighbors=50, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=50')
data_affinity_60  = kneighbors_graph(data_df, n_neighbors=60, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=60')
data_affinity_70  = kneighbors_graph(data_df, n_neighbors=70, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=70')
data_affinity_80  = kneighbors_graph(data_df, n_neighbors=80, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=80')
data_affinity_90  = kneighbors_graph(data_df, n_neighbors=90, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=90')
data_affinity_100 = kneighbors_graph(data_df, n_neighbors=100, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=100')
data_affinity_150 = kneighbors_graph(data_df, n_neighbors=150, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=150')
data_affinity_200 = kneighbors_graph(data_df, n_neighbors=200, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=200')
data_affinity_250 = kneighbors_graph(data_df, n_neighbors=250, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=250')
data_affinity_300 = kneighbors_graph(data_df, n_neighbors=300, mode='connectivity', n_jobs=n_cpus, include_self=True, metric=dis_corr)
print('++ INFO: Finished affinity matrix for n=300')

# +
os.system('if [ ! -d '+PRJDIR+'/Data/LE_Affinity_Matrix ]; then mkdir '+PRJDIR+'/Data/LE_Affinity_Matrix; fi') # Creates directory for affninity matrices if doesnt already exist

# Dictionary of affinity matrices created above
affinity_dict = {3:data_affinity_3, 4:data_affinity_4, 5: data_affinity_5, 6:data_affinity_6, 7:data_affinity_7, 8:data_affinity_8, 9:data_affinity_9,
                 10:data_affinity_10, 12:data_affinity_12, 14:data_affinity_14, 16:data_affinity_16, 18:data_affinity_18, 20:data_affinity_20, 25:data_affinity_25,
                 30:data_affinity_30, 35:data_affinity_35, 40:data_affinity_40, 45:data_affinity_45, 50:data_affinity_50, 60:data_affinity_60, 70:data_affinity_70,
                 80:data_affinity_80, 90:data_affinity_90, 100:data_affinity_100, 150:data_affinity_150, 200:data_affinity_200, 250:data_affinity_250,
                 300:data_affinity_300}

# Save affinity matricies to Affinity_Matrix directory
for n in affinity_dict.keys():
    affin = affinity_dict[n]
    path = osp.join(PRJDIR,'Data','LE_Affinity_Matrix','affinity_matrix_'+str(n)+'.dist_corr.ratio_data.npz')
    save_npz(path, affin)
# -

# ***
# ## Create Widgets

n_list = [3,4,5,6,7,8,9,10,12,14,16,18,20,25,30,35,40]#,45,50,60,70,80,90,100,150,200,250,300] # All n values computed
eigen_sel = pn.widgets.Select(name='Select Eigen Solver', options=['arpack','lobpcg','amg'], value='arpack', width=200) # Select eigen value solver
n_sel     = pn.widgets.Select(name='Select k Value', options=n_list, value=n_list[7], width=200) # Select n value for nearest neighbor

# ***
# ## Plotting Functions

# Returns embedding plot for Euclidean metric
@pn.depends(eigen_sel.param.value,n_sel.param.value)
def plot_embedding1(eigen_solver,n):
    n = int(n) # n value for nearest neighbor

    # 3D embedding transform created using default Euclidean metric
    embedding = SpectralEmbedding(n_components=3, affinity='nearest_neighbors', n_jobs=n_cpus, eigen_solver=eigen_solver, n_neighbors=n)
    data_transformed = embedding.fit_transform(data_df) # Transform data using embedding

    plot_input = pd.DataFrame(data_transformed,columns=['x','y','z']) # Change data to pandas data frame
    plot_input['Number'] = num_df.astype(str) # Add column of number identifier with elements as type string

    # Created 3D scatter plot of embedded data and color by number
    plot = px.scatter_3d(plot_input, x='x', y='y', z='z', color='Number', width=700, height=600, opacity=0.7, title='Euclidean Metric k='+str(n))
    plot = plot.update_traces(marker=dict(size=5,line=dict(width=0)), hovertemplate=["idx: "+str(x) for x in plot_input.index])

    return plot

# Returns embedding plot for distance correlation metric
@pn.depends(eigen_sel.param.value,n_sel.param.value)
def plot_embedding2(eigen_solver,n):
    n = int(n) # n value for nearest neighbor

    # 3D embedding transform created using distance correlation metric
    embedding = SpectralEmbedding(n_components=3, affinity='precomputed', n_jobs=n_cpus, eigen_solver=eigen_solver)

    path = osp.join(PRJDIR,'Data','LE_Affinity_Matrix','affinity_matrix_'+str(n)+'.dist_corr.ratio_data.npz') # Path to precomputed affinity matrix using distance correlation
    data_affinity = load_npz(path) # Load affinity matrix

    #data_affinity = scipy.sparse.csr_matrix.toarray(data_affinity)
    #data_affinity = np.where(data_affinity==0.5, 0, data_affinity) # TEST 1
    #data_affinity = data_affinity - np.identity(data_affinity.shape[0]) # TEST 2

    data_affinity = 0.5 * (data_affinity + data_affinity.T) # Make affinity matrix symetric by finding the average
    data_transformed = embedding.fit_transform(data_affinity) # Transform data using embedding

    plot_input = pd.DataFrame(data_transformed,columns=['x','y','z']) # Change data to pandas data frame
    plot_input['Number'] = num_df.astype(str) # Add column of number identifier with elements as type string

    # Created 3D scatter plot of embedded data and color by number
    plot = px.scatter_3d(plot_input, x='x', y='y', z='z', color='Number', width=600, height=550, opacity=0.7, title='Distance Correlation Metric k='+str(n))
    plot = plot.update_traces(marker=dict(size=5,line=dict(width=0)), hovertemplate=["t: {}".format(x) for x in  plot_input.index])

    return plot

# Retruns plot of affinity matrix for Euclidean metric
@pn.depends(eigen_sel.param.value,n_sel.param.value)
def affinity_matrix1(eigen_solver,n):
    n = int(n) # n value for nearest neighbor

    # 3D embedding transform created using default Euclidean metric
    embedding = SpectralEmbedding(n_components=3, affinity='nearest_neighbors', n_jobs=n_cpus, eigen_solver=eigen_solver, n_neighbors=n)
    data_transformed = embedding.fit_transform(data_df) # Transform data using embedding

    data_affinity = scipy.sparse.csr_matrix.toarray(embedding.affinity_matrix_) # Affinity matrix as a numpy array

    plot = hv.Image(data_affinity).opts(width=500, height=400, colorbar=True, cmap='Greys', title='Euclidean Affinity k='+str(n)) # Plot aray as image

    return plot

# Retruns plot of affinity matrix for distance correlation metric
@pn.depends(eigen_sel.param.value,n_sel.param.value)
def affinity_matrix2(eigen_solver,n):
    n = int(n) # n value for nearest neighbor

    # 3D embedding transform created using default Euclidean metric
    embedding = SpectralEmbedding(n_components=3, affinity='precomputed', n_jobs=n_cpus, eigen_solver=eigen_solver)

    path = osp.join(PRJDIR,'Data','LE_Affinity_Matrix','affinity_matrix_'+str(n)+'.dist_corr.ratio_data.npz') # Path to precomputed affinity matrix using distance correlation
    data_affinity = load_npz(path) # Load affinity matrix
    data_affinity = 0.5 * (data_affinity + data_affinity.T) # Make affinity matrix symetric by finding the average

    data_affinity = scipy.sparse.csr_matrix.toarray(data_affinity) # Affinity matrix as a numpy array

    #data_affinity = np.where(data_affinity==0.5, 0, data_affinity) # TEST 1
    #data_affinity = data_affinity - np.identity(data_affinity.shape[0]) # TEST 2

    plot = hv.Image(data_affinity).opts(width=500, height=400, colorbar=True, cmap='Greys', title='Distance Correlation Affinity k='+str(n)) # Plot aray as image

    return plot

# ***
# ## Dash Board Display

dash = pn.Column(pn.Row(eigen_sel,n_sel),pn.Row(plot_embedding1, plot_embedding2),pn.Row(affinity_matrix1, affinity_matrix2)) # Create embedding dash board

dash_server = dash.show(port=port_tunnel, open=False) # Run dashboard and create link

dash_server.stop() # Stop dashboard link

# ***
# ## Display Number as Image
# Each diget coresponds to 64 pixels, giving you an 8x8 picture. Each pixel value ranges from 0-16.

# +
idx = 8 # Index value for the number you wish to display (index determined by 'data_df')
dig = pd.Series(data_df.loc[idx]).array # Turn pixel values for that diget into an array

dig_df = pd.DataFrame() # Emptly data frame for diget image

# Append every 8 pixels into 'dig_df' as a column
x=0
for row in [1,2,3,4,5,6,7,8]:
    dig_df[row] = dig[x:x+7]
    x=x+8

# Display dig_df as an image to display diget
hv.Image(dig_df.to_numpy().T).opts(cmap='Greys')
# -

# ***
# ## Affinity Matrix Analysis
# These scripts are desighned to demonstrate how the affinity matrix for the Laplacian Eigenmap is computed. To show this we use a simple example of 6 2D points and find the nearest neighbor affnitnity matrix with an n value of 2. In this example we use Sci-kit Learns function's sklearn.neighbors.NearestNeighbors().

from sklearn.neighbors import NearestNeighbors
import numpy as np
import holoviews as hv
import plotly.express as px
hv.extension('matplotlib')

X = np.array([[-3, -2], [-2, -1], [-1, -1], [1, 1], [2, 1], [3, 2]]) # Example points
hv.Points(X) # Plot the example points

nbrs = NearestNeighbors(n_neighbors=2, algorithm='ball_tree').fit(X) # Compute nearest neighbor with n=2 and a distence metric of Euclidean
distances, indices = nbrs.kneighbors(X) # Execute nearest neighbor on our example points

distances # Display distances between point and its nearest neighbor

indices # Display the points and its nearest neighbor

affinity = nbrs.kneighbors_graph(X).toarray() # Create affinity matrix using nearest neighbor computed above
affinity # Display affinity matrix

affinity_sym = 0.5*(affinity+affinity.T) # Make 'affinity' symetric by averaging each point
affinity_sym # Display symetric affinity matrix

# As you can see, the affinity matrix labeled 'affinity' is not symmetric. With an assigned n of 2 each point must find 2 nearest neighbors including itself. A 1 in the matrix means that that point is a nearest neighbor for the point in which the row pertains to. In the example of the first point (the first row in the matrix), its nearest neighbor is itself and the second point. For point 2 (the second row in the matrix) its nearest neighbor is itself and point 3 not point 1. This happens because point 3 is closer to 2 then point 1 in terms of the Euclidean distance.
#
# The affinity matrix is made symmetric by averaging it by its transpose. As you can see from 'affinity_sym' some elements of the matrix now have a value of 0.5. For example, the first row (pertaining to point 1) has a value of 0.5 where it used to have a value of 1 in the second column. This tells us that point 1's nearest neighbor is point 2 but point 1 is not a nearest neighbor of point 2.
#
# Looking back at the matrix 'affinity', if we sum the matrix by its rows each row will have a value of 2 (the n value we assigned) because each point is required to find its 2 nearest neighbors. If we sum the matrix by its columns, we will get different values for each column. Column 1 will sum to 1, telling us that it is only a nearest neighbor to itself. Column 2, on the other hand, will sum to 3, telling us that it is the nearest neighbor to 2 other points besides itself.

# ***
# ## Distance Correlation Matrix
# These cells are created to test if the sepctral embedding can be computed using a distance matrix rather then an affinity matrix.

dis_corr_matrix = pairwise_distances(data_df[0:500], metric=dis_corr) # A distance correlation matrix is computed using the diget data (this matrix is symmetric)
dis_corr_matrix
hv.Image(dis_corr_matrix).opts(width=400, height=300, colorbar=True, cmap='jet') # Plot distance matrix

D = 0.25 # Distance condition
cond_matrix = np.where(dis_corr_matrix<D, 1, 0) # All distances less then 'D' are assighned a 1 and all distances greater then 'D' are assighned a 0
hv.Image(cond_matrix).opts(width=400, height=300, colorbar=True, cmap='Greys') # Plot conditional matrix 'cond_matrix'

embedding = SpectralEmbedding(n_components=3, affinity='precomputed', n_jobs=n_cpus, eigen_solver='arpack') # Compute 3D spectral embedding
data_transformed = embedding.fit_transform(np.abs(cond_matrix)) # Compute data transform by using 'cond_matrix' created above

plot_input = pd.DataFrame(data_transformed,columns=['x','y','z']) # Save transformed data at data frame
plot_input['Number'] = num_df.astype(str) # Add column of diget lables
plot = px.scatter_3d(plot_input, x='x', y='y', z='z', color='Number', width=500, height=400, opacity=0.7) # Create plot of embedding
#plot # Display plot


import wfdb
import numpy as np

# features array:
#
# (0 = no = negative = front)
# (1 = yes = positive = end)
#
# 0     parity = number of previous deliveries,
# 1     maternal age,
# 2     previous abortions,
# 3     weight,
# 4     hypertension,
# 5     diabetes,
# 6     smoker
# 7     bleeding first trimester,
# 8     bleeding second trimester,
# 9     funneling,
# 10    placental position,

# 6+ minutes
def get_features(records):
    """
    get the feature vector from the record
    string array to int array, if not, drop the record

    :param records: wfdb records to check
    :return: numpy arrays with all 15 features, and gestation period
    """
    features_set = []
    output_set = []
    canceled_index_list = []
    for (num, record) in enumerate(records):
        signals, fields = wfdb.rdsamp(record.record_name,pb_dir='tpehgdb/tpehgdb')
        features = np.empty(15, dtype=float)
        good_record_flag = True
        output = 1
        # index of features array
        i = 0
        for item in (fields['comments']):
            if "None" in item:
                # append canceled index
                canceled_index_list.append(num)
                good_record_flag = False
                break
            else:
                # good record
                if "Gestation" in item:
                    # output
                    output = (item.split()[1])
                if "Parity" in item:
                    features[i] = (item.split()[1])
                    i += 1
                if "Age" in item:
                    features[i] = (item.split()[1])
                    i += 1
                if "Abortions" in item:
                    features[i] = (item.split()[1])
                    i += 1
                if "Weight" in item:
                    features[i] = (item.split()[1])
                    i += 1
                if "Hypertension" in item:
                    if "no" in item:
                        features[i] = 0
                    else:
                        features[i] = 1
                    i += 1
                if "Diabetes" in item:
                    if "no" in item:
                        features[i] = 0
                    else:
                        features[i] = 1
                    i += 1
                if "Smoker" in item:
                    if "no" in item:
                        features[i] = 0
                    else:
                        features[i] = 1
                    i += 1
                if "Bleeding_first_trimester" in item:
                    if "no" in item:
                        features[i] = 0
                    else:
                        features[i] = 1
                    i += 1
                if "Bleeding_second_trimester" in item:
                    if "no" in item:
                        features[i] = 0
                    else:
                        features[i] = 1
                    i += 1
                if "Funneling" in item:
                    if "negative" in item:
                        features[i] = 0
                    else:
                        features[i] = 1
                    i += 1
                if "Placental_position" in item:
                    if "front" in item:
                        features[i] = 0
                    else:
                        features[i] = 1
                    i += 1
        if (good_record_flag):
            features_set.append(features)
            output_set.append(output)

    # arrays should have the same number of rows (number of records kept)
    features_array = np.empty(shape=(len(features_set),11), dtype=float)
    outputs_array = np.empty(shape=(len(output_set), 1), dtype=float)
    # convert list to ndarray
    for (i, feature_array) in enumerate(features_set):
        features_array[i] = feature_array[:-4]
    for (i, output_array) in enumerate(output_set):
        outputs_array[i] = output_array
    return features_array, outputs_array, canceled_index_list

# test preprocessing
if __name__ == "__main__":
    # record1 = wfdb.rdrecord('tpehgdb/tpehg1132',pb_dir='tpehgdb/tpehgdb') # dropped
    record2 = wfdb.rdrecord('tpehgdb/tpehg1134',pb_dir='tpehgdb/tpehgdb')
    r = []
    # r.append(record1)
    r.append(record2)
    f, o, a = get_features(r)
    for item in np.nditer(f):
        print((item))
    print(o[0])
    # signals, fields = wfdb.rdsamp(record.record_name,pb_dir='tpehgdb/tpehgdb')
    # print((fields['comments']))   # list


import os
import sys
import random
import math
import numpy as np
import skimage.io
import matplotlib
import matplotlib.pyplot as plt
import cv2
import time
import glob
import argparse
from mrcnn.config import Config
from datetime import datetime
from scipy.misc import imsave
##########################################################################
parser = argparse.ArgumentParser(description='Resize images in a folder')
parser.add_argument('--input',    '-i', help='input image folder', required=True)
args = parser.parse_args()
# Validate parameters
input_path = os.path.abspath(args.input)
if not os.path.isdir(args.input):
    print('--input ({}) must be a folder.'.format(args.input))
    sys.exit(1)

##########################################################################
# Root directory of the project
ROOT_DIR = os.getcwd()

# Import Mask RCNN
sys.path.append(ROOT_DIR)  # To find local version of the library
from mrcnn import utils
import mrcnn.model as modellib
from mrcnn import visualize
# Import COCO config
# sys.path.append(os.path.join(ROOT_DIR, "samples/coco/"))  # To find local version
# from samples.coco import coco

# Directory to save logs and trained model
MODEL_DIR = os.path.join(ROOT_DIR, "model_save")
##########################################################################
# Local path to trained weights file
# EVAL_MODEL_PATH = os.path.join(MODEL_DIR,"maskrcnn_config20200814T1659/mask_rcnn_maskrcnn_config_0187.h5")
#EVAL_MODEL_PATH=input_path
for root, _, basenames in os.walk(input_path):
        for basename in basenames:
            basename_check=basename.split('.')[1]
            if(basename_check=='h5'):
                EVAL_MODEL_PATH=os.path.join(input_path,basename)
model_basename=os.path.basename(EVAL_MODEL_PATH)
model_name=model_basename.split('.')[0]
print('model from == ',EVAL_MODEL_PATH)
print('===========================================================================================================================')
# Download COCO trained weights from Releases if needed
if not os.path.exists(EVAL_MODEL_PATH):
    utils.download_trained_weights(EVAL_MODEL_PATH)
    print("cuiwei***********************")

# Directory of images to run detection on
IMAGE_DIR = os.path.join(ROOT_DIR, "./datasets/Data640/eval_image_640x640_nospace/")
##########################################################################
class ShapesConfig(Config):
    """Configuration for training on the toy shapes dataset.
    Derives from the base Config class and overrides values specific
    to the toy shapes dataset.
    """
    # Give the configuration a recognizable name
    NAME = "MaskRCNN_config"

    # Train on 1 GPU and 8 images per GPU. We can put multiple images on each
    # GPU because the images are small. Batch size is 8 (GPUs * images/GPU).
    GPU_COUNT = 1
    IMAGES_PER_GPU = 1

    # Number of classes (including background)
    NUM_CLASSES = 1 + 24  # background + 1 shapes + 1 not_defined

    # Use small images for faster training. Set the limits of the small side
    # the large side, and that determines the image shape.
    IMAGE_MIN_DIM = 512
    IMAGE_MAX_DIM = 640

    # Use smaller anchors because our image and objects are small
    RPN_ANCHOR_SCALES = (40,80,160,320,640)  # anchor side in pixels

    # Reduce training ROIs per image because the images are small and have
    # few objects. Aim to allow ROI sampling to pick 33% positive ROIs.
    TRAIN_ROIS_PER_IMAGE =100

    # Use a small epoch since the data is simple
    STEPS_PER_EPOCH = 1

    # use small validation steps since the epoch is small
    VALIDATION_STEPS = 50

    # Non-maximum suppression threshold for detection
    #DETECTION_NMS_THRESHOLD = 0.3
##########################################################################
#import train_tongue
#class InferenceConfig(coco.CocoConfig):
class InferenceConfig(ShapesConfig):
    # Set batch size to 1 since we'll be running inference on
    # one image at a time. Batch size = GPU_COUNT * IMAGES_PER_GPU
    GPU_COUNT = 1
    IMAGES_PER_GPU = 1

config = InferenceConfig()
model = modellib.MaskRCNN(mode="inference", model_dir=MODEL_DIR, config=config)

# Create model object in inference mode.
model = modellib.MaskRCNN(mode="inference", model_dir=MODEL_DIR, config=config)
# Load weights trained on MS-COCO
model.load_weights(EVAL_MODEL_PATH, by_name=True)

# COCO Class names
# Index of the class in the list is its ID. For example, to get ID of
# the teddy bear class, use: class_names.index('teddy bear')
#class_names = ['BG', 'person']
class_names=['_background_',
             'cocacola',
             'cashewnuts',
             'M_MBIG',
             'M_MSMALL',
             'Hot-Chili-Squid-Flavor',
             'Original-Flavor',
             'Thai-Spicy-Mixed-Nuts',
             'Pon-De-Strawberry-Honey',
             'Pon-de-Strawberry',
             'Pon-De-Double-Chocolate',
             'Old-Fashioned',
             'Pon-De-Soybean',
             'Pringles',
             'TARO-FISH-SNACK',
             'SALTED-PEANUTS',
             'MANDARIN',
             'SPEARMINT',
             'Choco-Old-Fashioned',
             'Pon-De-Chocolate',
             'Fried-Seaweed',
             'Pon-De-Yogurt',
             'Strawberry-Ring',
             'Sugar-Ring'
            ]
##########################################################################
# Load a random image from the images folder
file_names = next(os.walk(IMAGE_DIR))[2]
#random_image_name=random.choice(file_names)
count=1
for eval_image in file_names:
    print('eval image... ',count)
    choice_eval_image_path=os.path.join(IMAGE_DIR,eval_image)
    image = skimage.io.imread(choice_eval_image_path)
    results = model.detect([image], verbose=1)
    r = results[0]
    visualize.display_instances(eval_image,image, r['rois'], r['masks'], r['class_ids'],
                            class_names, r['scores'])
    count+=1
print('===========================================================================================================================')
'''
a=datetime.now()
# Run detection
results = model.detect([image], verbose=1)
b=datetime.now()
# Visualize results
print("shijian",(b-a).seconds)
r = results[0]

#print('r == ',r)
#display_instances in visualize.py lines 83
visualize.display_instances(random_image_name,image, r['rois'], r['masks'], r['class_ids'],
                            class_names, r['scores'])
'''


from functools import partial
import time
from interp.ui.attribution_backend import AttributionBackend
from interp.ui.very_named_tensor import LazyVeryNamedTensor, VeryNamedTensor
from typing import Any
import asyncio
import websockets
import json
from interp.model.model_loading import load_model
from interp.encoding import get_callback_result, callables_table, msgpack_encode
import threading
from threading import Lock

from IPython.core.display import display, HTML
from typing import *

served_things: Dict[str, Any] = {}
thread = None
lock = Lock()
sockets = []

async def handler(websocket):
    global sockets
    print("handler")
    this_obj = {"websocket": websocket, "name": None}
    sockets.append(this_obj)
    async for buf in websocket:
        msg = json.loads(buf)
        kind = msg.get("kind")
        print(kind)
        if kind == "init":
            pass
        elif kind == "nameStartup":
            name = msg["name"]
            print("name", name)
            this_obj["name"] = name
            with lock:
                thing = served_things.get(name, None)
            await websocket.send(msgpack_encode({"kind": "nameStartup", "data": thing}))
        elif kind == "callback":
            enc = msgpack_encode(get_callback_result(msg))
            await websocket.send(enc)
        else:
            print("Unrecognized message: ", msg)

def loop_in_thread(loop, port):
    print("started")

    asyncio.set_event_loop(loop)
    loop.run_until_complete(websockets.serve(handler, "localhost", port))
    loop.run_forever()

async def init(port=6789):
    global thread
    port = str(port)
    loop = asyncio.new_event_loop()
    t = threading.Thread(target=loop_in_thread, args=(loop, port))
    t.start()
    thread = t
    print(
        "Composable UI initialized! Make sure you've run `npm install` and `npm run start` in /interp/app before using"
    )

async def show_tensors(*lvnts, name="untitled"):
    lvnts = [lvnt.to_lvnt() if not isinstance(lvnt, LazyVeryNamedTensor) else lvnt for lvnt in lvnts]
    with lock:
        did_exist = name in served_things
        served_things[name] = lvnts
    if did_exist:
        encoded = msgpack_encode({"kind": "nameStartup", "data": lvnts})
        try:
            await [socket for socket in sockets if socket["name"] == name][0]["websocket"].send(encoded)
        except:
            pass
    link = f"http://127.0.0.1:3000/#/tensors/{name}"
    return display(
        HTML(f'
Link
')
    )

async def show_fns(*lvnt_makers, name="untitled"):
    with lock:
        did_exist = name in served_things
        served_things[name] = lvnt_makers
    link = f"http://127.0.0.1:3000/#/functions/{name}"
    if did_exist:
        await [socket for socket in sockets if socket["name"] == name][0]["websocket"].send(
            msgpack_encode({"kind": "nameStartup", "data": lvnt_makers})
        )

    return display(
        HTML(f'
Link
')
    )

async def show_attribution(model, params, tokenizer, name="untitled"):
    func = partial(AttributionBackend, model, params, tokenizer)
    with lock:
        did_exist = name in served_things
        served_things[name] = func
    if did_exist:
        await [socket for socket in sockets if socket["name"] == name][0]["websocket"].send(
            msgpack_encode({"kind": "nameStartup", "data": func})
        )
    link = f"http://127.0.0.1:3000/#/attribution/{name}"
    return display(
        HTML(f'
Link
')
    )


# Code for 'diabetes_main.py' file.

# Importing the necessary Python modules.
import streamlit as st
import numpy as np
import pandas as pd

# Configure your home page by setting its title and icon that will be displayed in a browser tab.
st.set_page_config(page_title = 'Early Diabetes Prediction Web App',
                    page_icon = 'random',
                    layout = 'wide',
                    initial_sidebar_state = 'auto'
                    )

# Loading the dataset.
@st.cache()
def load_data():
    # Load the Diabetes dataset into DataFrame.

    df = pd.read_csv('diabetes.csv')
    df.head()

    # Rename the column names in the DataFrame.
    df.rename(columns = {"BloodPressure": "Blood_Pressure",}, inplace = True)
    df.rename(columns = {"SkinThickness": "Skin_Thickness",}, inplace = True)
    df.rename(columns = {"DiabetesPedigreeFunction": "Pedigree_Function",}, inplace = True)

    df.head()

    return df

diabetes_df = load_data()

# Create the Page Navigator for 'Home', 'Predict Diabetes' and 'Visualise Decision Tree' web pages in 'diabetes_main.py'
# Import the 'diabetes_predict' 'diabetes_home', 'diabetes_plots' Python files
import diabetes_predict
import diabetes_home
import diabetes_plots

# Adding a navigation in the sidebar using radio buttons
# Create the 'pages_dict' dictionary to navigate.
pages_dict = {"Home": diabetes_home,
           "Predict Diabetes": diabetes_predict,
           "Visualise Decision Tree": diabetes_plots}
# Add radio buttons in the sidebar for navigation and call the respective pages based on user selection.
st.sidebar.title('Navigation')
user_choice=st.sidebar.radio('Go to', tuple(pages_dict.keys()))
selected_page=pages_dict[user_choice]
selected_page.app(diabetes_df)


from typing import Optional, Union

import torch
import torch.nn as nn
import torch.nn.functional as F
import torchaudio
from pyannote.core.utils.generators import pairwise

from pyannote.audio.core.model import Model
from pyannote.audio.core.task import Task
from pyannote.audio.utils.params import merge_dict

class SSeRiouSS(Model):
    """Self-Supervised Representation for Speaker Segmentation

    wav2vec > LSTM > Feed forward > Classifier

    Parameters
    ----------
    sample_rate : int, optional
        Audio sample rate. Defaults to 16kHz (16000).
    num_channels : int, optional
        Number of channels. Defaults to mono (1).
    wav2vec: dict or str, optional
        Defaults to "WAVLM_BASE".
    wav2vec_layer: int, optional
        Index of layer to use as input to the LSTM.
        Defaults (-1) to use average of all layers (with learnable weights).
    lstm : dict, optional
        Keyword arguments passed to the LSTM layer.
        Defaults to {"hidden_size": 128, "num_layers": 4, "bidirectional": True},
        i.e. two bidirectional layers with 128 units each.
        Set "monolithic" to False to split monolithic multi-layer LSTM into multiple mono-layer LSTMs.
        This may proove useful for probing LSTM internals.
    linear : dict, optional
        Keyword arugments used to initialize linear layers
        Defaults to {"hidden_size": 128, "num_layers": 2},
        i.e. two linear layers with 128 units each.
    """

    WAV2VEC_DEFAULTS = "WAVLM_BASE"

    LSTM_DEFAULTS = {
        "hidden_size": 128,
        "num_layers": 4,
        "bidirectional": True,
        "monolithic": True,
        "dropout": 0.0,
    }
    LINEAR_DEFAULTS = {"hidden_size": 128, "num_layers": 2}

    def __init__(
        self,
        wav2vec: Union[dict, str] = None,
        wav2vec_layer: int = -1,
        lstm: dict = None,
        linear: dict = None,
        sample_rate: int = 16000,
        num_channels: int = 1,
        task: Optional[Task] = None,
    ):
        super().__init__(sample_rate=sample_rate, num_channels=num_channels, task=task)

        if isinstance(wav2vec, str):
            # `wav2vec` is one of the supported pipelines from torchaudio (e.g. "WAVLM_BASE")
            if hasattr(torchaudio.pipelines, wav2vec):
                bundle = getattr(torchaudio.pipelines, wav2vec)
                if sample_rate != bundle._sample_rate:
                    raise ValueError(
                        f"Expected {bundle._sample_rate}Hz, found {sample_rate}Hz."
                    )
                wav2vec_dim = bundle._params["encoder_embed_dim"]
                wav2vec_num_layers = bundle._params["encoder_num_layers"]
                self.wav2vec = bundle.get_model()

            # `wav2vec` is a path to a self-supervised representation checkpoint
            else:
                _checkpoint = torch.load(wav2vec)
                wav2vec = _checkpoint.pop("config")
                self.wav2vec = torchaudio.models.wav2vec2_model(**wav2vec)
                state_dict = _checkpoint.pop("state_dict")
                self.wav2vec.load_state_dict(state_dict)
                wav2vec_dim = wav2vec["encoder_embed_dim"]
                wav2vec_num_layers = wav2vec["encoder_num_layers"]

        # `wav2vec` is a config dictionary understood by `wav2vec2_model`
        # this branch is typically used by Model.from_pretrained(...)
        elif isinstance(wav2vec, dict):
            self.wav2vec = torchaudio.models.wav2vec2_model(**wav2vec)
            wav2vec_dim = wav2vec["encoder_embed_dim"]
            wav2vec_num_layers = wav2vec["encoder_num_layers"]

        if wav2vec_layer < 0:
            self.wav2vec_weights = nn.Parameter(
                data=torch.ones(wav2vec_num_layers), requires_grad=True
            )

        lstm = merge_dict(self.LSTM_DEFAULTS, lstm)
        lstm["batch_first"] = True
        linear = merge_dict(self.LINEAR_DEFAULTS, linear)

        self.save_hyperparameters("wav2vec", "wav2vec_layer", "lstm", "linear")

        monolithic = lstm["monolithic"]
        if monolithic:
            multi_layer_lstm = dict(lstm)
            del multi_layer_lstm["monolithic"]
            self.lstm = nn.LSTM(wav2vec_dim, **multi_layer_lstm)

        else:
            num_layers = lstm["num_layers"]
            if num_layers > 1:
                self.dropout = nn.Dropout(p=lstm["dropout"])

            one_layer_lstm = dict(lstm)
            one_layer_lstm["num_layers"] = 1
            one_layer_lstm["dropout"] = 0.0
            del one_layer_lstm["monolithic"]

            self.lstm = nn.ModuleList(
                [
                    nn.LSTM(
                        wav2vec_dim
                        if i == 0
                        else lstm["hidden_size"] * (2 if lstm["bidirectional"] else 1),
                        **one_layer_lstm,
                    )
                    for i in range(num_layers)
                ]
            )

        if linear["num_layers"] < 1:
            return

        lstm_out_features: int = self.hparams.lstm["hidden_size"] * (
            2 if self.hparams.lstm["bidirectional"] else 1
        )
        self.linear = nn.ModuleList(
            [
                nn.Linear(in_features, out_features)
                for in_features, out_features in pairwise(
                    [
                        lstm_out_features,
                    ]
                    + [self.hparams.linear["hidden_size"]]
                    * self.hparams.linear["num_layers"]
                )
            ]
        )

    def build(self):
        if self.hparams.linear["num_layers"] > 0:
            in_features = self.hparams.linear["hidden_size"]
        else:
            in_features = self.hparams.lstm["hidden_size"] * (
                2 if self.hparams.lstm["bidirectional"] else 1
            )

        if isinstance(self.specifications, tuple):
            raise ValueError("SSeRiouSS model does not support multi-tasking.")

        if self.specifications.powerset:
            out_features = self.specifications.num_powerset_classes
        else:
            out_features = len(self.specifications.classes)

        self.classifier = nn.Linear(in_features, out_features)
        self.activation = self.default_activation()

    def forward(self, waveforms: torch.Tensor) -> torch.Tensor:
        """Pass forward

        Parameters
        ----------
        waveforms : (batch, channel, sample)

        Returns
        -------
        scores : (batch, frame, classes)
        """

        num_layers = (
            None if self.hparams.wav2vec_layer < 0 else self.hparams.wav2vec_layer
        )

        with torch.no_grad():
            outputs, _ = self.wav2vec.extract_features(
                waveforms.squeeze(1), num_layers=num_layers
            )

        if num_layers is None:
            outputs = torch.stack(outputs, dim=-1) @ F.softmax(
                self.wav2vec_weights, dim=0
            )
        else:
            outputs = outputs[-1]

        if self.hparams.lstm["monolithic"]:
            outputs, _ = self.lstm(outputs)
        else:
            for i, lstm in enumerate(self.lstm):
                outputs, _ = lstm(outputs)
                if i + 1 < self.hparams.lstm["num_layers"]:
                    outputs = self.dropout(outputs)

        if self.hparams.linear["num_layers"] > 0:
            for linear in self.linear:
                outputs = F.leaky_relu(linear(outputs))

        return self.activation(self.classifier(outputs))


import inspect

import json
import sys

import arrow # TODO cpy3.7  datetime.fromisoformat('2017-01-01T12:30:59.000000+08:00')

from datetime import datetime, date

from aiohttp.web_exceptions import HTTPException
from .exception import RESTfulArgumentError

def argument_getter_factory(route_spec):
    """ 根据spec来生成handler函数参数值读取器 """

    func_sig = inspect.signature(route_spec.handler_func)

    param_names = list(func_sig.parameters.keys())
    arg_getters  = build_argval_getters(route_spec)
    n_args = len(arg_getters)

    async def argument_getters(request):
        errors = None
        values = {}
        for i in range(n_args):
            try:
                arg_name = param_names[i]
                values[arg_name] = await arg_getters[i](request)
            except HTTPException:
                raise
            except Exception as exc :
                if errors is None:
                    errors = []

                request.app.logger.error('', exc_info=True)

                exc_type = type(exc)

                data = {
                    "name": arg_name,
                    "type": f"{exc_type.__module__}.{exc_type.__qualname__}",
                    "error": str(exc)
                }

                errors.append(data)

        if errors is not None:
            raise RESTfulArgumentError(errors)

        return values

    return argument_getters

_handler_argval_getters = []

def register_argument_getter(getter_factory):
    _handler_argval_getters.append(getter_factory)

def build_argval_getters(route_spec):

    # proto, method, handler_func, path_fields
    # proto, method, handler, path_params

    getters = []
    for arg_name in inspect.signature(route_spec.handler_func).parameters:
        getter = _build_argval_getter(route_spec, arg_name)
        getters.append(getter)

    return getters

def _build_argval_getter(route_spec, arg_name):
    arg_spec = inspect.signature(route_spec.handler_func).parameters[arg_name]
    # print(123, arg_name)
    ann_type = arg_spec.annotation
    argval_getter = None
    if ann_type != inspect._empty:
        for getter_factory in _handler_argval_getters[::-1]:
            # print(3222, getter_factory)
            argval_getter = getter_factory(route_spec, arg_name)
            if argval_getter is not None:
                break

    if argval_getter is None:
        argval_getter = _defaul_argval_getter(route_spec, arg_name)

    if arg_spec.default is not inspect._empty:
        async def _getter(request):
            arg_val = await argval_getter(request)
            # if arg_val is None:
            #     arg_val = arg_spec.default

            return arg_val
    else:
        async def _getter(request):
            try:
                # print(arg_name, argval_getter)
                arg_val = await argval_getter(request)
            except TypeError as exc :
                raise TypeError(f"{exc} while reading '{arg_name}' with "
                                f"'{argval_getter.__qualname__}'")
            return arg_val

    return _getter

#----------------------------------------------------------------------------

def default_argval_getter_factory(route_spec, arg_name):

    if arg_name in route_spec.path_fields:
        async def _path_param_getter(request):
            return request.match_info.get(arg_name)
        return _path_param_getter

    async def _argvalue_func(request):
        if request.method in request.POST_METHODS:
            arg_val = request.post().get(arg_name)
            if arg_val is not None:
                return arg_val

        arg_val = request.query.get(arg_name)
        if arg_val is not None:
            return arg_val

        return None

    return _argvalue_func

def _defaul_argval_getter(route_spec, arg_name):
    arg_spec = inspect.signature(route_spec.handler_func).parameters[arg_name]
    ann_type = arg_spec.annotation

    read_argval = default_argval_getter_factory(route_spec, arg_name)

    if (issubclass(ann_type, int) or issubclass(ann_type, float)):
        async def _getter_func(request):
            arg_val = await read_argval(request)
            if arg_val is not None:
                arg_val = ann_type(arg_val)

            return arg_val
        return _getter_func

    async def _getter_func(request):
        return await read_argval(request)

    return read_argval

async def read_json(request):
    text = await request.text()
    return json.loads(text)

def _json_arg_getter(route_spec, arg_name):
    if arg_name not in ['json_arg', 'json_body']:
        return

    return read_json

def _identity_getter(route_spec, arg_name):
    if arg_name not in ['identity']:
        return

    async def _identify(request):
        secure_layer = request.app.get('secure_layer')
        if secure_layer is None:
            return None

        identity = await secure_layer.identify(request)
        return identity

    return _identify

def _datetime_value_getter(route_spec, arg_name):
    arg_spec = inspect.signature(route_spec.handler_func).parameters[arg_name]
    ann_type = arg_spec.annotation

    if not issubclass(ann_type, datetime):
        return

    read_argval = default_argval_getter_factory(route_spec, arg_name)

    async def getter(request):
        arg_val = arrow.get(read_argval(request)).datetime
        return arg_val

    return getter

def _date_value_getter(route_spec, arg_name):
    arg_spec = inspect.signature(route_spec.handler_func).parameters[arg_name]
    ann_type = arg_spec.annotation

    if not issubclass(ann_type, date):
        return

    read_argval = default_argval_getter_factory(route_spec, arg_name)

    async def getter(request, arg_val):
        arg_val = arrow.get(arg_val).datetime.date()
        return arg_val

    return getter

register_argument_getter(_identity_getter)
register_argument_getter(_json_arg_getter)
register_argument_getter(_date_value_getter)
register_argument_getter(_datetime_value_getter)