# Buddy 챗봇 모델을 API 형태로 발행할 때 필요한 py 파일

import sys
import torch
import torch.nn as nn
import random
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import bson
import base64
from tqdm import tqdm
from flask import Flask, render_template, request, jsonify, json, Response, make_response
from flask_mobility import Mobility

import azure.cognitiveservices.speech as speechsdk
from azure.cognitiveservices.speech import AudioDataStream, SpeechConfig, SpeechSynthesizer, SpeechSynthesisOutputFormat
from azure.cognitiveservices.speech.audio import AudioOutputConfig
import cognitive_face as CF

from transformers import AdamW
from torch.utils.data import dataloader
from dataloader.wellness import WellnessTextClassificationDataset
from model.kobert import KoBERTforSequenceClassfication
from model.kobert import KoBERTforSequenceClassfication, kobert_input
from kobert_transformers import get_tokenizer

# 로컬 폴더 path 추가 & root path 설정
sys.path.append('C:')
sys.path.append('C:/buddy')
root_path = "C:/buddy"

# 해당 파일을 처음 실행시켰을 때, 한 번만 실행되어야 할 것들
# Flask 설정
app = Flask(__name__)
#app.config['SECRET_KEY'] = 'enter-a-very-secretive-key-3479373'

# Azure Speech 서비스 key와 지역 할당
speech_key, service_region = "<YOUR API KEY>", "koreacentral"
speech_config = speechsdk.SpeechConfig(subscription=speech_key, region=service_region)

# STT/TTS 사전 설정. 한국어와 여성의 음성을 선택
speech_config.speech_synthesis_language = "ko-KR"
speech_config.speech_synthesis_voice_name = "ko-KR-SunHiNeural"

# Face Recogntion
KEY = "<YOUR API KEY>"
CF.Key.set(KEY)
BASE_URL = 'https://koreacentral.api.cognitive.microsoft.com/face/v1.0/'
CF.BaseUrl.set(BASE_URL)
happiness, anger, contempt, disgust, fear, sadness = [0, 0, 0, 0, 0, 0]
img_url = './emotions/frame.png'

# category와 answer 파일 열어서 답변 리스트를 생성하는 함수
def load_wellness_answer():
  category_path = f"{root_path}/data/wellness_dialog_category.txt"
  answer_path = f"{root_path}/data/wellness_dialog_answer.txt"

  c_f = open(category_path, 'r', encoding='UTF-8')
  a_f = open(answer_path, 'r', encoding='UTF-8')

  category_lines = c_f.readlines()
  answer_lines = a_f.readlines()

  category = {}
  answer = {}
  for line_num, line_data in enumerate(category_lines):
    data = line_data.split('    ')
    category[data[1][:-1]]=data[0]

  for line_num, line_data in enumerate(answer_lines):
    data = line_data.split('    ')
    keys = answer.keys()
    if(data[0] in keys):
      answer[data[0]] += [data[1][:-1]]
    else:
      answer[data[0]] =[data[1][:-1]]

  return category, answer

# 챗봇 Model 불러오기 및 실행
# 지난 번 실행이 느렸던건 해당 부분이 chatbotResponse()에 포함되어 반복해서 불러오는 작업을 수행했기 때문
checkpoint_path = f"{root_path}/checkpoint"
save_ckpt_path = f"{checkpoint_path}/kobert-wellnesee-text-classification.pth"

category, answer = load_wellness_answer()

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

checkpoint = torch.load(save_ckpt_path, map_location=device) # 저장한 Checkpoint 불러오기

model = KoBERTforSequenceClassfication()
model.load_state_dict(checkpoint['model_state_dict'])

model.to(ctx)
model.eval()

tokenizer = get_tokenizer()

# 기본 home 출력하는 탬플릿
@app.route('/', methods=["GET", "POST"])
def index():
    return render_template('index.html', **locals())

# 대기 시 수행하는 것. 먼저 말을 걸거나 표정이 안좋아보이기 전엔 대기
@app.route('/standby', methods=["GET", "POST"])
def standby():
    if request.method == 'POST': #post 방식으로 전송될 경우
        # files과 json 형식으로 데이터를 받음
        binary_data = {}
        the_files = request.files
        the_data = request.get_json()
        for file in the_files:
            binary_data[file] = the_files[file].read()

        # 받은 png와 wav 파일 저장
        f1 = open('./emotions/frame.png', 'wb')
        f1.write(binary_data['images'])
        f2 = open('./audio/user_voice.wav', 'wb')
        f2.write(binary_data['wave'])
        f1.close()
        f2.close()
        state = float(binary_data['state'])

        # 표정에서 감정 추출
        faces = CF.face.detect(img_url, True, False, "age, gender, emotion")
        for i in faces:
            happiness = i['faceAttributes']['emotion']['happiness']
            anger = i['faceAttributes']['emotion']['anger']
            contempt = i['faceAttributes']['emotion']['contempt']
            disgust = i['faceAttributes']['emotion']['disgust']
            fear = i['faceAttributes']['emotion']['fear']
            sadness = i['faceAttributes']['emotion']['sadness']
        bad_expression = anger + contempt + disgust + fear + sadness

        if happiness < bad_expression:  # 우울해 보일 때
            state = state + 0.1 # 잘못 체크 할 수도 있으니 약간만 증가
            # 무슨 일이 있으신가요? 기분이 안좋아보여요. 제가 도울 수 있는게 있으면 말해주세요.
            open_read = open('./audio/Opening.wav', 'rb').read()
            encoded = base64.b64encode(open_read)
            dict_data = {"response": str(encoded), "run_check": "1", "state": str(state)}

            return Response(json.dumps(dict_data), mimetype='text/plain')
        else:  # 우울해 보이지 않을 땐 버디 이름을 부를때까지 대기
            audio_input = speechsdk.AudioConfig(filename="./audio/user_voice.wav")
            speech_recognizer = speechsdk.SpeechRecognizer(speech_config=speech_config,
                                                           language="ko-KR", audio_config=audio_input)
            the_question = speech_recognizer.recognize_once_async().get()
            if '버디' in the_question.text:  # 이름을 불렀을 때
                # 네, 부르셨나요?
                open_read = open('./audio/call_name.wav', 'rb').read()
                encoded = base64.b64encode(open_read)
                dict_data = {"response": str(encoded), "run_check": "1", "state": str(state)}

                return Response(json.dumps(dict_data), mimetype='text/plain')

        # 아무런 말이 없을 때는 무음 wav를 return한다 (형식을 맞추기 위함)
        open_read = open('./audio/silence.wav', 'rb').read()
        encoded = base64.b64encode(open_read)
        dict_data = {"response": str(encoded), "run_check": "0", "state": str(state)}

        return Response(json.dumps(dict_data), mimetype='text/plain')

# 본격적인 대화 부분
@app.route('/chatbot', methods=["GET", "POST"])
def chatbotResponse():
    if request.method == 'POST': #post 방식으로 전송될 경우
        # files 형식으로 데이터를 받음
        binary_data = {}
        the_files = request.files
        for file in the_files:
            binary_data[file] = the_files[file].read()

        # 받은 png와 wav 파일 저장
        f1 = open('./emotions/frame.png', 'wb')
        f1.write(binary_data['images'])
        f2 = open('./audio/user_voice.wav', 'wb')
        f2.write(binary_data['wave'])
        f1.close()
        f2.close()
        state = float(binary_data['state'])
        silence = int(binary_data['silence'])

        faces = CF.face.detect(img_url, True, False, "age, gender, emotion")
        for i in faces:
            happiness = i['faceAttributes']['emotion']['happiness']
            anger = i['faceAttributes']['emotion']['anger']
            contempt = i['faceAttributes']['emotion']['contempt']
            disgust = i['faceAttributes']['emotion']['disgust']
            fear = i['faceAttributes']['emotion']['fear']
            sadness = i['faceAttributes']['emotion']['sadness']
        bad_expression = anger + contempt + disgust + fear + sadness

        if happiness < bad_expression:  # 우울해 보일 때
            state = state + bad_expression * 0.5

        # STT API로 사용자의 발화를 문자로 변환
        audio_input = speechsdk.AudioConfig(filename="./audio/user_voice.wav")
        speech_recognizer = speechsdk.SpeechRecognizer(speech_config=speech_config,
                                                           language="ko-KR", audio_config=audio_input)
        the_question = speech_recognizer.recognize_once_async().get()

        if '종료' in the_question.text:  # 종료를 원할 때
            # 네. 종료하겠습니다.
            open_read = open('./audio/end.wav', 'rb').read()
            encoded = base64.b64encode(open_read)
            dict_data = {"response": str(encoded), "run_check": "0", "state": str(0),
                         "silence": str(0), "music": str(0)}

            return Response(json.dumps(dict_data), mimetype='text/plain')

        elif '음악' in the_question.text:  # 음악 재생을 바랄 때
            # 음악을 재생합니다.
            open_read = open('./audio/music_start.wav', 'rb').read()
            encoded = base64.b64encode(open_read)
            dict_data = {"response": str(encoded), "run_check": "0", "state": str(0),
                         "silence": str(0), "music": str(1)}

            return Response(json.dumps(dict_data), mimetype='text/plain')

        elif state >= 10.0 :  # 기준 수치 초과
            # 마음이 소란 스러울 때, 듣기 좋은 음악을 들어보시는 건 어떤가요? 원하신다면 음악 틀어줘, 라고 말해주세요.
            open_read = open('./audio/suggestion.wav', 'rb').read()
            encoded = base64.b64encode(open_read)
            dict_data = {"response": str(encoded), "run_check": "1", "state": str(state),
                         "silence": str(silence), "music": str(0)}

            return Response(json.dumps(dict_data), mimetype='text/plain')

        elif len(str(the_question.text)) <= 1: # 사용자가 침묵하고 있을 때
            silence = silence + 1
            open_read = open('./audio/silence.wav', 'rb').read()
            encoded = base64.b64encode(open_read)
            dict_data = {"response": str(encoded), "run_check": "1", "state": str(state),
                         "silence": str(silence), "music": str(0)}

            return Response(json.dumps(dict_data), mimetype='text/plain')

        else : # 음성이 녹음되어 있을 때
            data = kobert_input(tokenizer, str(the_question.text), device, 512)

            output = model(**data)

            logit = output[0]
            softmax_logit = torch.softmax(logit, dim=-1)
            softmax_logit = softmax_logit.squeeze()

            max_index = torch.argmax(softmax_logit).item()
            max_index_value = softmax_logit[torch.argmax(softmax_logit)].item()

            answer_list = answer[category[str(max_index)]]
            answer_len = len(answer_list) - 1
            answer_index = random.randint(0, answer_len)

            response = answer_list[answer_index]
            state = state + 1

            # TTS API로 음성 답변 생성
            audio_config = AudioOutputConfig(filename="./audio/response.wav")
            synthesizer = SpeechSynthesizer(speech_config=speech_config, audio_config=audio_config)
            synthesizer.speak_text_async(response)

            open_read = open('./audio/response.wav', 'rb').read()
            encoded = base64.b64encode(open_read)
            dict_data = {"response": str(encoded), "run_check": "1", "state": str(state),
                         "silence": str(silence), "music": str(0)}

            return Response(json.dumps(dict_data), mimetype='text/plain')

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


import json
from db import db
from flask import Flask
from flask import request
from db import Party
from db import User
import os

app = Flask(__name__)

app = Flask(__name__)
db_filename = "findmyparty.db"

app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///%s" % db_filename
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True
app.config["SQLALCHEMY_ECHO"] = True

db.init_app(app)
with app.app_context():
    db.create_all()

def success_response(data, code=200):
    return json.dumps(data), code

def failure_response(message, code=404):
    return json.dumps({"error": message}), code

@app.route("/api/parties/")
def get_all_parties():
    print('called-route')
    return success_response(
        {"parties":[party.serialize() for party in Party.query.all()]}
    )

@app.route("/api/parties/host/", methods=['POST'])
def host_party():
    body = json.loads(request.data)
    host = body.get("host")
    location = body.get("location")
    photoURL = body.get("photoURL")
    dateTime = body.get("dateTime")
    theme = body.get("theme")
    if not (body or host or location or photoURL or dateTime):
        return failure_response("The request is badly formatted.", 400)
    new_party = Party(
        host=host,
        location=location,
        photoURL=photoURL,
        dateTime=dateTime,
        theme=theme,
        attendees=[]
    )
    print(new_party)
    db.session.add(new_party)
    db.session.commit()
    return success_response(
        new_party.serialize(),
        201
    )
@app.route("/api/party/<int:party_id>/")
def get_party_by_id(party_id):
    party = Party.query.filter_by(id=party_id).first()
    if not party:
        return failure_response(f"Party with ID {party_id} does not exist!")
    return success_response(party.serialize())

@app.route("/api/users/", methods=["POST"])
def add_user():
    body = json.loads(request.data)
    name = body.get("name")
    email = body.get("email")
    photoURL = body.get("photoURL")
    if  not (name or email or photoURL):
        return failure_response("The request is badly formatted.", 400)
    new_user = User(
        name=name,
        email=email,
        photoURL=photoURL,
        parties = []
    )
    db.session.add(new_user)
    db.session.commit()
    return success_response(
        new_user.serialize(),
        201
    )

@app.route("/api/user/<int:user_id>/")
def get_user_by_id(user_id):
    user = User.query.filter_by(id=user_id).first()
    if not user:
        return failure_response(f"User with ID {user_id} does not exist!")
    return success_response(user.serialize())

@app.route("/api/party/<int:party_id>/attend/", methods=["POST"])
def attend_party(party_id):
    body = json.loads(request.data)
    id = body.get("user_id")
    if not id:
        return failure_response(f"The request is badly formatted.")
    user = User.query.filter_by(id=id).first()
    if not user:
        return failure_response(f"User with ID {id} does not exist!")
    party = Party.query.filter_by(id=party_id).first()
    if not party:
        failure_response(f"Party with ID {party_id} does not exist!")
    user.parties.append(party)
    party.users.append(user)
    db.session.commit()
    return success_response(
        party.serialize(),
        200
    )

@app.route("/api/party/<int:party_id>/attendees/")
def get_attendees(party_id):
    party = Party.query.filter_by(id=party_id).first()
    if not party:
        failure_response(f"Party with ID {party_id} does not exist!")
    attendees = party.serialize()["attendees"]
    return success_response(attendees, 200)

@app.route("/api/user/<int:user_id>/parties/")
def get_parties(user_id):
    user = User.query.filter_by(id=user_id).first()
    if not user:
        return failure_response(f"User with ID {user_id} does not exist!")
    parties = user.serialize()["parties"]
    return success_response(parties, 200)

@app.route("/api/user/email/", methods=['POST'])
def get_user_by_email():
    body = json.loads(request.data)
    email = body.get("email")
    if not email:
        return failure_response("No email provided")
    user = User.query.filter_by(email=email).first()
    if not user:
        return failure_response(f"User with email {email} does not exist!")
    return success_response(user.serialize(), 200)

@app.route("/api/user/delete/", methods=["DELETE"])
def delete_user_by_email():
    body = json.loads(request.data)
    email = body.get("email")
    if not email:
        return failure_response("No email provided")
    user = User.query.filter_by(email=email).first()
    if not user:
        return failure_response(f"User with email {email} does not exist!")
    db.session.delete(user)
    db.session.commit()
    return success_response(user.serialize())

@app.route("/api/party/<int:id>/delete/", methods=["DELETE"])
def delete_party_by_id(id):
    party = Party.query.filter_by(id=id).first()
    if not party:
        return failure_response(f"Party with id {id} does not exist!")
    db.session.delete(party)
    db.session.commit()
    return success_response(party.serialize())

if __name__ == "__main__":
    port = int(os.environ.get("PORT", 5000))
    app.run(host='0.0.0.0', port=port)


import torch
import os
import numpy as np
import re

from src.config import cfg
from src.data import make_gallery_loader, make_query_loader
from src.modeling import build_model
from src.data.transforms import build_transforms

def Singleton(cls):
    _instance = {}

    def _singleton(*args, **kargs):
        if cls not in _instance:
            _instance[cls] = cls(*args, **kargs)
        return _instance[cls]

    return _singleton

@Singleton
class ReidModel(object):
    """
    """
    def __init__(self, config = cfg, config_file="configs/softmax_triplet.yml"):
        """ initialize a ReidModel object
        :param:
            :config_file: a relative path of yml file, which specify the model type, model weight path etc.
        """
        # build kernel
        config.merge_from_file(os.path.join(os.path.dirname(__file__), config_file))
        self.__cfg = config
        self.__kernel = None
        self.__build_kernel(config)

        # load or extract gallery features
        self.__gallery_image_features = None
        self.__gallery_image_paths = None
        self.__load_gallery_features()

        self.__transform = build_transforms(config)

    def __build_kernel(self, config):
        """ build reid algorighm kernel object. only for extracting image features
        :param:
            config: CfgNode object; specifiy model structure, weight path etc.
        :return: reid algorighm kernel object
        """
        kernel = build_model(config)
        kernel.load_param(config.TEST.WEIGHT)
        kernel.eval()
        kernel.cuda()
        self.__kernel = kernel

    def __update_gallery_feature(self, feature_dir="./Features"):
        """ forece to update the gallery feature in case of gallery change
        :param:
            :feature_path: archive path of gallery features:
        """
        # update features in memory
        gallery_loader = make_gallery_loader(self.__cfg)
        gallery_image_features, gallery_image_paths = self.__extract_gallery_features(gallery_loader)
        self.__gallery_image_features = gallery_image_features
        self.__gallery_image_paths = gallery_image_paths

        # update features archived
        os.makedirs(feature_dir, exist_ok=True)
        feature_path = os.path.join(feature_dir, "feautures.pt")
        torch.save(gallery_image_features, feature_path)

        image_list_path = os.path.join(feature_dir, "image_paths.txt")
        with open(image_list_path, 'w') as f:
            for image_path in gallery_image_paths:
                f.write(image_path+'\n')

    def __load_gallery_features(self, feature_dir="./Features"):
        """ load gallery features if exists, otherwise extract gallery features and store it.
        :param:
            :feature_path: archive path of gallery features
        """
        feature_path = os.path.join(feature_dir, "feautures.pt")
        image_list_path = os.path.join(feature_dir, "image_paths.txt")

        if os.path.exists(feature_path) and os.path.exists(image_list_path):
            self.__gallery_image_features = torch.load(feature_path)
            with open(image_list_path) as f:
                self.__gallery_image_paths = f.readlines()
                self.__gallery_image_paths = [image_path.rstrip('\n') for image_path in self.__gallery_image_paths]
        else:
            self.__update_gallery_feature(feature_dir=feature_dir)

    def __extract_single_feature(self, image):
        """ extract feature for a single image. usually for query image
        :param:
            :image: PIL.Image.Image object; image to process.
        """
        image = image.convert('RGB')
        image = self.__transform(image)
        image = image.unsqueeze(0)              # 从(c,h,w) _ (1,c,h,w)适配模型的输入
        image = image.to(self.__cfg.MODEL.DEVICE)
        with torch.no_grad():
            feature = self.__kernel(image)
            feature = torch.nn.functional.normalize(feature, dim=1, p=2)            # nomralization for compute cosine distance
            return feature

    def __extract_gallery_features(self, dataloader):
        features = []
        image_paths = []
        g_pids = []
        g_camids = []

        with torch.no_grad():
            for batch in dataloader:
                data, pids, camids, img_paths = batch
                data = data.to(self.__cfg.MODEL.DEVICE)
                feat = self.__kernel(data)
                features.append(feat)
                image_paths += img_paths
                g_pids.extend(pids)
                g_camids.extend(camids)

            self.__g_pids = g_pids
            self.__g_camids = g_camids
            features = torch.cat(features, dim=0)
            features = torch.nn.functional.normalize(features, dim=1, p=2)
            return features, image_paths

    def __compute_distance_matrix(self, qf, gf):
        """ compute the distance between query feature and gallery features
        :param:
            qf: query feature
            gf: gallery feature
        :return: distmat: a [1xn] matrix, matrix[0][i] indicates the distance between query feature and ith gallery feature.
        """
        # nomalize the query feature and gallery feature
        print("The query feature is normalized")

        m, n = qf.shape[0], gf.shape[0]
        distmat = torch.pow(qf, 2).sum(dim=1, keepdim=True).expand(m, n) + \
                  torch.pow(gf, 2).sum(dim=1, keepdim=True).expand(n, m).t()
        distmat.addmm_(qf, gf.t(), beta=1, alpha=-2)

        return distmat

    def get_gallery_size(self):
        return len(self.__gallery_image_paths)

    def get_similar_image_rank_list(self, query, max_length=10):
        """ get a rank list of similary images of input image.
        :param:
            query: image to match the gallery images.
        :return: a list of image path, the distance between query image and each in the list ascends.
        image path format like "/path/0001_c0_f0123456.jpg"
        """
        query_feature = self.__extract_single_feature(query)
        distmat = self.__compute_distance_matrix(query_feature, self.__gallery_image_features)
        rank_list = np.argsort(distmat.cpu(), axis=1)
        rank_list = rank_list.squeeze()
        return [self.__gallery_image_paths[index] for index in rank_list[:max_length]]

    def evaluate_performance_on_origin_dataset(self):
        """ to verify the implementation is correct
        """
        from src.utils.eval_reid import eval_func

        # extrack all query features
        query_loader = make_query_loader(self.__cfg)
        query_image_features = []
        query_image_paths = []
        q_pids = []
        q_camids = []
        with torch.no_grad():
            for batch in query_loader:
                data, pids, camids, img_paths = batch
                data = data.to(self.__cfg.MODEL.DEVICE)
                feat = self.__kernel(data)
                query_image_features.append(feat)
                query_image_paths += img_paths
                q_pids.extend(pids)
                q_camids.extend(camids)

            query_image_features = torch.cat(query_image_features, dim=0)
            query_image_features = torch.nn.functional.normalize(query_image_features, dim=1, p=2)

        # calculate distance matrix
        distmat = self.__compute_distance_matrix(query_image_features, self.__gallery_image_features)
        cmc, mAP = eval_func(distmat.cpu(), np.asarray(q_pids), np.asarray(self.__g_pids), np.asarray(q_camids), np.asarray(self.__g_camids))
        return cmc[0], mAP


from flask import (
    request,
)
from typing import Tuple
from ApplicationModels.RegisterWebUserForm import RegisterWebUserForm
from ApplicationModels.PageContents import PageContents, RegisterFormData

class ViewRegisterUseCase():
    def execute(
        self,
        page_contents: PageContents[RegisterFormData]
    ) -> Tuple[PageContents[RegisterFormData], RegisterWebUserForm]:
        page_contents.page_title = 'ユーザー登録'
        form = RegisterWebUserForm(request.form)

        form.name.data = page_contents.data.login_name
        form.email.data = page_contents.data.login_email

        return page_contents, form


import logging
import http.client as http_client
import os

SEARCH_API_URL_FORMAT = 'https://api.{env}.bookshareunifiedsearch.org/search'
INGESTION_URL_FORMAT = 'https://ingest.{env}.bookshareunifiedsearch.org/records'
DELETE_URL_FORMAT = 'https://ingest.{env}.bookshareunifiedsearch.org/recordDeletes'
GET_URL_FORMAT = 'https://ingest.{env}.bookshareunifiedsearch.org/recordGets'

SEARCH_API_URL = "unset"
INGESTION_URL = "unset"
DELETE_URL = "unset"
GET_URL = "unset"

def set_servers(env):
    global SEARCH_API_URL
    global INGESTION_URL
    global DELETE_URL
    global GET_URL
    if not env:
        env = 'qa'

    SEARCH_API_URL = SEARCH_API_URL_FORMAT.format(env=env)
    INGESTION_URL = INGESTION_URL_FORMAT.format(env=env)
    DELETE_URL = DELETE_URL_FORMAT.format(env=env)
    GET_URL = GET_URL_FORMAT.format(env=env)

    if env == 'prod':
        SEARCH_API_URL = SEARCH_API_URL.replace('.prod', '')
        INGESTION_URL = INGESTION_URL.replace('.prod', '')
        DELETE_URL = DELETE_URL.replace('.prod', '')
        GET_URL = GET_URL.replace('.prod', '')

EMMA_API_KEY = os.environ.get('EMMA_API_KEY', 'none')

http_client.HTTPConnection.debuglevel = 1
logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True


# coding: utf-8

# # Introduction to graphons using pygraphon

# In this notebook, we introduce the basics of graphons using the package pygraphon.

# In[1]:

from pygraphon.core.base import Graphon

get_ipython().magic(u'load_ext autoreload')
get_ipython().magic(u'autoreload 2')

get_ipython().magic(u'matplotlib inline')

# ## Graphons and exchangeable random graphs
# A graphon $W$ is a measurable function $W: [0,1]^2 \rightarrow [0,1]$ such that $W(x,y) = W(y,x)$, i.e., $W$ is a symmetric function.
#
# Consider the graphon given by $W(x,y) = \frac{1}{2}$. This is an Erd\"os-R\'enyi graph with probability $\frac{1}{2}$. We can express this in pygraphon by creating a Graphon object which takes in such a function:

# In[2]:

from pygraphon.core.graphons import er

er_quasi = er(0.5) # returns the function lambda x,y: 0.5
ER = Graphon(er_quasi)
ER.plot(colorbar=True)

# The cell above shows the input as the unit square $[0,1]^2$ and the output a value between $[0,1]$, where the color represents a this value on a grayscale gradient. Here white correponds to 0, and 1 corresponds to black. In an adjacency matrix, we just have black and white pixels (called pixel pictures).
#
# Given a graphon, we can sample an exchangeable graph $(G_{ij})_{i,j\in [n]}, (\text{where } [n]:=\{1,\ldots,n\}), n \in \mathbb{N} \cup \infty$ from it as follows:
# \begin{align}
# U_i &\sim_{\text{iid}} \text{Uniform}[0,1] \\
# G_{\{ij\}}  &\sim_{\text{ind}} \text{Bernoulli}(W(U_i, U_j))\\
# \end{align}
#
# In pygraphon, given the Graphon object, we can then sample (and plot) a finite graph from it as follows:

# In[3]:

er1 = ER.sample(10) # 10 vertices
er1.plot(colorbar=True)

er2 = ER.sample(100) # 100 vertices
er2.plot(colorbar=True)

er3 = ER.sample(1000) # 1000 vertices
er3.plot(colorbar=True)

# Notice that as $n$ gets bigger, each image looks more and more like one big "gray pixel" -- that's because the graphon is a graph limit. To see this more clearly, consider the following example of a graphon:
# $$ W(x,y) = \frac{(1-x) + (1-y)}{2}. $$
# We will refer this this throughout as the "gradient" graphon because it looks like this:

# In[4]:

from pygraphon.core.graphons import gradient

grad = Graphon(gradient)
grad.plot()

# This is more interesting than the ER example, which is just a single big "gray pixel" -- here we see a continuous gradient. Also note the symmetry in the function.
#
# Here are 3 random samples of size $n=10, 100, 1000$ from this gradient graphon.

# In[5]:

grad1 = grad.sample(10)
grad1.plot()

grad2 = grad.sample(100)
grad2.plot()

grad3 = grad.sample(1000)
grad3.plot()

# Notice the structure in these random samples already looks a little different from the ER graphon example.
# But to see the graph limit part of it, we are going to rearrange these by the uniform random variables that
# we sampled originally -- because these are exchangeable graphs, simultaneously rerranging the rows and columns
# of the adjacency matrix won't change the distribution of the underlying graph. We'll see that you can recover various structure by just reordering the rows and columns of the adjacency matrix.
#
# The idea here is that when we sort the graph by the $U_i$'s, we will get something that looks close to the original graphon, since the $U_i$'s tell us from which part of the graphon to sample.
#
# The rearranged samples, sorted by the $U_i$'s look like:

# In[6]:

grad1.sort_by_unifs().plot()
grad2.sort_by_unifs().plot()
grad3.sort_by_unifs().plot()

# For a comparison, resorting the ER samples from earlier by the $U_i$'s looks like this:

# In[7]:

er1.sort_by_unifs().plot()
er2.sort_by_unifs().plot()
er3.sort_by_unifs().plot()

# Aside: finite graphs can also be viewed as graphons by promoting them to step-functions.

# In[8]:

grad1.plot() # as a finitegraph
grad1_graphon = grad1.to_step_function() # promote finite graph to a step-function
grad1_graphon.plot() # as a graphon
grad1_graphon.sample(100).plot() # a sample from this step-function graphon
grad1_graphon.sample(100).sort_by_unifs().plot() # sorted by unifs -- looks like the original (but not quite)

# Step-function graphons don't have to be black and white (0-1 valued) -- they can take on any value. Block models are an example of this. In fact, many models for graphs based on stochastic block models give random graphons.
#
# Consider the nonparametric version of the stochastic block model (symmetric infinite relational model). Here we partition the vertices according to a Chinese Restaurant Process (or the interval $[0,1]$ according to a Dirichlet stick-breaking process),
# and then draw weights from a Beta distribution.
#
# Here are some realizations from the symmetric IRM along with samples from the graphons, sorted by increasing $U_i$:

# In[9]:

from pygraphon.core.graphons import IRM_symmetric

# realizations
irm1 = Graphon(IRM_symmetric(T=1000, alpha=5, a=1, b=1, seed=None))
irm2 = Graphon(IRM_symmetric(T=1000, alpha=5, a=1, b=1, seed=None))
irm3 = Graphon(IRM_symmetric(T=1000, alpha=5, a=1, b=1, seed=None))

# 200-vertex sample from 1st realization, sorted by unifs
irm1.plot()
irm1_samp = irm1.sample(300)
irm1_samp.sort_by_unifs().plot()

# 200-vertex sample from 2nd realization, sorted by unifs
irm2.plot()
irm2_samp = irm2.sample(300)
irm2_samp.sort_by_unifs().plot()

# 200-vertex sample from 3rd realization, sorted by unifs
irm3.plot()
irm3_samp = irm3.sample(300)
irm3_samp.sort_by_unifs().plot()

# We might also be interested in different sorting schemes, e.g., sorting the vertices by degree (the number of edges a vertex is connected to).

# In[10]:

grad1.sort_by_degree().plot()
grad2.sort_by_degree().plot()
grad3.sort_by_degree().plot()

# This looks a lot like the graphs that were reordered by $U_i$'s (but we can see it's not the same permutation from the $n=10$ example). That is, we get gradient structure upon resorting for both.
#
# But most exchangeable graphs are not degree-sortable, as it requires the graphon to be monotonizable (or at the very least partially monotonizable up to some partition).
#
# Consider the following 2 examples from block models. The first is the IRM sample and the second is a sample from a $2\times 2$ block model. In both, we can see that the pixel pictures of the sample resorted by the $U_i$'s is very different from the sample resorted by degree.

# In[11]:

# graphon
irm1.plot()
# sample sorted by unifs
irm1_samp.sort_by_unifs().plot()
# sample sorted by degree
irm1_samp.sort_by_degree().plot()

# In the degree-sorted picture, we can still see some block structure, but it's clearly not very close to the original.

# In[12]:

from pygraphon.core.graphons import SBM
sbm = Graphon(SBM(0.3, 0.8, 0.5))
sbm.plot()

sbm_samp = sbm.sample(300)
sbm_samp.plot()
sbm_samp.sort_by_unifs().plot()
sbm_samp.sort_by_degree().plot()

# In[13]:

sbm_samp.sort_by_degree().smooth().plot()

# Once again, the block structure in the picture of the sample sorted by $U_i$'s is super obvious and matches the original, whereas in the degree sorted sample, there is no visible block structure at all (as opposed to the IRM example).

# In[14]:

grad0 = grad.sample(300)
_= pylab.hist(grad0.graph.sum(0), bins=70, alpha=0.7)
_= pylab.hist(irm1_samp.graph.sum(0), bins=50, alpha=0.7)
_= pylab.hist(sbm_samp.graph.sum(0), bins=20, alpha=0.7)
pylab.legend(['gradient', 'IRM', 'SBM'])
pylab.title('Histogram of degrees')

# ## Graphon estimation basics

# We might want to estimate a graphon given a single graph sample. Two problems we might be interested in are:
#
# 1. Graphon function estimation - estimating the function (up to some measure-preserving transformation).
#
# 2. Graphon value estimation - estimating the array of probabilities (weighted graph) from the points in which the graph was sampled.
#
# We now show how you might obtain simple estimates for both of these problems. For the latter value estimation problem, we show how to evaluate an estimate using the mean square error.
#
# We first consider the gradient graphon. Previously, we saw that sorting the adjacency matrix by degree recovers gradient structure. One class of estimators focuses on sorting by degree and then smoothing the graph in some way to obtain an estimator -- this is a value estimator but can be turned into a function estimator by promoting it to a step-function.
#
# In this example, we first sort by degree and then smooth using a method called universal singular value thresholding (USVT) -- this method basically takes the SVD of the matrix, thresholds the singular values, and returns the resulting matrix with the thresholded singular values.

# In[15]:

grad3_sort = grad3.sort_by_degree() # sort by degree
grad3_sort.plot(title='Sorted sample')

est = grad3_sort.smooth() # smoothing using USVT, returns a GraphonValueEstimator object
est.plot(title='Value estimator')

est.to_graphon_function().plot(title='Function estimator') # aside: can turn the value estimator into a GraphonFunctionEstimator

grad.plot(title='Gradient graphon')

# In[16]:

est = grad3_sort.smooth() # smoothing using USVT, returns a GraphonValueEstimator object
est.plot()

# To compute the mean squared error (MSE), we consider the weighed graph $M_{ij} := W(U_i, U_j)$. The mean squared error is given by:
# $$\frac{1}{n^2}\sum_{i,j} \left(M_{ij} - \widehat{M}_{ij}\right)^2$$
#
# Here $(\widehat{M}_{ij})$ is the value estimator where the array is ordered according the order the vertices in the graph $(G_{ij})$ were sampled. The first plot below shows the weighted graph $(M_{ij})$ and the second plot shows the graph reordered by the $U_i$'s.

# In[17]:

grad3.get_weighted_graph().plot(title='Weighted graph $(M_{ij})$')
gsorted = grad3.get_weighted_graph().sort_by_unifs()
gsorted.plot(title='Weighted graph, ordered by $U_i$\'s')
#est.compute_MSE(grad3.get_weighted_graph(), grad3_sort.permutation) # MSE

# For the IRM example, we consider an estimator formed from sorting by degree and then histogramming the vertices. The histogram estimator is given by specifiying a number of bins $m$, where each bin is equally sized.
#
# This type of histogram estimator returns a step-function, or function estimate, but from it we can get a value estimator by taking the points in the function that correspond to the sampled graph.

# In[18]:

#irm3.plot()
samp = irm3_samp
irm_sorted = samp.sort_by_degree()
irm_sorted.plot(title='Sorted sample')

hist0 = irm_sorted.hist(3)
mse0 = hist0.compute_MSE(samp.get_weighted_graph(), irm_sorted.permutation)
hist0.plot(title='3 bins, MSE: %.4f' % mse0)

hist1 = irm_sorted.hist(10)
mse1 = hist1.compute_MSE(samp.get_weighted_graph(), irm_sorted.permutation)
hist1.plot(title='10 bins, MSE: %.4f' % mse1)

hist2 = irm_sorted.hist(30)
mse2 = hist2.compute_MSE(samp.get_weighted_graph(), irm_sorted.permutation)
hist2.plot(title='30 bins, MSE: %.4f' % mse2)

hist3 = irm_sorted.hist(50)
mse3 = hist3.compute_MSE(samp.get_weighted_graph(), irm_sorted.permutation)
hist3.plot(title='50 bins, MSE: %.4f' % mse3)

# This type of histogram estimator is one of the most basic ones you can specify. One open question is how we might choose the partition (e.g., sort it according to some other scheme rather than degree, or spacing the histogram into less-equitable sizes).

# In[ ]:

# In[19]:

from pygraphon.core.graphons import SBM
sbm = Graphon(SBM(0.3, 0.8, 0.3))
sbm.plot()

sbm_samp = sbm.sample(300)
sbm_samp.plot()
sbm_samp.sort_by_unifs().plot()
sbm_samp.sort_by_degree().plot()

sbm_sorted = sbm_samp.sort_by_degree()

hist0 = sbm_sorted.hist(2)
mse0 = hist0.compute_MSE(sbm_samp.get_weighted_graph(), sbm_sorted.permutation)
hist0.plot()#title=2 bins, MSE: %.4f' % mse0)

hist1 = sbm_sorted.hist(3)
mse1 = hist1.compute_MSE(sbm_samp.get_weighted_graph(), sbm_sorted.permutation)
hist1.plot()#title='4 bins, MSE: %.4f' % mse1)

hist2 = sbm_sorted.hist(4)
mse2 = hist2.compute_MSE(sbm_samp.get_weighted_graph(), sbm_sorted.permutation)
hist2.plot()#title='5 bins, MSE: %.4f' % mse2)

hist3 = sbm_sorted.hist(5)
mse3 = hist3.compute_MSE(sbm_samp.get_weighted_graph(), sbm_sorted.permutation)
hist3.plot()#title='5 bins, MSE: %.4f' % mse3)

# In[20]:

sbm_samp.sort_by_degree().smooth().plot()

# In[21]:

tri_sort = sbm_samp.sort_by_triangle()
tri_sort.plot()

# In[ ]:

# In[22]:

tri_sort.smooth().plot()

# In[23]:

sbm = Graphon(SBM(0.3, 0.8, 0.5))
sbm.plot()
sbm_samp = sbm.sample(300)
sbm_samp.plot()
sbm_samp.sort_by_unifs().plot()
sbm_samp.sort_by_degree().plot()
sbm_samp.sort_by_triangle().plot()
sbm_samp.sort_by_gray().plot()

# In[24]:

sbm_samp.sort_by_degree().smooth().plot()
sbm_samp.sort_by_triangle().smooth().plot()

# In[ ]:

# In[25]:

grad_samp = grad.sample(200)

# In[26]:

grad_samp.sort_by_degree().smooth().plot()
grad_samp.sort_by_triangle().smooth().plot()

# In[27]:

grad_samp.sort_by_unifs().plot()
grad_samp.sort_by_degree().plot()
grad_samp.sort_by_triangle().plot()

# In[28]:

# graphon
irm1.plot()

irm2_samp = irm1.sample(100)
# sample sorted by unifs
irm2_samp.sort_by_unifs().plot()
# sample sorted by degree
irm_deg = irm2_samp.sort_by_degree()
irm_deg.plot()
#irm_deg.smooth().plot()

irm_tri = irm2_samp.sort_by_triangle()
irm_tri.plot()
#irm_tri.smooth().plot()

# In[29]:

irm2_samp.sort_by_gray().plot()

# In[30]:

irm2_samp.sort_by_gray().hist(8).plot()

# In[ ]:


import numpy as np
from pydub import AudioSegment

def encode_audio_to_array(audio_file, output_file):
    try:
        audio = AudioSegment.from_file(audio_file)
        samples = np.array(audio.get_array_of_samples())
        encoded_array = ','.join(map(str, samples))
        with open(output_file, 'w') as outfile:
            outfile.write(encoded_array)
        print(f"Encoded audio array exported to {output_file}!")
    except FileNotFoundError:
        print("File not found!")

# Provide the path to your MP3 audio file
audio_file_path = 'C:/Users/GEORGIE/Downloads/converted2.mp3'
# Provide the desired output file path
output_file_path = 'C:/Users/GEORGIE/Downloads/output.txt'

encode_audio_to_array(audio_file_path, output_file_path)


import random
from db_conn import get_db_connection
from subprocess import STARTF_USESTDHANDLES
from flask import Blueprint, request

from users import get_single_user

quality = Blueprint('quality', __name__)

@quality.route('/quality', methods=['GET'])
def get_quality_info():
    conn = get_db_connection()
    info = conn.execute('SELECT dispenser_quality, filter_quality, water_quality FROM quality ORDER BY id DESC').fetchone()
    result = dict(info)
    conn.close()
    return result

@quality.route('/quality', methods=['POST'])
def set_quality_info():
    conn = get_db_connection()
    quality_info = {
        "water_quality": random.random(),
        "filter_quality": random.random(),
        "dispenser_quality": random.random()
    }
    conn.execute("INSERT INTO quality(water_quality,filter_quality,dispenser_quality) VALUES (?, ?, ?)",
        (quality_info["water_quality"], quality_info['filter_quality'], quality_info['dispenser_quality']))
    conn.commit()
    conn.close()
    return {"message":"Quality inserted successfully!"}


from msilib import sequence
import os
import numpy as np
import pandas as pd
import tensorflow as tf
import matplotlib.pyplot as plt
from datetime import date
from random import randint
from numpy.typing import ArrayLike
from pandas import DataFrame
from typing import Tuple
from typing import List
from typing import Union
from tensorflow import Tensor
from tensorflow.python.keras.models import Model
from tensorflow.python.keras.losses import MeanSquaredError
from tensorflow.python.keras.metrics import MeanAbsoluteError
from tensorflow.python.keras.callbacks import EarlyStopping

from sqlalchemy import create_engine
from sqlalchemy import MetaData
"""
Tensorflow Logging:
    0 = all messages printed (default)
    1 = INFO messages are not printed
    2 = INFO and WARNING messages are not printed
    3 = INFO, WARNING, and ERROR messages are not printed
"""
os.environ["TF_CPP_MIN_LOG_LEVEL"] = '1'

config = {
    "input_width": 30,
    "label_width": 5,
    "offset": 5,
    "num_features": None,
    "label_columns": ["close"],
    "train_split": 0.7,
    "val_split": 0.8,
    "batch_size": 32,
    "epochs": 36,
    "patience": 2,
    "loss_func": MeanSquaredError(),
    "optmizer": tf.optimizers.Adam(),
    "metrics": [MeanAbsoluteError()],
    "callbacks": [EarlyStopping()]
}

class Sequence(object):
    """
    Class to hold raw data, normailizd data, and train/val/test split
    for each security
    """

    def __init__(self, sym: str, timeseries: DataFrame) -> None:
        # Flip the dataframe so start index is oldest date
        timeseries = timeseries.iloc[::-1]

        # Record symbol and original dataframe
        self.sym = sym
        self.timeseries_df: DataFrame = timeseries

        # Column headers and Date before stripping them
        self.n_rows, self.n_columns = self.timeseries_df.shape
        self.dates: List[date] = [timestamp.date() for timestamp in timeseries.index.to_list()]

        self.columns: List[str] = timeseries.columns.to_list()
        self.column_indices = {col:i for i, col in enumerate(self.columns)}

        train_val_index = int(self.n_rows*config["train_split"])
        val_test_index = int(self.n_rows*config["val_split"])

        # Slices for easily indexing datasets
        self.train_slice = slice(0, train_val_index)
        self.val_slice = slice(train_val_index, val_test_index)
        self.test_slice = slice(val_test_index, None)

        config["num_features"] = self.n_columns

        # Strip the features into 2D Arrays
        self.timeseries: ArrayLike = timeseries.to_numpy()
        self.train: ArrayLike = None
        self.val: ArrayLike = None
        self.test: ArrayLike = None

        # Save the corresponding dates in lists
        self.train_dates: List[date] = None
        self.val_dates: List[date] = None
        self.test_dates: List[date] = None

        # Split and normalize the data to feed into the model
        self.__split()
        self.__normalize()

    def __split(self) -> None:
        """ Split self.timeseries and self.dates into appopiate train, val, test sets"""
        self.train = self.timeseries[self.train_slice]
        self.train_dates = self.dates[self.train_slice]

        self.val = self.timeseries[self.val_slice]
        self.val_dates = self.dates[self.val_slice]

        self.test = self.timeseries[self.test_slice]
        self.test_dates = self.dates[self.test_slice]

        # Ensure that no datapoints were loss
        assert len(self.train) + len(self.val) + len(self.test) == len(self.timeseries)
        assert len(self.train_dates) + len(self.val_dates) + len(self.test_dates) == len(self.dates)

    def __normalize(self) -> None:
        """Normalize the data using the training metrics"""
        self.mean = self.train.mean(axis=0)
        self.std = self.train.std(axis=0)

        self.train = (self.train - self.mean) / self.std
        self.val = (self.val - self.mean) / self.std
        self.test = (self.test - self.mean) / self.std

        # Ensure each feature has a mean value of 0
        assert any(np.around(self.train.mean(axis=0), decimals=5)) == False

    def invert(self, x: ArrayLike) -> ArrayLike:
        """Reverses the normalization for readiability"""
        return (x * self.std) + self.mean

    def __getitem__(self, i: Union[int, slice]) -> ArrayLike:
        """ Dunder to retrieve a datum """
        return self.timeseries[i]

    def __repr__(self) -> str:
        """ Dunder for represetnation """
        return (f'TimeSeries Data - Train/Val/Test: {self.train.shape}/{self.val.shape}/{self.test.shape}')

    def get_splits(self) -> Tuple[ArrayLike, ArrayLike, ArrayLike]:
        """ Get method for train, val, test arrays """
        return self.train, self.val, self.test

    def plot(self) -> None:
        """ Plot the train/val/test splits normalized for closing price """
        close_index = self.column_indices['close']

        plt.figure(figsize=(12, 8))
        plt.plot(self.train_dates, self.train[:, close_index], c='#ff0000', label='train')
        plt.plot(self.val_dates, self.val[:, close_index], c='#00ff00', label='val')
        plt.plot(self.test_dates, self.test[:, close_index], c='#0000ff', label='test')

        plt.title(self.sym)
        plt.ylabel('Close [Normed]')
        plt.xlabel('Date')
        plt.legend()
        plt.show()

class WindowGenerator(object):
    """
    Class to handle the "windowing" of a given sequence

    LSTM uses previous values to predict the next value(s), so we need to have
    inputs of previous values and labels of current values.

    If given the params of:
        input_width = 3
        label_width = 1
        offset = 1
        series = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    Then we will want our features and labels to look like:
        x = [[1, 2, 3],
             [2, 3, 4],
             [3, 4, 5],
             [4, 5, 6],
             [5, 6, 7],
             [6, 7, 8],
             [7, 8, 9]
            ]

        y = [4, 5, 6, 7, 8, 9, 10]
    """

    def __init__(self, seq: Sequence) -> None:
        """
        inputs_width = the window size of the input(s)
        label_width = the window size of label(s)
        offset = the timesteps betwen input_width and the end of label_width
        """

        # Record the sequence
        self.sequence = seq

        # Record indices for column lookups
        self.label_columns = config["label_columns"]
        self.label_columns_indices = {name:i for i, name in enumerate(self.label_columns)}
        self.column_indices = self.sequence.column_indices

        # Dimensions for windowing will want final shape of the window, inputs, and labels to be (batch, time, features)
        self.inputs_width = config["input_width"]
        self.labels_width = config["label_width"]
        self.offset = config["offset"]
        self.total_window_size = self.inputs_width + self.offset

        # Determine the inputs indices
        self.inputs_slice = slice(0, self.inputs_width)
        self.inputs_indices = np.arange(self.total_window_size)[self.inputs_slice]

        # Determine indices of the labels
        self.labels_slice = slice(self.total_window_size - self.labels_width, None)
        self.labels_indices = np.arange(self.total_window_size)[self.labels_slice]

    def __split_window(self, features: Tensor) -> Tensor:
        """
        Apply "windowing" to a given tensor
        """

        inputs: Tensor = features[:, self.inputs_slice, :]
        labels: Tensor = features[:, self.labels_slice, :]
        labels: Tensor = tf.stack([labels[:, :, self.sequence.column_indices[name]] for name in self.label_columns],
                        axis=-1)

        inputs.set_shape([None, self.inputs_width, None])
        labels.set_shape([None, self.labels_width, None])

        return inputs, labels

    def __make_dataset(self, data: ArrayLike) -> tf.data.Dataset:
        ds: tf.data.Dataset = tf.keras.utils.timeseries_dataset_from_array(
                                            data=data,
                                            targets=None,
                                            sequence_length=self.total_window_size,
                                            sequence_stride=1,
                                            shuffle=True,
                                            batch_size=config["batch_size"],
                                        )

        return ds.map(self.__split_window)

    def plot_window(self, column: str = None, n: int=3) -> None:
        inputs, labels = next(iter(self.get_train_dataset()))
        plt.figure(figsize=(12, 8))

        if not column:
            column = self.label_columns[0]

        input_column_index = self.column_indices[column]
        label_column_index = self.label_columns_indices[column]

        n = min(n, len(inputs))
        for i in range(n):
            plt.subplot(n, 1, i+1)
            plt.ylabel(f'{column} [normed]')
            plt.plot(self.inputs_indices, inputs[i, :, input_column_index],
                     label='Inputs', marker='.', zorder=-10)

            plt.scatter(self.labels_indices, labels[i, :, label_column_index],
                edgecolors='k', label='Labels', c='#2ca02c', s=64)

            if i == 0:
                plt.legend()

        plt.xlabel('Time Step')
        plt.show()

    def plot_predictions(self, inputs: ArrayLike, labels: ArrayLike,
                         predictions: ArrayLike, column: str = None) -> None:

        # Default column to plot if not specified
        if not column:
            column = config["label_columns"][0]

        # Convert 3D to 2D
        inputs, labels, predictions = inputs[0], labels[0], predictions[0]

        # Inverse the normalziation
        inputs = self.sequence.invert(inputs)
        labels = self.sequence.invert(labels)
        predictions = self.sequence.invert(predictions)

        # Grab input column index and label column index
        input_col_index = self.column_indices[column]
        label_col_index = self.label_columns_indices[column]

        # Grab the corresponding dates
        input_dates = self.sequence.train_dates + self.sequence.val_dates
        label_dates = self.sequence.test_dates

        # Shape the dates
        input_dates = input_dates[-1*len(inputs):]
        label_dates = label_dates[:len(labels)]

        # Ensure the correct shapes
        assert len(input_dates) == len(inputs)
        assert len(label_dates) == len(labels)

        # Plot hte results
        plt.figure(figsize=(12, 8))
        plt.plot(input_dates, inputs[:, input_col_index],
                    label='Inputs', marker='.', zorder=-10)
        plt.scatter(label_dates, labels[:, label_col_index], edgecolors='k',
                    label='Labels', c='#2ca02c', s=64)
        plt.scatter(label_dates, predictions[:, label_col_index], edgecolors='k',
                    marker='X', label='Predictions', c='#ff7f0e', s=64)

        plt.title(self.sequence.sym)
        plt.ylabel(f'{column}')
        plt.xlabel('Dates')
        plt.legend()
        plt.show()
        return

    def get_train_dataset(self) -> tf.data.Dataset:
        return self.__make_dataset(self.sequence.train)

    def get_val_dataset(self) -> tf.data.Dataset:
        return self.__make_dataset(self.sequence.val)

    def get_test_dataset(self) -> tf.data.Dataset:
        return self.__make_dataset(self.sequence.test)

    def __repr__(self) -> str:
        return (f'\nTotal window size: {self.total_window_size}\n'
                f'Input indices: {self.inputs_indices}\n'
                f'Label indices: {self.labels_indices}\n'
                f'Label column names: {self.label_columns}\n')

def load_data() -> List[Sequence]:
    """Function to load local stored data"""

    engine = create_engine('sqlite:///../data/test.db')

    metadata = MetaData(engine)
    metadata.reflect(engine)
    syms = list(metadata.tables.keys())
    data = []
    for sym in syms:
        df = pd.read_sql_table(sym, engine.connect(), index_col='date', parse_dates=['date'])
        data.append(Sequence(sym, df))

    assert len(data) == len(syms)
    return data

if __name__ == "__main__":
    data = load_data()
    seq = data[randint(0, len(data) - 1)]
    print(f'Random sequnce selected for ticker={seq.sym} \n')
    print(f'{seq} \n')
    seq.plot()

    window = WindowGenerator(seq)
    print(f'{window} \n')

    train_ds = window.get_test_dataset()
    for inputs, labels in train_ds.take(1):
        print("Dataset Shape: ")
        print(f'\tInputs shape (batch, steps, features): {inputs.shape}')
        print(f'\tLabels shape (batch, steps, features): {labels.shape}\n')

    window.plot_window()


import pygame
from pygame.locals import *
from sys import exit
from random import randint

pygame.init()

red = (255, 0, 0)
black = (0, 0, 0)
white = (255, 255, 255)
green = (10, 10, 255)

width = 640
height = 480

x_cobra = int(width/2)
y_cobra = int(height/2)

vel = 10
x_control = vel
y_control = 0

xc = randint(40, 600)
yc = randint(50, 430)

pontos = 0
font = pygame.font.SysFont('arial', 40, bold=True)

screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Snake')
clock = pygame.time.Clock()

listC = []
comprimentoIni = 5
gameOver= False

def upCobra(listC):
    for XeY in listC:
        pygame.draw.rect(screen, green, (XeY[0], XeY[1], 20, 20))

def reset():
    global pontos, comprimentoIni, x_cobra, y_cobra, listC, listCab, xc, yc, gameOver
    pontos = 0
    comprimentoIni = 5
    x_cobra = int(width/2)
    y_cobra = int(height/2)
    listC = []
    listCab = []
    xc = randint(40, 600)
    yc = randint(50, 430)
    gameOver = False

while True:
    clock.tick(30)
    screen.fill((255, 255, 255))
    mens = f'Pontos: {pontos}'
    txtF = font.render(mens, True, black)

    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            exit()

        if event.type == KEYDOWN:
            if event.key == K_a:
                if x_control == vel:
                    pass
                else:
                    x_control = -vel
                    y_control = 0
            if event.key == K_d:
                if x_control == -vel:
                    pass
                else:
                    x_control = vel
                    y_control = 0
            if event.key == K_w:
                if y_control == vel:
                    pass
                else:
                    y_control = -vel
                    x_control = 0
            if event.key == K_s:
                if y_control == -vel:
                    pass
                else:
                    y_control = vel
                    x_control = 0

        x_cobra += x_control
        y_cobra += y_control

        cobra = pygame.draw.rect(screen, (green), (x_cobra, y_cobra, 20, 20))
        com = pygame.draw.rect(screen, red, (xc, yc, 20, 20))

        if cobra.colliderect(com):
            xc = randint(40, 600)
            yc = randint(50, 430)
            pontos += 1
            comprimentoIni += 1

        listCab = []
        listCab.append(x_cobra)
        listCab.append(y_cobra)

        listC.append(listCab)

        if listC.count(listCab) > 1:
            fonte = pygame.font.SysFont('arial', 20, True, False)
            mens = 'Game over! Precione R para jogar novamente'
            textF = fonte.render(mens, True, white)
            retTxt = textF.get_rect()
            gameOver = True
            while gameOver:
                screen.fill(white)
                for event in pygame.event.get():
                    if event.type == QUIT:
                        pygame.quit()
                        exit()
                    if event.type == KEYDOWN:
                        if event.key == K_r:
                            reset()
                retTxt.center = (width/2, height/2)
                screen.blit(txtF, retTxt)
                pygame.display.update()

        if x_cobra > width:
            x_cobra = 0
        if x_cobra < 0:
            x_cobra = width
        if y_cobra < 0:
            y_cobra = height
        if y_cobra > height:
            y_cobra = 0

        if len(listC) > comprimentoIni:
            del listC[0]

        upCobra(listC)

        screen.blit(txtF, (450, 40))

        pygame.display.update()


# python soln.py  0.09s user 0.02s system 70% cpu 0.161 total

import itertools

# ---------------- Class Setup ----------------------

class Octopus:
    def __init__(self, level):
        self.level = level
        self.flashed_this_step = False

    def __repr__(self):
        return f"{str(self.level):>2}"

class OctoGrid:
    def __init__(self, grid):
        self.grid = grid
        self.height = len(self.grid)
        self.width = len(self.grid[0])
        self.addresses = [(i, j) for i in range(self.height) for j in range(self.width)]
        self.flash_count = 0
        self.step_num = 0

    def __repr__(self):
        msg = f"Step Count: {self.step_num}\nFlash Count: {self.flash_count}\nGrid:\n"
        for i in self.grid:
            msg = msg + str(i) + "\n"
        return msg

    def get_adjs(self, coord):
        adjs = [
            x for x in list(itertools.product([1, 0, -1], [1, 0, -1])) if x != (0, 0)
        ]
        return [
            (coord[0] + adj[0], coord[1] + adj[1])
            for adj in adjs
            if 0 <= coord[0] + adj[0] < self.height
            and 0 <= coord[1] + adj[1] < self.width
        ]

    def get_flash_octs(self):
        return [
            (i, j)
            for (i, j) in self.addresses
            if self.grid[i][j].level > 9 and not self.grid[i][j].flashed_this_step
        ]

    def get_flashed_octs(self):
        return [
            (i, j) for (i, j) in self.addresses if self.grid[i][j].flashed_this_step
        ]

    def flash(self, coord):
        adjs = self.get_adjs(coord)
        for i, j in adjs:
            self.grid[i][j].level += 1

        self.grid[coord[0]][coord[1]].flashed_this_step = True
        self.flash_count += 1

    def step(self):
        # increment each octopus
        for i, j in self.addresses:
            grid[i][j].level += 1

        # flash all octopuses > 9 that haven't flashed - keep doing this
        flash_oct_addrs = self.get_flash_octs()
        while len(flash_oct_addrs) > 0:
            for i, j in flash_oct_addrs:
                self.flash((i, j))
            flash_oct_addrs = self.get_flash_octs()

        # reset flashed octs to 0 and reset all flash indicators
        flashed_octs = self.get_flashed_octs()
        for i, j in flashed_octs:
            self.grid[i][j].level = 0
            self.grid[i][j].flashed_this_step = False
        self.step_num += 1

    def multi_step(self, step_count):
        for i in range(step_count):
            self.step()

    def all_octs_just_flashed(self):
        return all(self.grid[i][j].level == 0 for (i, j) in self.addresses)

# -------------------- P1 -----------------------------

with open("input.txt") as in_file:
    grid = [[Octopus(int(o)) for o in line.strip()] for line in in_file.readlines()]

octo_grid = OctoGrid(grid)
octo_grid.multi_step(100)

print(f"P1 Soln: {octo_grid.flash_count}")

# -------------------- P2 -----------------------------

while not octo_grid.all_octs_just_flashed():
    octo_grid.step()

print(f"P2 Soln: {octo_grid.step_num}")


# import the opencv library
import cv2
import os
from time import time
import numpy as np
from buffer import Buffer
from face_detect import FaceDetection, pixelate

once = True

tracker = cv2.TrackerMIL_create()

backtracker = cv2.TrackerMIL_create()
detector = FaceDetection()

frame_buffer = Buffer(30)
my_img_1 = np.zeros((1280, 720, 1), dtype="uint8")

filename = "output.mp4"
frames_per_second = 30.0
res = "720p"

def change_res(cap, width, height):
    cap.set(3, width)
    cap.set(4, height)

# Standard Video Dimensions Sizes
STD_DIMENSIONS = {
    "480p": (640, 480),
    "720p": (1280, 720),
    "1080p": (1920, 1080),
    "4k": (3840, 2160),
}

def get_dims(cap, res="1080p"):
    width, height = STD_DIMENSIONS["480p"]
    # if res in STD_DIMENSIONS:
    #     width, height = STD_DIMENSIONS[res]
    ## change the current caputre device
    ## to the resulting resolution
    change_res(cap, width, height)
    return width, height

VIDEO_TYPE = {
    "avi": cv2.VideoWriter_fourcc(*"XVID"),
    "mp4": cv2.VideoWriter_fourcc(*"mp4v"),
}

def get_video_type(filename):
    filename, ext = os.path.splitext(filename)
    if ext in VIDEO_TYPE:
        return VIDEO_TYPE[ext]
    return VIDEO_TYPE["mp4"]

# define a video capture object
# vid = cv2.VideoCapture(0, cv2.CAP_DSHOW)
vid = cv2.VideoCapture("input.mp4")
out = cv2.VideoWriter(filename, get_video_type(filename), 25, get_dims(vid, res))
start_time = time()
print_delay = True
detect = True
bbox = None
write_frame = None

input_frames = []
output_frames = []

while True:
    ret, frame = vid.read()
    if not ret:
        break
    input_frames.append(frame)
    out.write(frame)
vid.release()

counter = 0

while True:
    try:
        frame = input_frames.pop(0)
    except IndexError:
        frame = False

    if not isinstance(frame, bool):
        frame, detect, bbox = detector.detect_or_track(frame, detect, tracker)
        if once and not detect:
            once = False
            backtracker.init(frame, bbox)
            frames = frame_buffer.get_buffer_frames()
            for i in range(len(frames) - 2, 0, -1):
                cur_frame = frames[i]
                status, bbox = backtracker.update(cur_frame)
                if status:
                    x, y, w, h = bbox
                    cur_frame = pixelate(cur_frame, x, y, w, h)
                    cv2.rectangle(cur_frame, (x, y), (x + w, y + h), (0, 0, 255), 2)
                    frame_buffer.update_frame(cur_frame, i)
        status = frame_buffer.add_frames(frame)

    ret_frame = frame_buffer.get_frames()
    if isinstance(ret_frame, bool):
        if not ret_frame and isinstance(frame, bool):
            break
        if not ret_frame:
            write_frame = my_img_1
    else:
        write_frame = ret_frame
        if print_delay:
            frame_start_time = time()
            print("Frame Lag ", frame_start_time - start_time)
            print_delay = False

    cv2.imshow("frame", write_frame)
    output_frames.append(write_frame)
    counter += 1
    if cv2.waitKey(1) & 0xFF == ord("q"):
        break

for frame in output_frames:
    out.write(frame)

out.release()
# Destroy all the windows
cv2.destroyAllWindows()


import os
import json
import jieba.analyse
import threading
from django.shortcuts import render
from django.http import HttpResponse, JsonResponse, QueryDict
from .models import Post, Comment, Photo, Favor, TextKey
from user.models import User
from django.views.decorators.csrf import csrf_exempt, csrf_protect

gen_response = {
    'success': {
        "code": 200,
        "data": {
            "msg": "success"
        }
    },
    'method_err': {
        "code": 600,
        "data": {
            "msg": "wrong method"
        }
    },
    'param_err': {
        "code": 700,
        "data": {
            "msg": "wrong parameter"
        }
    },
    'post_not_exist': {
        "code": 300,
        "data": {
            "msg": "post not exists"
        }
    },
    'user_not_exist': {
        "code": 300,
        "data": {
            "msg": "user not exists"
        }
    },
    'user_error': {
        "code": 400,
        "data": {
            "msg": "not authorized"
        }
    }
}

def demo(request):
    return HttpResponse('Post Response')

def posts(request):
#动态列表
    print('server receive {} {}'.format(request.method, request.get_full_path()))

    if request.method == 'GET':
    #请求动态列表，GET /posts/?limit&start

        # 检查登陆状态
        if not request.user.is_authenticated:
            return JsonResponse(gen_response["user_error"])

        try:
            num = int(request.GET.get('limit', default=10)) #请求动态数量
            start = int(request.GET.get('start', default=0)) #起始动态id
        except:
            return JsonResponse(gen_response['param_err'])

        post_list = Post.objects.order_by('-post_id')[start:start+num] #获取最新动态

        posts = []
        for item in post_list:

            # 加载图片
            multimedia = []
            if item.is_video == False:
                for photo in Photo.objects.filter(post=item):
                    multimedia.append(photo.photo)

            # 判断是否给自己点赞
            user = User.objects.get(id=request.user.id)
            if Favor.objects.filter(post=item).filter(user=user):
                self_favor = 1
            else:
                self_favor = 0

            # 一条摘要动态的数据结构
            publisher_info = {
                'userID': item.publisher.id,
                'username': item.publisher.username,
                'avatar': item.publisher.avatar
            }
            favorcnt = Favor.objects.filter(post=item).count()
            post_info =  {
                'postID': item.post_id,
                'publisher': publisher_info,
                'time': int(item.time.timestamp()*1000),
                'text': item.text,
                'multimediaContent': multimedia,
                'favor': {
                    'self': self_favor,
                    'favorCnt': favorcnt
                }
            }
            posts.append(post_info)

        response = {
            "code": 200,
            "data": {
                "downloadCount": len(posts),
                "posts": posts
            }
        }
        return JsonResponse(response)
    else:
        return JsonResponse(gen_response['method_err'])

@csrf_exempt
def post(request):
#动态获取、添加、删除
    if request.method == 'GET':
    #请求动态，GET /post/?postID&comments
        print('server receive GET', request.get_full_path())

        # 检查登陆状态
        if not request.user.is_authenticated:
            return JsonResponse(gen_response["user_error"])

        try:
            post_id = int(request.GET.get('postID')) #动态id
            comments_num = int(request.GET.get('comments', default=10)) #评论数量
        except:
            return JsonResponse(gen_response['param_err'])

        # 获取动态数据
        try:
            post = Post.objects.get(post_id=post_id)
        except:
            return JsonResponse(gen_response['post_not_exist'])

        # 获取评论区列表
        total_cnt = Comment.objects.filter(post=post).count()
        comments = Comment.objects.filter(post=post)[:comments_num]
        comment_list = []
        for comment in comments:

            user = {
                'userID': comment.user.id,
                'username': comment.user.username,
                'avatar': comment.user.avatar
            }
            comment_list.append({
                'commentID': comment.id,
                'user': user,
                'time': int(comment.time.timestamp()*1000),
                'text': comment.text
            })
        if len(comment_list):
            _start = comment_list[0]['commentID']
        else:
            _start = -1
        comment_list_info = {
            'postID': post.post_id,
            'totalCount': total_cnt,
            'downloadCount': len(comment_list),
            'start': _start,
            'comments': comment_list
        }

        publisher_info = {
            'userID': post.publisher.id,
            'username': post.publisher.username,
            'avatar': post.publisher.avatar
        }

        # 加载多媒体内容
        multimedia = []
        if post.is_video == False:
            photos = Photo.objects.filter(post=post)
            for photo_info in photos:
                multimedia.append(photo_info.photo)
        elif post.is_video == True:
            multimedia.append(post.video)

        # 判断是否给自己点赞
        user = User.objects.get(id=request.user.id)
        if Favor.objects.filter(post=post).filter(user=user):
            self_favor = 1
        else:
            self_favor = 0

        favorcnt = Favor.objects.filter(post=post).count()
        post_info =  {
            'postID': post.post_id,
            'publisher': publisher_info,
            'time': int(post.time.timestamp()*1000),
            'text': post.text,
            'isVideo': post.is_video,
            'multimediaContent': multimedia,
            'commentList': comment_list_info,
            'favor': {
                'self': self_favor,
                'favorCnt': favorcnt
            }
        }
        response = {
            "code": 200,
            "data": {
                "downloadCount": 1,
                "post": post_info
            }
        }
        return JsonResponse(response)

    if request.method == 'POST':
        # 发布动态, POST /post/

        # 检查登陆状态
        if not request.user.is_authenticated:
            return JsonResponse(gen_response["user_error"])

        text = request.POST.get('text')
        isVideo = request.POST.get('isVideo')
        #print('isVideo', repr(isVideo))
        multimediaContent = request.POST.getlist('multimediaContent')

        if isVideo == '1':
            isVideo = True
        elif isVideo == '0':
            isVideo = False
        else:
            return JsonResponse(gen_response['param_err'])

        # 分析参数
        if text is None and len(multimediaContent) == 0:
            return JsonResponse(gen_response['param_err'])
        if isVideo and len(multimediaContent) == 0:
            return JsonResponse(gen_response['param_err'])

        publisher = User.objects.get(id=request.user.id)

        # 创建数据库动态数据
        post = Post()
        post.publisher = publisher
        post.text = text if not text is None else ""
        post.is_video = isVideo
        if post.is_video:
            post.video = multimediaContent[0]
        post.save()

        # 存储图片
        if isVideo == False:
            for photo_path in multimediaContent:
                photo = Photo()
                photo.photo = photo_path
                photo.post = post
                photo.save()

        # 创建关键词数据
        if not text is None:
            keywords = jieba.analyse.extract_tags(text, topK=10)
            for key in keywords:
                TextKey(key=key, post=post).save()

        response = {
            "code": 200,
            "data": {
                "postID": post.post_id,
                "time": int(post.time.timestamp()*1000)
            }
        }
        return JsonResponse(response)

    if request.method == 'DELETE':
    # 删除动态, DELETE /post/?postID=123
        print('server receive DELETE', request.get_full_path())

        # 检查登陆状态
        if not request.user.is_authenticated:
            return JsonResponse(gen_response["user_error"])

        DELETE = json.loads(request.body)
        try:
            post_id = int(DELETE.get('postID'))
        except:
            return JsonResponse(gen_response['param_err'])

        # 不存在id
        try:
            post = Post.objects.get(post_id=post_id)
        except:
            return JsonResponse(gen_response['post_not_exist'])

        try:
            post.delete()
        except:
            response = {
                "code": 300,
                "data": {
                    "msg": "delete fail"
                }
            }
            return JsonResponse(response)

        response = {
            "code": 200,
            "data": {
                "msg": "delete post successfully"
            }
        }
        return JsonResponse(response)

    response = gen_response['method_err']
    return JsonResponse(response)

def search(request):
# 搜索动态
    if request.method == 'GET':
    # 搜索动态, GET /posts/search/?userID=123&keyword=大威
        print('server receive GET', request.get_full_path())

        # 检查登陆状态
        if not request.user.is_authenticated:
            return JsonResponse(gen_response["user_error"])

        try:
            user_id = int(request.GET.get('userID', default=-1))
            keyword = request.GET.get('keyword', default=None)
            if user_id < 0 and keyword==None:
                return JsonResponse(gen_response['param_err'])
        except:
            return JsonResponse(gen_response['param_err'])

        if user_id >= 0:
            # 从User数据库获取user
            try:
                publisher = User.objects.get(id=user_id)
            except:
                return JsonResponse(gen_response['user_not_exist'])

            post_list = Post.objects.filter(publisher=publisher)

        else:
            # 获取包含该关键词的post
            keyword_list = TextKey.objects.filter(key=keyword)
            post_list = []
            for key in keyword_list:
                post_list.append(key.post)

        user = User.objects.get(id=request.user.id)
        posts = []
        for item in post_list:

            # 加载图片
            multimedia = []
            if item.is_video == False:
                for photo in Photo.objects.filter(post=item):
                    multimedia.append(photo.photo)

            # 判断是否给自己点赞
            if Favor.objects.filter(post=item).filter(user=user):
                self_favor = 1
            else:
                self_favor = 0

            # 一条摘要动态的数据结构
            publisher_info = {
                'userID': item.publisher.id,
                'username': item.publisher.username,
                'avatar': item.publisher.avatar
            }
            favorcnt = Favor.objects.filter(post=item).count()
            post_info =  {
                'postID': item.post_id,
                'publisher': publisher_info,
                'time': int(item.time.timestamp()*1000),
                'text': item.text,
                'multimediaContent': multimedia,
                'favor': {
                    'self': self_favor,
                    'favorCnt': favorcnt
                }
            }
            posts.append(post_info)

        response = {
            "code": 200,
            "data": {
                "downloadCount": len(posts),
                "posts": posts
            }
        }
        return JsonResponse(response)

    response = gen_response['method_err']
    return JsonResponse(response)

@csrf_exempt
def comments(request):
    if request.method == 'GET':
    # 获取评论列表, GET /post/comments/?postID=123&limit=10&start=10
        print('server receive GET', request.get_full_path())

        # 检查登陆状态
        if not request.user.is_authenticated:
            return JsonResponse(gen_response["user_error"])

        try:
            post_id = int(request.GET.get('postID')) # 评论的动态id
            num = int(request.GET.get('limit', default=10)) # 获取多少个评论
            start = int(request.GET.get('start', default=0)) # 上一次获取的结束评论号
        except:
            return(JsonResponse(gen_response['param_err']))

        try:
            post = Post.objects.get(post_id=post_id)
        except:
            return JsonResponse(gen_response['post_not_exist'])

        # 获取评论区列表
        total_cnt = Comment.objects.filter(post=post).count()

        comments = Comment.objects.filter(post=post).order_by('-id')[start:start+num]

        comment_list = []
        for comment in comments:

            user = {
                'userID': comment.user.id,
                'username': comment.user.username,
                'avatar': comment.user.avatar
            }
            comment_list.append({
                'commentID': comment.id,
                'user': user,
                'time': int(comment.time.timestamp()*1000),
                'text': comment.text
            })
        if len(comment_list):
            _start = comment_list[0]['commentID']
        else:
            _start = -1
        comment_list_info = {
            'postID': post.post_id,
            'totalCount': total_cnt,
            'downloadCount': len(comment_list),
            'start': _start,
            'comments': comment_list
        }

        response = {
            "code": 200,
            "data": {
                "commentList": comment_list_info
            }
        }
        return JsonResponse(response)
    response = gen_response['method_err']
    return JsonResponse(response)

@csrf_exempt
def favor(request):
    if request.method == 'POST':
    # 点赞, POST /post/favor/?postID=123
        print('server receive POST', request.get_full_path())

        # 检查登陆状态
        if not request.user.is_authenticated:
            return JsonResponse(gen_response["user_error"])

        try:
            post_id = int(request.POST.get('postID'))
            user_id = request.user.id
        except:
            return(JsonResponse(gen_response['param_err']))

        try:
            post = Post.objects.get(post_id=post_id)
        except:
            return JsonResponse(gen_response['post_not_exist'])

        try:
            user = User.objects.get(id=user_id)
        except:
            return JsonResponse(gen_response['user_not_exist'])

        fail = {
            "code": 300,
            "data": {
                "msg": "favored already"
            }
        }

        if Favor.objects.filter(post=post).filter(user=user):
            return JsonResponse(fail)
        try:
            Favor(post=post, user=user).save()
        except:
            pass

        return JsonResponse(gen_response['success'])
    elif request.method == 'DELETE':
    # 取消点赞, DELETE /post/favor/?postID=123&userID=123
        print('server receive DELETE', request.get_full_path())

        # 检查登陆状态
        if not request.user.is_authenticated:
            return JsonResponse(gen_response["user_error"])

        DELETE = json.loads(request.body)
        try:
            post_id = int(DELETE.get('postID'))
            user_id = int(DELETE.get('userID'))
        except:
            return(JsonResponse(gen_response['param_err']))

        try:
            post = Post.objects.get(post_id=post_id)
        except:
            return JsonResponse(gen_response['post_not_exist'])

        try:
            user = User.objects.get(id=user_id)
        except:
            return JsonResponse(gen_response['user_not_exist'])

        fail = {
            "code": 300,
            "data": {
                "msg": "never favored"
            }
        }
        try:
            favor = Favor.objects.filter(post=post).filter(user=user)[0]
            favor.delete()
        except:
            return JsonResponse(fail)

        return JsonResponse(gen_response['success'])

    return JsonResponse(gen_response['method_err'])

@csrf_exempt
def comment(request):
    if request.method == 'POST':
    # 评论, POST /post/comment/?postID=123&text=“test”
        print('server receive POST', request.get_full_path())

        # 检查登陆状态
        if not request.user.is_authenticated:
            return JsonResponse(gen_response["user_error"])

        try:
            post_id = int(request.POST.get('postID'))
            user_id = request.user.id
            text = request.POST.get('text', default='')
        except:
            return(JsonResponse(gen_response['param_err']))

        try:
            post = Post.objects.get(post_id=post_id)
        except:
            return JsonResponse(gen_response['post_not_exist'])

        try:
            user = User.objects.get(id=user_id)
        except:
            return JsonResponse(gen_response['user_not_exist'])

        comment = Comment()
        comment.post = post
        comment.user = user
        comment.text = text

        try:
            comment.save()
        except:
            response = {
                "code": 300,
                "data": {
                    "msg": "comment fail"
                }
            }
            return JsonResponse(response)

        return JsonResponse(gen_response['success'])
    response = gen_response['method_err']
    return JsonResponse(response)


from breezypythongui import EasyFrame

class ButtonDemo(EasyFrame):
    def __init__(self):
        EasyFrame.__init__(self)
        self.label = self.addLabel(text="Hey world.",row=0,column=0,columnspan=2)
        self.clearBtn = self.addButton(text="Clear",row=1,column=0)
        self.restoreBtn = self.addButton(text="Restore",row=1,column=1,state="disabled")

def main():
    root = ButtonDemo()
    root.mainloop()

if __name__ == '__main__':
    main()


from __future__ import annotations

from typing import Any, Tuple

from langchain.chains.query_constructor.ir import (
    Comparator,
    Comparison,
    Operation,
    Operator,
    StructuredQuery,
    Visitor,
)
from langchain.vectorstores.redis import Redis
from langchain.vectorstores.redis.filters import (
    RedisFilterExpression,
    RedisFilterField,
    RedisFilterOperator,
    RedisNum,
    RedisTag,
    RedisText,
)
from langchain.vectorstores.redis.schema import RedisModel

_COMPARATOR_TO_BUILTIN_METHOD = {
    Comparator.EQ: "__eq__",
    Comparator.NE: "__ne__",
    Comparator.LT: "__lt__",
    Comparator.GT: "__gt__",
    Comparator.LTE: "__le__",
    Comparator.GTE: "__ge__",
    Comparator.CONTAIN: "__eq__",
    Comparator.LIKE: "__mod__",
}

class RedisTranslator(Visitor):
    """Translate"""

    allowed_comparators = (
        Comparator.EQ,
        Comparator.NE,
        Comparator.LT,
        Comparator.LTE,
        Comparator.GT,
        Comparator.GTE,
        Comparator.CONTAIN,
        Comparator.LIKE,
    )
    """Subset of allowed logical comparators."""
    allowed_operators = (Operator.AND, Operator.OR)
    """Subset of allowed logical operators."""

    def __init__(self, schema: RedisModel) -> None:
        self._schema = schema

    def _attribute_to_filter_field(self, attribute: str) -> RedisFilterField:
        if attribute in [tf.name for tf in self._schema.text]:
            return RedisText(attribute)
        elif attribute in [tf.name for tf in self._schema.tag or []]:
            return RedisTag(attribute)
        elif attribute in [tf.name for tf in self._schema.numeric or []]:
            return RedisNum(attribute)
        else:
            raise ValueError(
                f"Invalid attribute {attribute} not in vector store schema. Schema is:"
                f"\n{self._schema.as_dict()}"
            )

    def visit_comparison(self, comparison: Comparison) -> RedisFilterExpression:
        filter_field = self._attribute_to_filter_field(comparison.attribute)
        comparison_method = _COMPARATOR_TO_BUILTIN_METHOD[comparison.comparator]
        return getattr(filter_field, comparison_method)(comparison.value)

    def visit_operation(self, operation: Operation) -> Any:
        left = operation.arguments[0].accept(self)
        if len(operation.arguments) > 2:
            right = self.visit_operation(
                Operation(
                    operator=operation.operator, arguments=operation.arguments[1:]
                )
            )
        else:
            right = operation.arguments[1].accept(self)
        redis_operator = (
            RedisFilterOperator.OR
            if operation.operator == Operator.OR
            else RedisFilterOperator.AND
        )
        return RedisFilterExpression(operator=redis_operator, left=left, right=right)

    def visit_structured_query(
        self, structured_query: StructuredQuery
    ) -> Tuple[str, dict]:
        if structured_query.filter is None:
            kwargs = {}
        else:
            kwargs = {"filter": structured_query.filter.accept(self)}
        return structured_query.query, kwargs

    @classmethod
    def from_vectorstore(cls, vectorstore: Redis) -> RedisTranslator:
        return cls(vectorstore._schema)


from src.__init__ import *

def make_one_hot(
        num_classes: int,
        category_id: int
) -> Tensor:

    return torch.from_numpy(np.eye(num_classes, dtype='int8')[category_id]).to(device)

def category_filter(
        original_cat: Union[list, tuple],
        missing_cat: Union[list, tuple]
) -> Dict:

    valid_cat = list(filter(lambda c: c not in missing_cat, original_cat))
    cat_table = {c: i for i, c in enumerate(valid_cat)}
    return cat_table

def fill_empty_category(
        category_id: int,
        missing_cat: Union[list, tuple],
        start_id: int
) -> int:

    category_id += start_id

    for missing_id in missing_cat:
        if category_id >= missing_id:
            category_id += 1
        else:
            break

    return category_id

def imagenet_fill():
    return tuple([round(255 * m) for m in (0.485, 0.456, 0.406)])

def make_mini_batch(
        sample
) -> Tuple[Tensor, Tensor]:

    images, labels, target_nums = [], [], []

    zero_labels = []
    max_target_num = 0

    for image, label in sample:
        images.append(image)
        labels.append(label)
        target_num = label.size(0)
        target_nums.append(target_num)
        max_target_num = max(max_target_num, target_num)

    for label in labels:
        target_num = label.size(0)
        zero_fill = torch.zeros((max_target_num - target_num, label.size(1)), dtype=label.dtype, device=label.device)
        zero_label = torch.cat((label, zero_fill), dim=0)
        zero_labels.append(zero_label)

    images = torch.stack(images)
    labels = torch.stack(zero_labels)

    return images, labels


"""
An example on how to read existing CP2K input files directly into the CP2K
object.
"""
from pycp2k import CP2K

# The CP2K object is normally initialized
calc = CP2K()

# This function tries to read the input file in the given path and places its
# contents to the input tree. Notice that this will overwrite any already set
# inputs.
calc.parse("template.in")

# The calculation can be modified and run after reading the input file
calc.CP2K_INPUT.GLOBAL.Project_name = "modified"
calc.write_input_file("parse_example_modified.txt")


from typing import Iterable, Optional

from django.contrib.auth import get_user_model
from django.db import models

TASK_STATUS_CHOICES = [
    ('N', 'NEW'),
    ('I', 'IN PROGRESS'),
    ('P', 'IN PAUSE'),
    ('D', 'DONE'),
]

TASK_PRIORITY_CHOICES = [
    ('HH', 'Highest'),
    ('H', 'High'),
    ('M', 'Medium'),
    ('L', 'Low'),
    ('LL', 'Lowest'),
]

User = get_user_model()

class Task(models.Model):
    description = models.CharField(max_length=255)
    status = models.CharField(choices=TASK_STATUS_CHOICES, max_length=2)
    priority = models.CharField(
        choices=TASK_PRIORITY_CHOICES, default='M')
    owner = models.ForeignKey(User, on_delete=models.CASCADE)


import os

RENAME_PATTERNS = [
    ('__project_name__', '{{cookiecutter.project_name}}'),
    ('__app_name__', '{{cookiecutter.app_name}}'),
]

IGNORE_FILES = ['rename.py', 'README.md']
IGNORE_DIRS = ['.git']

def replace(text):
    output = text
    for pattern in RENAME_PATTERNS:
        output = output.replace(pattern[0], pattern[1])
    return output, text != output

def is_ignore_dir(dirpath):
    for dir in IGNORE_DIRS:
        if dir in dirpath:
            return True
    return False

def main():
    for dirpath, dirnames, filenames in list(os.walk('.'))[:]:
        if is_ignore_dir(dirpath):
            continue

        for filename in filenames:
            fullpath = os.path.join(dirpath, filename)
            if filename in IGNORE_FILES:
                continue
            with open(fullpath, 'r') as fp:
                text = fp.read()
            text, changed = replace(text)
            if changed:
                with open(fullpath, 'w') as fp:
                    fp.write(text)

        for dirname in dirnames:
            fullpath = os.path.join(dirpath, dirname)
            new_fullpath, changed = replace(fullpath)
            if changed:
                os.rename(fullpath, new_fullpath)

        for filename in filenames:
            if filename in IGNORE_FILES:
                continue
            fullpath = os.path.join(dirpath, filename)
            new_fullpath, changed = replace(fullpath)
            if changed:
                os.rename(fullpath, new_fullpath)

if __name__ == '__main__':
    main()


# -*- coding:UTF-8 -*-
import re

def get_score_from_file_GM_new():   #read P1 P2 P3 for calculate  the final score
    scores = []
    scores_num = []
    f_data = open("result.txt", "r")
    try:
        all_the_text = f_data.read()
        every_frame_information = all_the_text.split('query')
        for string in every_frame_information[1:]:
            P1_first_index = string.index('P1: ')   #first time it exist
            if string[P1_first_index+7].isdigit() == True:
                P1_score = float(string[P1_first_index+4:P1_first_index+8])
            else:
                P1_score = float(string[P1_first_index+4:P1_first_index+7])
            if P1_score < 0.2:
                scores_num.append(0)
            else:
                P2_first_index = string.index('P2: ')
                if string[P2_first_index+5].isdigit() == True:
                    P2_score = float(string[P2_first_index+4:P2_first_index+6])
                else:
                    P2_score = float(string[P2_first_index+4:P2_first_index+5])

                P3_first_index = string.index('max_same_angle_count is : ')
                if string[P3_first_index+27].isdigit() == True:       #
                    if string[P3_first_index+28] == '.':
                        P3_score = float(string[P3_first_index+26:P3_first_index+30])  #like: 10.5
                    else:
                        P3_score = int(string[P3_first_index+26:P3_first_index+28])  #like: 10
                elif string[P3_first_index+27] == '.':
                    P3_score = float(string[P3_first_index+26:P3_first_index+29])  #like: 8.5
                else:
                    P3_score = int(string[P3_first_index+26:P3_first_index+27])   #like: 8

                tem_final_score = P1_score + 5*P2_score + 2*P3_score
                scores_num.append(tem_final_score)
    finally:
        f_data.close()
    return scores_num

score_GM = get_score_from_file_GM_new()

def R_P_calculate(frames_num, scores, score_threshold, true_positive, flag = ' '):
    FP_list = [];  TP_list = []
    TP=0 ; FP =0 ; TN=0 ; FN=0
    for i in range(frames_num):
        if scores[i] ==-1:
            continue
        elif  scores[i] >=score_threshold:   #positive
            if true_positive[i] == 1:
                TP = TP+ 1
                TP_list.append(i)
            elif true_positive[i] == 0:
                FP = FP + 1
                FP_list.append(i)
        elif scores[i] < score_threshold:  #negetive
            if true_positive[i] == 1:
                FN = FN+ 1
            elif true_positive[i] == 0:
                TN = TN + 1

    if TP +FN == 0:
        recall_once = 0
    else:
        recall_once = float(TP) / (TP +FN)

    if TP +FP == 0:
        precision_once = 0
    else:
        precision_once =  float(TP) / (TP +FP)

    # print(FP_list)
    return recall_once, precision_once, FP_list, TP_list

#true positive
frames_num = 300
true_positive = [0 for i in range(frames_num)]
for i in range(frames_num):                #scenenet-209-1675frame
    if (i>=0 and i<=74) or (i>=167 and i<=213) or (i>=293 and i<=299) :
        true_positive[i] = 1  #positive
    else:             #negetive
        true_positive[i] = 0

#P-R curve
recall_GM = [] ; precision_GM = []
precision_GM.append(1) ; recall_GM.append(0)
for score_threshold in range(1000, -1, -1):
    score_threshold = float(score_threshold)/10

    recall_GM_once, precision_GM_once, FP_list, TP_list = R_P_calculate(frames_num, score_GM, score_threshold, true_positive, 'ours')
    if recall_GM_once != 0 or precision_GM_once != 0:
        recall_GM.append( recall_GM_once )
        precision_GM.append( precision_GM_once )
        # print(recall_GM_once, precision_GM_once)

def R_P_area_calculate(precision_list, recall_list): #P-R curve area
    area = 0
    for i in range(len(recall_list)-1):
        area += float(precision_list[i] + precision_list[i+1]) * (recall_list[i+1] - recall_list[i]) /2
    print( "The area of the P-R curve is: "+str(area))
    return area

R_P_area_calculate(precision_GM,recall_GM)

import matplotlib.pyplot as plt
plt.plot(recall_GM, precision_GM, 'r', label='area:0.986')
plt.legend()

plt.show()


import pandas as pd
import os

path = "D:\\lenovo\\Desktop\\sysevr\\"
all_dfs = []

for dirname, _, filenames in os.walk(path):
    for filename in filenames:
        p = path+filename
        # print(p)
        df = pd.read_csv(p)
        all_dfs.append(df)

final_df = pd.concat(all_dfs)
print(final_df['code'].count())

print(final_df.head(5))

path1 = "D:\\lenovo\\Desktop\\2018280142\\Preprocess\\data\\sysevr\\all_standardized_sysevr.csv"
final_df.to_csv(path1, index=None, header=True)

print('done')

# dummy_data1 = {
#     'name': ['Sam', 'Fred'],
#     'age': ['21', '16']}
#
# dummy_data2 = {
#     'name': ['Jack', 'Tom'],
#     'age': ['23', '56']}
#
# dummy_data3 = {
#     'name': ['Smith', 'Norry'],
#     'age': ['12', '34']}
#
# df1 = pd.DataFrame(dummy_data1, columns=['name', 'age'])
# df2 = pd.DataFrame(dummy_data2, columns=['name', 'age'])
# df3 = pd.DataFrame(dummy_data3, columns=['name', 'age'])

# df4 = pd.concat([df1, df2, df3])
# print(df4['name'].count())


import matplotlib.pyplot as plt
import numpy as np

def barChart():
    x = np.arange(4)
    y1 = np.random.randint(20, 50, 4)
    y2 = np.random.randint(10, 60, 4)
    plt.figure(figsize=(6, 4), dpi=120)
    # 通过横坐标的偏移，让两组数据对应的柱子分开
    # width参数控制柱子的粗细，label参数为柱子添加标签
    plt.bar(x - 0.1, y1, width=0.2, label='销售A组')
    plt.bar(x + 0.1, y2, width=0.2, label='销售B组')
    # 定制横轴的刻度
    plt.xticks(x, labels=['Q1', 'Q2', 'Q3', 'Q4'])
    # 定制显示图例
    plt.legend()
    plt.show()

def stackGraph():
    x = np.arange(4)
    y1 = np.random.randint(20, 50, 4)
    y2 = np.random.randint(10, 60, 4)
    labels = ['Q1', 'Q2', 'Q3', 'Q4']
    plt.figure(figsize=(6, 4), dpi=120)
    plt.bar(labels, y1, width=0.4, label='销售A组')
    # 注意：堆叠柱状图的关键是将之前的柱子作为新柱子的底部
    # 可以通过bottom参数指定底部数据，新柱子绘制在底部数据之上
    plt.bar(labels, y2, width=0.4, bottom=y1, label='销售B组')
    plt.legend(loc='lower right')
    plt.show()

def pie():
    data = np.random.randint(100, 500, 7)
    labels = ['苹果', '香蕉', '桃子', '荔枝', '石榴', '山竹', '榴莲']

    plt.figure(figsize=(5, 5), dpi=120)
    plt.pie(
        data,
        # 自动显示百分比
        autopct='%.1f%%',
        # 饼图的半径
        radius=1,
        # 百分比到圆心的距离
        pctdistance=0.8,
        # 颜色（随机生成）
        colors=np.random.rand(7, 3),
        # 分离距离
        # explode=[0.05, 0, 0.1, 0, 0, 0, 0],
        # 阴影效果
        # shadow=True,
        # 字体属性
        textprops=dict(fontsize=8, color='black'),
        # 楔子属性（生成环状饼图的关键）
        wedgeprops=dict(linewidth=1, width=0.35),
        # 标签
        labels=labels
    )
    # 定制图表的标题
    plt.title('水果销售额占比')
    plt.show()

if __name__ == '__main__':
    plt.rcParams['font.sans-serif'] = ['SimHei', 'Songti SC']
    plt.rcParams['axes.unicode_minus'] = False
    #plt.figure(figsize=(8, 4), dpi=120, facecolor='darkgray')
    #plt.subplot(2, 2, 1)

    # barChart()
    # stackGraph()
    pie()