#!/usr/bin/python3
# -*- coding: utf-8 -*-
import os, random, time, pprint, threading, logging, base64
import cv2, numpy, queue, threading, time
from yattag import Doc

from pprint import pprint

from flask import Flask, request, Response, render_template, send_from_directory, send_file, abort, redirect
os.environ["DISPLAY"] = ":0"
os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"] = "rtsp_transport;tcp"
vcap = cv2.VideoCapture("rtsp://127.0.0.1:8554/cam", cv2.CAP_FFMPEG)  #"rtmp://10.83.6.197/cam"

# bufferless VideoCapture
class VCOBJ:
# https://stackoverflow.com/questions/43665208/how-to-get-the-latest-frame-from-capture-device-camera-in-opencv
  def __init__(self, source):
    self.cap = cv2.VideoCapture(source)
    self.q = queue.Queue()
    t = threading.Thread(target=self._reader)
    t.daemon = True
    t.start()

  # read frames as soon as they are available, keeping only most recent one
  def _reader(self):
    while True:
      ret, frame = self.cap.read()
      if not ret:
        print("read empty frame")
        break
      if not self.q.empty():
        try:
          self.q.get_nowait()   # discard previous (unprocessed) frame
        except queue.Empty:
          pass
      self.q.put(frame)
      time.sleep(0.1)   # simulate time between events
      cv2.imshow("frame", frame)
      #if chr(cv2.waitKey(1)&255) == 'q':
#    break

  def read(self):
    return self.q.get()

cap = VCOBJ("rtsp://127.0.0.1:8554/cam")

app = Flask(__name__, static_url_path='')
app.logger.setLevel(logging.DEBUG)
logging.basicConfig(level=logging.DEBUG)

@app.route("/pic.jpeg")
def pic_jpeg():
    frame = cap.read()
    ret, buffer = cv2.imencode('.jpg', frame)
    frame = buffer.tobytes()
    return Response(frame, mimetype='image/jpeg')

@app.route("/",methods=['POST', 'GET'])
def index():
    doc, tag, text = Doc().tagtext()

    with tag('h2'):
        text("Get Data Area")

    with tag('big'):
        with tag('a', ('href', '/pic.jpeg')):
            text('get full pic')

    with tag('hr'):
        pass
    with tag('h2'):
        text("request.environ")
    with tag('pre'):
        for k, v in request.environ.items():
            doc.asis(str(k) + ': ' + str(v) + os.linesep)
    return Response(doc.getvalue(), mimetype='text/html;charset=UTF-8')

if __name__ == "__main__":
#  time.sleep(0.5)   # simulate time between events
#  frame = cap.read()
#  cv2.imshow("frame", frame)
#  if chr(cv2.waitKey(1)&255) == 'q':
#    break
  logging.info("starting flask")
  app.run(host='0.0.0.0', port=6660, debug=False)


from flask import request, render_template
from web_server import app
import os
from web_server.entity.vtt_video import VTTVideo

BASE_DIRECTORY = os.path.dirname(os.path.realpath(__file__))
VIDEO_FILE_NAME = "videos/<test case name>.webm"
VTT_FILE_NAME = "videos/<test case name>.vtt"
VTT_VIDEO = VTTVideo()

@app.route('/select-test', methods=['POST'])
def select_test():
    if len(request.values) > 0:
        app.logger.debug(f"test-case-name: {request.values['test-case-name']}")

        test_case_name = request.values['test-case-name']
        vtt_file = os.path.join(os.path.dirname(BASE_DIRECTORY), "static/" +
                                VTT_FILE_NAME.replace("<test case name>", test_case_name))
        VTT_VIDEO.set_test_case_name(test_case_name)
        VTT_VIDEO.generate_vtt_list()
        VTT_VIDEO.save_vtt_list_to_file(vtt_file)

        video_file = os.path.join(os.path.dirname(BASE_DIRECTORY), "static/" +
                                  VIDEO_FILE_NAME.replace("<test case name>", test_case_name))

        VTT_VIDEO.set_video_url()
        status = VTT_VIDEO.save_video_to_file(video_file)

    return show_video_with_track()

@app.route('/upload-file', methods=['POST'])
def upload_file():
    fp = request.files['xml file']
    app.logger.debug(f"request.files['xml file']: {fp.filename}")
    if fp.filename != "":
        file_name = os.path.join(app.config['UPLOAD_FOLDER'], fp.filename)
        fp.save(file_name)
        VTT_VIDEO.set_parser(file_name)

    return show_video_with_track()

@app.route('/')
def show_video_with_track():
    test_case_name = VTT_VIDEO.get_test_name()

    video_name = VIDEO_FILE_NAME.replace("<test case name>", test_case_name)
    track_name = VTT_FILE_NAME.replace("<test case name>", test_case_name)

    test_names = VTT_VIDEO.get_test_names()

    return render_template("index.html",
                           video_name=video_name,
                           track_name=track_name,
                           tests=test_names)


import time
from random import shuffle

q_n_as = [
    ['My favorite color is blue', 'T'],
    ['I hate animals', 'F'],
    ['I love cucumbers', 'F'],
    ['I speak some Turkish', 'T'],
    ['My parents have never divorced', 'F'],
    ['I graduated from a linguistic uni', 'T'],
    ['My name is rare in Belarus', 'T']
]
shuffle(q_n_as)

score = 0
start_time = time.perf_counter()
for q, a in q_n_as:
    my_answer = input(f'True or false: {q} ')
    if my_answer == a:
        score += 1
        print('Excellent!')
    else:
        print('Not correct.')
end_time = time.perf_counter()
print(f'Your score is {score}, time spent is {end_time - start_time}')


import streamlit as st
from streamlit_option_menu import option_menu
import homepage, experience, resume, contact, projects

st.set_page_config(
    page_title="My WebPage",
    page_icon=":tada:",
    layout="wide")

# # Option Menu 1
# with st.sidebar:
#     selected = option_menu(
#         menu_title="Sazzad H. Farhaan",
#         options=["Home", "Experience", "Resume", "Contact"],
#         # "Awards", "Education", "Certificates", "Technical Skills"
#         # "Competitions", "Volunteering", "Blog"]
#         icons=["person-bounding-box", "hourglass-split",  # From https://icons.getbootstrap.com/
#                "file-earmark-person-fill", "envelope-at"],
#         menu_icon="Mortorboard",
#         default_index=0,
#     )
# if selected == "About Me":
#     st.title(f"You have selected {selected}")
# if selected == "Experience":
#     st.title(f"You have selected {selected}")
# if selected == "Resume":
#     st.title(f"You have selected {selected}")
# if selected == "Contact":
#     st.title(f"You have selected {selected}")
#

class MultiApp:

    def __init__(self):
        self.apps = []

    # def add_app(self, title, func):
    #
    #     self.apps.append({
    #         "title": title,
    #         "function": func
    #     })

    def run():
        # app = st.sidebar(
        with st.sidebar:
            selected = option_menu(
                menu_title="Sazzad H. Farhaan",
                options=["Home", "Projects", "Experience", "Resume", "Contact"],
                # "Awards", "Education", "Certificates", "Technical Skills"
                # "Competitions", "Volunteering", "Blog"]
                icons=["person-bounding-box", "code-square", "hourglass-split",  # From https://icons.getbootstrap.com/
                       "file-earmark-person-fill", "envelope-at"],
                menu_icon="Mortorboard",
                default_index=0,
                styles={
                    "container": {"padding": "5!important", "background-color": 'black'},
                    "icon": {"color": "white", "font-size": "23px"},
                    "nav-link": {"color": "white", "font-size": "18px", "text-align": "left", "margin": "0px",
                                 "--hover-color": "blue"},
                    "nav-link-selected": {"background-color": "#02ab21"}, }

            )

        if selected == "Home":
            homepage.app()
        if selected == "Projects":
            projects.app()
        if selected == "Experience":
            experience.app()
        if selected == "Resume":
            resume.app()
        if selected == "Contact":
            contact.app()

    run()


print("******************* Welcome to the world of Love **************************************")
yourName= input("Enter your name: ")
partnerName = input("Please enter your partner name: ")

name = yourName.lower()
partner = partnerName.lower()

lCount=name.count("l") + partner.count("l")
oCount=name.count("o") + partner.count("o")
vCount=name.count("v") + partner.count("v")
eCount=name.count("e") + partner.count("e")
tCount=name.count("t") + partner.count("t")
rCount=name.count("r") + partner.count("r")
uCount=name.count("u") + partner.count("u")

loveTotal= lCount + oCount +vCount + eCount
trueTotal= tCount + rCount + uCount+ eCount

print(f"T occurs {tCount} times\nR occurs {rCount} times\nU occurs {uCount} times\nE occurs {eCount} times")
print(f"Total = {trueTotal}")

print(f"L occurs {lCount} times\nO occurs {oCount} times\nV occurs {vCount} times\nE occurs {eCount} times")
print(f"Total = {loveTotal}")

loveScore = int(str(trueTotal)+str(loveTotal))

if loveScore<10 or loveScore>90:
    print(f"Your score is {loveScore}, you go together like coke and mentos.")
elif loveScore >=40 and loveScore<=50:
     print(f"Your score is {loveScore}, you are alright together.")
else:
    print(f"Your Score is {loveScore}.")


# -*- coding: utf8 -*-
import turtle               # 汇入turtle套件，允许我们使用turtle指令
window = turtle.Screen()        # 产生画布以进行画图
window.bgcolor("lightgreen")# 设定画布底色为浅绿色

marry = turtle.Turtle()         # 建立一个海龟turtle，它的名字叫marry
marry.color("hotpink")          # 设定画笔颜色为粉红色
marry.pensize(5)                        # 设定画笔粗细为5个像素

john = turtle.Turtle()          # 建立一个海龟turtle，它的名字叫john
colors = ["yellow", "red", "purple", "blue" ,"hotpink"]
for pen_color in colors:
    john.color(pen_color)
    john.forward(240)                # 告诉海龟往前走50个单位
    john.left(144)                   # 告诉海龟左转90度

window.exitonclick()                    # 等待使用者关闭视窗


# -*- coding: utf-8 -*-

import logging
from jellyfinapi.api_helper import APIHelper
from jellyfinapi.controllers.base_controller import BaseController
from jellyfinapi.models.base_item_dto_query_result import BaseItemDtoQueryResult
from jellyfinapi.models.base_item_dto import BaseItemDto
from jellyfinapi.exceptions.api_exception import APIException
from jellyfinapi.exceptions.problem_details_exception import ProblemDetailsException

class YearsController(BaseController):

    """A Controller to access Endpoints in the jellyfinapi API."""

    def __init__(self, config, auth_managers):
        super(YearsController, self).__init__(config, auth_managers)
        self.logger = logging.getLogger(__name__)

    def get_years(
        self,
        start_index=None,
        limit=None,
        sort_order=None,
        parent_id=None,
        fields=None,
        exclude_item_types=None,
        include_item_types=None,
        media_types=None,
        sort_by=None,
        enable_user_data=None,
        image_type_limit=None,
        enable_image_types=None,
        user_id=None,
        recursive=True,
        enable_images=True,
    ):
        """Does a GET request to /Years.

        Get years.

        Args:
            start_index (int, optional): Skips over a given number of items
                within the results. Use for paging.
            limit (int, optional): Optional. The maximum number of records to
                return.
            sort_order (list of SortOrderEnum, optional): Sort Order -
                Ascending,Descending.
            parent_id (uuid|string, optional): Specify this to localize the
                search to a specific item or folder. Omit to use the root.
            fields (list of ItemFieldsEnum, optional): Optional. Specify
                additional fields of information to return in the output.
            exclude_item_types (list of BaseItemKindEnum, optional): Optional.
                If specified, results will be excluded based on item type.
                This allows multiple, comma delimited.
            include_item_types (list of BaseItemKindEnum, optional): Optional.
                If specified, results will be included based on item type.
                This allows multiple, comma delimited.
            media_types (list of string, optional): Optional. Filter by
                MediaType. Allows multiple, comma delimited.
            sort_by (list of string, optional): Optional. Specify one or more
                sort orders, comma delimited. Options: Album, AlbumArtist,
                Artist, Budget, CommunityRating, CriticRating, DateCreated,
                DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName,
                Random, Revenue, Runtime.
            enable_user_data (bool, optional): Optional. Include user data.
            image_type_limit (int, optional): Optional. The max number of
                images to return, per image type.
            enable_image_types (list of ImageTypeEnum, optional): Optional.
                The image types to include in the output.
            user_id (uuid|string, optional): User Id.
            recursive (bool, optional): Search recursively.
            enable_images (bool, optional): Optional. Include image
                information in output.

        Returns:
            BaseItemDtoQueryResult: Response from the API. Year query
                returned.

        Raises:
            APIException: When an error occurs while fetching the data from
                the remote API. This exception includes the HTTP Response
                code, an error message, and the HTTP body that was received in
                the request.

        """
        try:
            self.logger.info("get_years called.")

            # Prepare query URL
            self.logger.info("Preparing query URL for get_years.")
            _url_path = "/Years"
            _query_builder = self.config.get_base_uri()
            _query_builder += _url_path
            _query_parameters = {
                "startIndex": start_index,
                "limit": limit,
                "sortOrder": sort_order,
                "parentId": parent_id,
                "fields": fields,
                "excludeItemTypes": exclude_item_types,
                "includeItemTypes": include_item_types,
                "mediaTypes": media_types,
                "sortBy": sort_by,
                "enableUserData": enable_user_data,
                "imageTypeLimit": image_type_limit,
                "enableImageTypes": enable_image_types,
                "userId": user_id,
                "recursive": recursive,
                "enableImages": enable_images,
            }
            _query_builder = APIHelper.append_url_with_query_parameters(
                _query_builder, _query_parameters
            )
            _query_url = APIHelper.clean_url(_query_builder)

            # Prepare headers
            self.logger.info("Preparing headers for get_years.")
            _headers = {"accept": "application/json"}

            # Prepare and execute request
            self.logger.info("Preparing and executing request for get_years.")
            _request = self.config.http_client.get(_query_url, headers=_headers)
            # Apply authentication scheme on request
            self.apply_auth_schemes(_request, "global")

            _response = self.execute_request(_request, name="get_years")

            # Endpoint and global error handling using HTTP status codes.
            self.logger.info("Validating response for get_years.")
            if _response.status_code == 401:
                raise APIException("Unauthorized", _response)
            elif _response.status_code == 403:
                raise APIException("Forbidden", _response)
            self.validate_response(_response)

            decoded = APIHelper.json_deserialize(
                _response.text, BaseItemDtoQueryResult.from_dictionary
            )

            return decoded

        except Exception as e:
            self.logger.error(e, exc_info=True)
            raise

    def get_year(self, year, user_id=None):
        """Does a GET request to /Years/{year}.

        Gets a year.

        Args:
            year (int): The year.
            user_id (uuid|string, optional): Optional. Filter by user id, and
                attach user data.

        Returns:
            BaseItemDto: Response from the API. Year returned.

        Raises:
            APIException: When an error occurs while fetching the data from
                the remote API. This exception includes the HTTP Response
                code, an error message, and the HTTP body that was received in
                the request.

        """
        try:
            self.logger.info("get_year called.")

            # Prepare query URL
            self.logger.info("Preparing query URL for get_year.")
            _url_path = "/Years/{year}"
            _url_path = APIHelper.append_url_with_template_parameters(
                _url_path, {"year": {"value": year, "encode": True}}
            )
            _query_builder = self.config.get_base_uri()
            _query_builder += _url_path
            _query_parameters = {"userId": user_id}
            _query_builder = APIHelper.append_url_with_query_parameters(
                _query_builder, _query_parameters
            )
            _query_url = APIHelper.clean_url(_query_builder)

            # Prepare headers
            self.logger.info("Preparing headers for get_year.")
            _headers = {"accept": "application/json"}

            # Prepare and execute request
            self.logger.info("Preparing and executing request for get_year.")
            _request = self.config.http_client.get(_query_url, headers=_headers)
            # Apply authentication scheme on request
            self.apply_auth_schemes(_request, "global")

            _response = self.execute_request(_request, name="get_year")

            # Endpoint and global error handling using HTTP status codes.
            self.logger.info("Validating response for get_year.")
            if _response.status_code == 401:
                raise APIException("Unauthorized", _response)
            elif _response.status_code == 403:
                raise APIException("Forbidden", _response)
            elif _response.status_code == 404:
                raise ProblemDetailsException("Year not found.", _response)
            self.validate_response(_response)

            decoded = APIHelper.json_deserialize(
                _response.text, BaseItemDto.from_dictionary
            )

            return decoded

        except Exception as e:
            self.logger.error(e, exc_info=True)
            raise


#!/usr/bin/python3
import string
import datetime

# Parameters
pathToFile = "resources/x.txt"
pathToNewFile = "resources/y.txt"
textToReplace = "xxxx"

# Open file and record file with timeSTAMP
text = open(pathToFile).read()
stamp = int(datetime.datetime.now().timestamp())
text = text.replace(textToReplace, str(stamp))
newTest = open(pathToNewFile, 'w')
newTest.write(text)
newTest.close()


# https://codingcompetitions.withgoogle.com/kickstart/round/000000000019ff48/00000000003f4b8b

T = int(input())
for t in range(T):
    N, K = map(int,input().split())
    intervals = []
    for n in range(N):
        aux = list(map(int,input().split()))
        intervals.append(aux)

    intervals.sort(key = lambda x: x[0])

    ans, prv = 0, 0
    for [x,y] in intervals:
        if x < prv and prv < y:
            aux = (y-prv)//K
            if (y-prv)%K:
                aux += 1
            ans += aux
            prv = prv + aux*K

        elif prv <= x:
            aux = (y-x)//K
            if (y-x)%K:
                aux += 1
            ans += aux
            prv = x + aux*K

    print('Case #{}: {}'.format(t+1,ans))


import numpy as np
import cv2
import os
import json

PROJ_DIR = "/home/olle/PycharmProjects/LODE/workspace/feature_segmentation/segmentation"
MICHAEL_FIB_DIR = os.path.join(PROJ_DIR, "data/versions/fibrosis_corrections/michael")
BEN_FIB_DIR = os.path.join(PROJ_DIR, "data/versions/fibrosis_corrections/ben")

def map_changes(img_id, map_):
    if "14277_R_20180305" in img_id:
        map_[map_ == 7] = 13
        map_[map_ == 5] = 13

    if "57929_L_20170123" in img_id:
        map_[map_ == 8] = 7
        map_[map_ == 5] = 13

    if "239396_R_20151117" in img_id:
        map_[map_ == 5] = 6

    if "92927_R_20171127" in img_id:
        map_[map_ == 5] = 7

    if "181978_R_20160725" in img_id:
        map_[map_ == 5] = 13

    if "175612_L_20180606" in img_id:
        map_[map_ == 8] = 7
        map_[map_ == 5] = 6

    if "176808_R_20160303" in img_id:
        map_[map_ == 5] = 13
        map_[map_ == 8] = 7

    return map_


import multiprocessing
import time
import concurrent.futures
import test_global as tg
import p2

def counting():
    for i in range(20):
        print(i)
        print(f'[f1] pad detected: {tg.PAD_DETECTED}')
        time.sleep(3)

def dummy_sensor():

    land = False
    for i in range(10):
        sensor_data = input("is there a pad?")
        if sensor_data == str(1):
            tg.PAD_DETECTED = True
        print(f'[f2] pad detected: {tg.PAD_DETECTED}')

def start_p2():
    p2.main()

if __name__ == "__main__":
    with concurrent.futures.ThreadPoolExecutor() as executor:
        f1 = executor.submit(counting)
        f2 = executor.submit(dummy_sensor)
        f3 = executor.submit(start_p2)

        concurrent.futures.wait([f1, f2, f3])

    """
    p2 = multiprocessing.Process(target=dummy_sensor())
    p1 = multiprocessing.Process(target=counting(2))

    p2.start()
    p1.start()

    p1.join()
    p2.join()
    """


from typing import Dict, Tuple, Union, Callable, Type, Optional, Any
import hashlib
import json
import logging
import time

from ray.serve.config import ReplicaConfig, DeploymentConfig
from ray.serve.schema import ServeApplicationSchema
from ray.serve._private.constants import SERVE_LOGGER_NAME
from ray.serve._private.common import DeploymentInfo

import ray
import ray.util.serialization_addons

logger = logging.getLogger(SERVE_LOGGER_NAME)

def get_deploy_args(
    name: str,
    deployment_def: Union[Callable, Type[Callable], str],
    init_args: Tuple[Any],
    init_kwargs: Dict[Any, Any],
    ray_actor_options: Optional[Dict] = None,
    config: Optional[Union[DeploymentConfig, Dict[str, Any]]] = None,
    version: Optional[str] = None,
    route_prefix: Optional[str] = None,
    is_driver_deployment: Optional[str] = None,
    docs_path: Optional[str] = None,
    app_name: Optional[str] = None,
) -> Dict:
    """
    Takes a deployment's configuration, and returns the arguments needed
    for the controller to deploy it.
    """

    if config is None:
        config = {}
    if ray_actor_options is None:
        ray_actor_options = {}

    curr_job_env = ray.get_runtime_context().runtime_env
    if "runtime_env" in ray_actor_options:
        # It is illegal to set field working_dir to None.
        if curr_job_env.get("working_dir") is not None:
            ray_actor_options["runtime_env"].setdefault(
                "working_dir", curr_job_env.get("working_dir")
            )
    else:
        ray_actor_options["runtime_env"] = curr_job_env

    replica_config = ReplicaConfig.create(
        deployment_def,
        init_args=init_args,
        init_kwargs=init_kwargs,
        ray_actor_options=ray_actor_options,
    )

    if isinstance(config, dict):
        deployment_config = DeploymentConfig.parse_obj(config)
    elif isinstance(config, DeploymentConfig):
        deployment_config = config
    else:
        raise TypeError("config must be a DeploymentConfig or a dictionary.")

    deployment_config.version = version

    if (
        deployment_config.autoscaling_config is not None
        and deployment_config.max_concurrent_queries
        < deployment_config.autoscaling_config.target_num_ongoing_requests_per_replica  # noqa: E501
    ):
        logger.warning(
            "Autoscaling will never happen, "
            "because 'max_concurrent_queries' is less than "
            "'target_num_ongoing_requests_per_replica' now."
        )

    controller_deploy_args = {
        "name": name,
        "deployment_config_proto_bytes": deployment_config.to_proto_bytes(),
        "replica_config_proto_bytes": replica_config.to_proto_bytes(),
        "route_prefix": route_prefix,
        "deployer_job_id": ray.get_runtime_context().get_job_id(),
        "is_driver_deployment": is_driver_deployment,
        "docs_path": docs_path,
        "app_name": app_name,
    }

    return controller_deploy_args

def deploy_args_to_deployment_info(
    deployment_name: str,
    deployment_config_proto_bytes: bytes,
    replica_config_proto_bytes: bytes,
    deployer_job_id: Union[str, bytes],
    route_prefix: Optional[str],
    is_driver_deployment: Optional[bool] = False,
    app_name: Optional[str] = None,
) -> DeploymentInfo:
    """Takes deployment args passed to the controller after building an application and
    constructs a DeploymentInfo object.
    """

    deployment_config = DeploymentConfig.from_proto_bytes(deployment_config_proto_bytes)
    version = deployment_config.version
    replica_config = ReplicaConfig.from_proto_bytes(
        replica_config_proto_bytes, deployment_config.needs_pickle()
    )

    # Java API passes in JobID as bytes
    if isinstance(deployer_job_id, bytes):
        deployer_job_id = ray.JobID.from_int(
            int.from_bytes(deployer_job_id, "little")
        ).hex()

    return DeploymentInfo(
        actor_name=deployment_name,
        version=version,
        deployment_config=deployment_config,
        replica_config=replica_config,
        deployer_job_id=deployer_job_id,
        start_time_ms=int(time.time() * 1000),
        is_driver_deployment=is_driver_deployment,
        app_name=app_name,
        route_prefix=route_prefix,
    )

def get_app_code_version(app_config: ServeApplicationSchema) -> str:
    """Returns the code version of an application.

    Args:
        app_config: The application config.

    Returns: a hash of the import path and (application level) runtime env representing
            the code version of the application.
    """
    encoded = json.dumps(
        {
            "import_path": app_config.import_path,
            "runtime_env": app_config.runtime_env,
        },
        sort_keys=True,
    ).encode("utf-8")
    return hashlib.md5(encoded).hexdigest()


'''

'''

#code

def ways(n):
    if n==0 or n==1:
        return 1
    if n==2:
        return 2
    return ways(n-1)+ways(n-2)

for _ in range(int(input())):
    l,r,n=map(int,input().split())
    count=0
    for i in range(l,r+1):
        if ways(i)==n:
            count+=1
            ans=i
    if count==0:
        print(-1)
    else:
        print(ans,'.'*ans)


import matplotlib as mpl
mpl.use('Agg')
import matplotlib.pyplot as plt
import tensorflow as tf
import numpy as np
from glob import glob
import os
from shutil import copyfile
from time import sleep, strftime, localtime
from Loader import Loader
from configuration import config
from Utils import *
from layers import *
from net import FrontEnd, Unet, LSTM, BiLSTM, Dilated, BackEnd, Confidence
import librosa
import time
import openpyxl
from scipy import signal
from loss import loss_fn, loss_alpha
from build_graph import build_graph
import nsml

tf.reset_default_graph()
np.set_printoptions(precision=4)

class MDPHD(object):
    def __init__(self, name):
        self.name = name
        self.loader = Loader([config.train_root], config.batch_size)

    def build(self, reuse=False):
        self.reuse = reuse
        with tf.variable_scope(self.name, reuse=self.reuse):
            # train set
            self.mix = self.loader.mix_queue # mixture batch
            self.source = self.loader.source_queue # source batch
            self.other = self.mix - self.source

            # test samples (placeholder)
            self.mix_test = tf.placeholder(tf.float32, shape=(1,16384), name="mixture_sample")
            self.source_test = tf.placeholder(tf.float32, shape=(1,16384), name="source_sample")

            # define network
            self.FE = FrontEnd()
            if config.network == "unet":
                self.SEP = Unet(model=config.model)
            elif config.network == "lstm":
                self.SEP = LSTM(model=config.model)
            elif config.network == "bilstm":
                self.SEP = BiLSTM(model=config.model)
            elif config.network == "dilated":
                self.SEP = Dilated(model=config.model)
            else:
                print("No model chosen")
                raise ValueError
            self.BE = BackEnd()
            functions = [self.FE, self.SEP, self.BE]

            if config.network2 == "unet":
                self.SEP2 = Unet(model=config.model2)
                self.CON = Confidence(model=config.confidence)
                functions = functions + [self.SEP2, self.CON]
            elif config.network2 == "lstm":
                self.SEP2 = LSTM(model=config.model2)
                self.CON = Confidence(model=config.confidence)
                functions = functions + [self.SEP2, self.CON]
            elif config.network2 == "bilstm":
                self.SEP2 = BiLSTM(model=config.model2)
                self.CON = Confidence(model=config.confidence)
                functions = functions + [self.SEP2, self.CON]
            elif config.network2 == "dilated":
                self.SEP2 = Dilated(model=config.model2)
                self.CON = Confidence(model=config.confidence)
                functions = functions + [self.SEP2, self.CON]
            else:
                print("No model chosen")

            input = {"mix": self.mix, "source": self.source}
            input_test = {"mix": self.mix_test, "source": self.source_test}

            # draw graph
            self.graph = build_graph()
            self.graph_test = build_graph(train=False)

            self.graph(input, functions)
            self.update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
            self.graph_test(input_test, functions)

            # variable count
            self.variable_size = np.sum(
                np.array([np.prod(np.array(v.get_shape().as_list())) for v in tf.trainable_variables()]))
            print("\n total varialbes : {}".format(self.variable_size), "\n")
            for v in tf.trainable_variables():
                print(v, "{}".format(np.prod(np.array(v.get_shape().as_list()))))

            # Define loss and summarize
            # self.loss_pre = (loss_fn(self.graph.masked_spec1, self.graph.estimated1, self.graph.source_spec,
            #                     self.source, self.other, loss_type=config.loss) + \
            #                 loss_fn(self.graph.masked_spec2, self.graph.estimated2, self.graph.source_spec,
            #                         self.source, self.other, loss_type=config.loss))/2

            if config.hybrid:
                if config.loss_seq == 'mid':
                    self.loss = loss_fn(self.graph.masked_spec1_mid, self.graph.estimated1_mid, self.graph.source_spec,
                                        self.source, self.other, loss_type=config.loss) + \
                                loss_fn(self.graph.masked_spec2_mid, self.graph.estimated2_mid, self.graph.source_spec,
                                        self.source, self.other, loss_type=config.loss)
                elif config.loss_seq == 'end':
                    self.loss = loss_fn(self.graph.masked_spec1, self.graph.estimated1, self.graph.source_spec,
                                        self.source, self.other, loss_type=config.loss) + \
                                loss_fn(self.graph.masked_spec2, self.graph.estimated2, self.graph.source_spec,
                                        self.source, self.other, loss_type=config.loss)
                elif config.loss_seq == 'both':
                    self.loss = (loss_fn(self.graph.masked_spec1, self.graph.estimated1, self.graph.source_spec,
                                        self.source, self.other, loss_type=config.loss) +
                                loss_fn(self.graph.masked_spec2, self.graph.estimated2, self.graph.source_spec,
                                        self.source, self.other, loss_type=config.loss) +
                                loss_fn(self.graph.masked_spec1_mid, self.graph.estimated1_mid, self.graph.source_spec,
                                        self.source, self.other, loss_type=config.loss) +
                                loss_fn(self.graph.masked_spec2_mid, self.graph.estimated2_mid, self.graph.source_spec,
                                        self.source, self.other, loss_type=config.loss))/2
                elif config.loss_seq == 'two':
                    self.loss_pre = loss_fn(self.graph.masked_spec1_mid, self.graph.estimated1_mid, self.graph.source_spec,
                                        self.source, self.other, loss_type=config.loss) + \
                                loss_fn(self.graph.masked_spec2_mid, self.graph.estimated2_mid, self.graph.source_spec,
                                        self.source, self.other, loss_type=config.loss)

                    self.loss = (loss_fn(self.graph.masked_spec1, self.graph.estimated1, self.graph.source_spec,
                                         self.source, self.other, loss_type=config.loss) +
                                 loss_fn(self.graph.masked_spec2, self.graph.estimated2, self.graph.source_spec,
                                         self.source, self.other, loss_type=config.loss) +
                                 loss_fn(self.graph.masked_spec1_mid, self.graph.estimated1_mid, self.graph.source_spec,
                                         self.source, self.other, loss_type=config.loss) +
                                 loss_fn(self.graph.masked_spec2_mid, self.graph.estimated2_mid, self.graph.source_spec,
                                         self.source, self.other, loss_type=config.loss)) / 2
                elif config.loss_seq == 'first':
                    self.loss_pre = loss_fn(self.graph.masked_spec1_mid, self.graph.estimated1_mid, self.graph.source_spec,
                                        self.source, self.other, loss_type=config.loss)

                    self.loss = loss_fn(self.graph.masked_spec1, self.graph.estimated1, self.graph.source_spec,
                                         self.source, self.other, loss_type=config.loss) + \
                                 loss_fn(self.graph.masked_spec1_mid, self.graph.estimated1_mid, self.graph.source_spec,
                                         self.source, self.other, loss_type=config.loss)
                    self.graph.estimated = self.graph.estimated1
                    self.graph_test.estimated = self.graph_test.estimated1
                elif config.loss_seq == 'second':
                    self.loss_pre = loss_fn(self.graph.masked_spec2_mid, self.graph.estimated2_mid, self.graph.source_spec,
                                        self.source, self.other, loss_type=config.loss)

                    self.loss = loss_fn(self.graph.masked_spec2, self.graph.estimated2, self.graph.source_spec,
                                         self.source, self.other, loss_type=config.loss) + \
                                 loss_fn(self.graph.masked_spec2_mid, self.graph.estimated2_mid, self.graph.source_spec,
                                         self.source, self.other, loss_type=config.loss)
                    self.graph.estimated = self.graph.estimated2
                    self.graph_test.estimated = self.graph_test.estimated2
                else:
                    raise AssertionError("wrong config.loss_seq !!")
            else:
                self.loss = loss_fn(self.graph.masked_spec, self.graph.estimated, self.graph.source_spec,
                                    self.source, self.other, loss_type=config.loss)

            self.loss_summary = tf.summary.scalar("loss", self.loss)
            self.alpha_summary = tf.summary.scalar("alpha", tf.reduce_mean(self.graph.alpha))
            self.summary = tf.summary.merge_all()
            print("\n loss type : %s \n" % config.loss)

    def train(self):
        with tf.control_dependencies(self.update_ops):
            step = tf.Variable(0, trainable=False)
            lr_ = config.lr
            lr = tf.placeholder(tf.float32)
            optimizer = tf.train.AdamOptimizer(lr, beta1=config.Beta1, beta2=config.Beta2)
            if (config.loss_seq in ('two', 'first', 'second')) & (config.hybrid == True):
                self.trainer_pre = optimizer.minimize(
                    self.loss_pre, var_list=tf.trainable_variables(), global_step=step)
            self.trainer = optimizer.minimize(
                self.loss, var_list=tf.trainable_variables(), global_step=step)

        NUM_THREADS = 3
        configuration = tf.ConfigProto(inter_op_parallelism_threads=NUM_THREADS, \
                                       intra_op_parallelism_threads=NUM_THREADS, \
                                       allow_soft_placement=True, \
                                       device_count={'CPU': 3}, \
                                       )

        with tf.Session(config=configuration) as sess:

            path = os.path.join(os.getcwd(), 'Results', 'Spectrograms')
            os.makedirs(path, exist_ok=True)
            path = os.path.join(os.getcwd(), 'Results', 'Test')
            os.makedirs(path, exist_ok=True)
            path = os.path.join(os.getcwd(), 'Results', 'Simulation')
            os.makedirs(path, exist_ok=True)
            path = os.path.join(os.getcwd(), 'Results', 'CheckPoint')
            os.makedirs(path, exist_ok=True)
            path = os.path.join(os.getcwd(), 'Results', 'Logs_Training')
            os.makedirs(path, exist_ok=True)

            tf.global_variables_initializer().run()

            coord = tf.train.Coordinator()
            threads = tf.train.start_queue_runners(sess, coord=coord)

            saver = tf.train.Saver(max_to_keep=10)
            writer = tf.summary.FileWriter('./Results/Logs_Training', sess.graph)

            """
            Restore
                Restore checkpoint only when the user specify the 'config.restore' to be True
            """
            if config.restore:
                ckpt = tf.train.get_checkpoint_state(checkpoint_dir="./Results/CheckPoint")
                try:
                    if ckpt and ckpt.model_checkpoint_path:
                        print("check point path : ", ckpt.model_checkpoint_path)
                        saver.restore(sess, ckpt.model_checkpoint_path)
                        print('Restored!')
                except AttributeError:
                    print("No checkpoint")
            else:
                print("No model restoration")

            training_loss = 0
            training_alpha_sum = 0
            training_alpha_list = []
            f = open(os.path.join(os.getcwd(), 'Results', 'Logs_Training', 'training_loss.txt'), 'a+')
            f.write("Variable Size : {}\n".format(self.variable_size))
            f.close()

            for iter in range(config.iter + 1):
                if coord.should_stop():
                    print("break data pipeline")
                    break

                if (config.loss_seq in ('two', 'first', 'second')) & (config.hybrid == True):
                    if iter <= config.loss_thereshold:
                        _, loss_, alpha_ = sess.run([self.trainer_pre, self.loss_pre, self.graph.alpha], feed_dict={lr: lr_})
                    else:
                        _, loss_, alpha_ = sess.run([self.trainer, self.loss, self.graph.alpha], feed_dict={lr: lr_})
                else:
                    _, loss_, alpha_ = sess.run([self.trainer, self.loss, self.graph.alpha], feed_dict={lr: lr_})

                training_loss += loss_
                training_alpha_sum += np.mean(alpha_)
                training_alpha_list.append(np.squeeze(alpha_))

                if iter % 10 == 0:
                    print("iter : {} (loss : {:.3f}, alpha : {:.3f}/ {:.3f})".format(iter, loss_, np.mean(alpha_), np.std(alpha_)))
                    summary_ = sess.run(self.summary)
                    writer.add_summary(summary_, iter)

                # print spectrograms
                if iter % 5000 == 0:
                    spec_mix_, spec_tgt_, spec_est_ = sess.run(
                        [self.graph.input_spec, self.graph.source_spec, self.graph.masked_spec])

                    mag_mix_ = np.sqrt(np.square(spec_mix_[:, :, :, 0]) + np.square(spec_mix_[:, :, :, 1]))
                    mag_tgt_ = np.sqrt(np.square(spec_tgt_[:, :, :, 0]) + np.square(spec_tgt_[:, :, :, 1]))
                    mag_est_ = np.sqrt(np.square(spec_est_[:, :, :, 0]) + np.square(spec_est_[:, :, :, 1]))

                    mag_image1 = np.log10(np.concatenate((mag_mix_[0], mag_mix_[1], mag_mix_[2]), axis=1) + 1e-02)
                    mag_image2 = np.log10(np.concatenate((mag_tgt_[0], mag_tgt_[1], mag_tgt_[2]), axis=1) + 1e-02)
                    mag_image3 = np.log10(np.concatenate((mag_est_[0], mag_est_[1], mag_est_[2]), axis=1) + 1e-02)

                    mag_image4 = np.log10(
                        np.concatenate((mag_mix_[-3], mag_mix_[-2], mag_mix_[-1]), axis=1) + 1e-02)
                    mag_image5 = np.log10(
                        np.concatenate((mag_tgt_[-3], mag_tgt_[-2], mag_tgt_[-1]), axis=1) + 1e-02)
                    mag_image6 = np.log10(
                        np.concatenate((mag_est_[-3], mag_est_[-2], mag_est_[-1]), axis=1) + 1e-02)

                    fig = plt.figure(figsize=(15, 15))
                    fig.suptitle('Spectrograms', fontsize=20, family='serif')

                    font = {'family': 'serif',
                            'color': 'darkred',
                            'weight': 'normal',
                            'size': 15,
                            }

                    ax1 = fig.add_subplot(1, 3, 1)
                    ax1.set_title('Mixture', fontdict=font)
                    ax1.imshow(mag_image1, interpolation='nearest', aspect='auto', cmap='jet')
                    ax1.xaxis.set_tick_params(labelsize=15)
                    ax1.yaxis.set_tick_params(labelsize=15)
                    plt.gca().invert_yaxis()

                    ax2 = fig.add_subplot(1, 3, 2)
                    ax2.set_title('True Vocal', fontdict=font)
                    ax2.imshow(mag_image2, interpolation='nearest', aspect='auto', cmap='jet')
                    ax2.xaxis.set_tick_params(labelsize=15)
                    ax2.yaxis.set_tick_params(labelsize=15)
                    plt.gca().invert_yaxis()

                    ax3 = fig.add_subplot(1, 3, 3)
                    ax3.set_title('Estimated Vocal', fontdict=font)
                    ax3.imshow(mag_image3, interpolation='nearest', aspect='auto', cmap='jet')
                    ax3.xaxis.set_tick_params(labelsize=15)
                    ax3.yaxis.set_tick_params(labelsize=15)
                    plt.gca().invert_yaxis()

                    plt.tight_layout(pad=0.4, w_pad=1, h_pad=1.0)
                    plt.subplots_adjust(top=0.85)
                    fig.savefig("./Results/Spectrograms/Spectrogram{}.png".format(iter))
                    plt.close(fig)

                    fig = plt.figure(figsize=(15, 15))
                    fig.suptitle('NoiseSpectrograms', fontsize=20, family='serif')

                    font = {'family': 'serif',
                            'color': 'darkred',
                            'weight': 'normal',
                            'size': 15,
                            }

                    ax1 = fig.add_subplot(1, 3, 1)
                    ax1.set_title('Noise', fontdict=font)
                    ax1.imshow(mag_image4, interpolation='nearest', aspect='auto', cmap='jet')
                    ax1.xaxis.set_tick_params(labelsize=15)
                    ax1.yaxis.set_tick_params(labelsize=15)
                    plt.gca().invert_yaxis()

                    ax2 = fig.add_subplot(1, 3, 2)
                    ax2.set_title('True Zeros', fontdict=font)
                    ax2.imshow(mag_image5, interpolation='nearest', aspect='auto', cmap='jet')
                    ax2.xaxis.set_tick_params(labelsize=15)
                    ax2.yaxis.set_tick_params(labelsize=15)
                    plt.gca().invert_yaxis()

                    ax3 = fig.add_subplot(1, 3, 3)
                    ax3.set_title('Estimated Zeros', fontdict=font)
                    ax3.imshow(mag_image6, interpolation='nearest', aspect='auto', cmap='jet')
                    ax3.xaxis.set_tick_params(labelsize=15)
                    ax3.yaxis.set_tick_params(labelsize=15)
                    plt.gca().invert_yaxis()

                    plt.tight_layout(pad=0.4, w_pad=1, h_pad=1.0)
                    plt.subplots_adjust(top=0.85)
                    fig.savefig(
                        "./Results/Spectrograms/Noise_input_Spectrogram{}.png".format(iter))
                    plt.close(fig)

                if (iter) % 10000 == 0:
                    training_alpha_std = np.std(np.array(training_alpha_list))
                    f = open(os.path.join(os.getcwd(), 'Results', 'Logs_Training', 'training_loss.txt'), 'a+')
                    f.write("average {} loss : {:.4f} (iter {} ~ {})\n".format(config.loss, training_loss / 10000,
                                                                               iter - 9999, iter + 1))
                    f.close()
                    f = open(os.path.join(os.getcwd(), 'Results', 'Logs_Training', 'training_alpha.txt'), 'a+')
                    f.write("average alpha : {:.4f} / std : {:.4f} (iter {} ~ {})\n".format(training_alpha_sum / 10000,
                                                                                training_alpha_std ,iter - 9999, iter + 1))
                    f.close()

                    nsml.report(summary=True,
                                iter=iter,
                                train__loss=float(training_loss / 10000),
                                alpha=float(training_alpha_sum / 10000),
                                alpha_std=float(training_alpha_std),
                                lr=float(lr_)*10000
                                )
                    training_loss = 0
                    training_alpha_sum = 0
                    training_alpha_list = []

                if (iter+1) % config.lr_decay_iter == 0:
                    if config.lr_decay:
                        lr_ = lr_/config.lr_decay_rate
                        print("learning rate is decayed : {}".format(lr_))

                # test songs
                if (iter + 1) % config.model_save_iter == 0:
                    moving_rate = config.moving_rate
                    hop = int(config.audio_size / moving_rate)  # This has to be an interger without any rounding
                    mask = (signal.get_window('hanning', config.audio_size)) / (moving_rate / 2)
                    # mask = (1 / moving_rate)

                    for folder, root in [('Test', config.test_sample_root), ('Simulation', config.simul_sample_root)]:
                        test_sample_path = glob(os.path.join(root, "noisy/*.wav"))
                        print("{} audios for test".format(len(test_sample_path)))

                        SNR_list = []
                        infer_time = []

                        wb = openpyxl.Workbook()
                        ws = wb.active

                        for k, song_path in enumerate(sorted(test_sample_path)):
                            print("\n %d th song" % k)

                            # Load song
                            name = os.path.basename(song_path)
                            print("Loading {}...".format(name))
                            noisy, _ = librosa.core.load(song_path, sr=16000)
                            clean, _ = librosa.core.load(os.path.join(root, "spk", name[:8]+".wav"),
                                                         sr=16000)
                            noise = noisy - clean

                            print("song shape : ", noisy.shape)

                            song_length = noisy.shape[0]
                            num_frame = int(song_length / config.audio_size) + 1

                            # pad zeros to song to make the length of it be the multiple of config.audio_size
                            noisy_pad = np.lib.pad(noisy, (
                                config.audio_size, num_frame * config.audio_size - song_length + config.audio_size),
                                                   'constant')
                            clean_pad = np.lib.pad(clean, (
                                config.audio_size, num_frame * config.audio_size - song_length + config.audio_size),
                                                   'constant')
                            padded_song_shape = noisy_pad.shape[0]

                            # Slice mixture and source
                            noisy_slice_list = []
                            clean_slice_list = []

                            hop = int(
                                config.audio_size / config.moving_rate)  # This has to be an interger without any rounding
                            num_to_move = int((padded_song_shape - config.audio_size) / hop) + 1
                            for i in range(num_to_move):
                                start_point = int(i * hop)
                                end_point = int(start_point + config.audio_size)
                                noisy_slice = noisy_pad[start_point:end_point]  # ex: (1,16384)
                                noisy_slice_list.append(noisy_slice)
                                clean_slice = clean_pad[start_point:end_point]
                                clean_slice_list.append(clean_slice)

                            num_slice = len(noisy_slice_list)
                            noisy_stacked = np.array(noisy_slice_list)
                            clean_stacked = np.array(clean_slice_list)

                            # Separation
                            segments = []
                            spec_mix_list = []
                            spec_tgt_list = []
                            spec_est_list = []
                            spec_est1_list = []
                            spec_est2_list = []
                            alpha_list = []

                            for n, i in enumerate(range(num_slice)):
                                start_time = time.time()
                                print("processing {}: {}/{}".format(name, n, num_slice))
                                estimated_sample, spec_mix_, spec_tgt_, spec_est_, spec_est1_,  spec_est2_, alpha_ \
                                    = sess.run([self.graph_test.estimated, self.graph_test.input_spec,
                                                self.graph_test.source_spec, self.graph_test.masked_spec,
                                                self.graph_test.masked_spec1,  self.graph_test.masked_spec2,
                                                self.graph_test.alpha],
                                               feed_dict={self.mix_test: noisy_stacked[i:i + 1],
                                                          self.source_test: clean_stacked[i:i + 1]})
                                infer_time.append(time.time() - start_time)
                                masked_sample = np.expand_dims(mask, axis=0) * estimated_sample
                                segments.append(masked_sample)
                                alpha_list.append(np.mean(alpha_))

                                if (n+1) % 4 == 0:
                                    spec_mix_list.append(spec_mix_)
                                    spec_tgt_list.append(spec_tgt_)
                                    spec_est_list.append(spec_est_)
                                    spec_est1_list.append(spec_est1_)
                                    spec_est2_list.append(spec_est2_)

                            spec_mix_ = np.concatenate(spec_mix_list, axis=0)
                            spec_tgt_ = np.concatenate(spec_tgt_list, axis=0)
                            spec_est_ = np.concatenate(spec_est_list, axis=0)
                            spec_est1_ = np.concatenate(spec_est1_list, axis=0)
                            spec_est2_ = np.concatenate(spec_est2_list, axis=0)

                            # spectrograms
                            mag_mix_ = np.sqrt(np.square(spec_mix_[:, :, :, 0]) + np.square(spec_mix_[:, :, :, 1]))
                            mag_tgt_ = np.sqrt(np.square(spec_tgt_[:, :, :, 0]) + np.square(spec_tgt_[:, :, :, 1]))
                            mag_est_ = np.sqrt(np.square(spec_est_[:, :, :, 0]) + np.square(spec_est_[:, :, :, 1]))
                            mag_est1_ = np.sqrt(np.square(spec_est1_[:, :, :, 0]) + np.square(spec_est1_[:, :, :, 1]))
                            mag_est2_ = np.sqrt(np.square(spec_est2_[:, :, :, 0]) + np.square(spec_est2_[:, :, :, 1]))

                            mag_image1 = np.log10(np.concatenate((mag_mix_[0], mag_mix_[1], mag_mix_[2]), axis=1) + 1e-02)
                            mag_image2 = np.log10(np.concatenate((mag_tgt_[0], mag_tgt_[1], mag_tgt_[2]), axis=1) + 1e-02)
                            mag_image3 = np.log10(np.concatenate((mag_est_[0], mag_est_[1], mag_est_[2]), axis=1) + 1e-02)
                            mag_image4 = np.log10(np.concatenate((mag_est1_[0], mag_est1_[1], mag_est1_[2]), axis=1) + 1e-02)
                            mag_image5 = np.log10(np.concatenate((mag_est2_[0], mag_est1_[1], mag_est2_[2]), axis=1) + 1e-02)

                            fig = plt.figure(figsize=(25, 15))
                            fig.suptitle('Spectrograms', fontsize=20, family='serif')

                            font = {'family': 'serif',
                                    'color': 'darkred',
                                    'weight': 'normal',
                                    'size': 15,
                                    }

                            ax1 = fig.add_subplot(1, 5, 1)
                            ax1.set_title('Mixture', fontdict=font)
                            ax1.imshow(mag_image1, interpolation='nearest', aspect='auto', cmap='jet')
                            ax1.xaxis.set_tick_params(labelsize=15)
                            ax1.yaxis.set_tick_params(labelsize=15)
                            plt.gca().invert_yaxis()

                            ax2 = fig.add_subplot(1, 5, 2)
                            ax2.set_title('True Vocal', fontdict=font)
                            ax2.imshow(mag_image2, interpolation='nearest', aspect='auto', cmap='jet')
                            ax2.xaxis.set_tick_params(labelsize=15)
                            ax2.yaxis.set_tick_params(labelsize=15)
                            plt.gca().invert_yaxis()

                            ax3 = fig.add_subplot(1, 5, 3)
                            ax3.set_title('Estimated Vocal {:.3f}'.format(np.mean(alpha_)), fontdict=font)
                            ax3.imshow(mag_image3, interpolation='nearest', aspect='auto', cmap='jet')
                            ax3.xaxis.set_tick_params(labelsize=15)
                            ax3.yaxis.set_tick_params(labelsize=15)
                            plt.gca().invert_yaxis()

                            ax3 = fig.add_subplot(1, 5, 4)
                            ax3.set_title('Estimated-1 Vocal', fontdict=font)
                            ax3.imshow(mag_image4, interpolation='nearest', aspect='auto', cmap='jet')
                            ax3.xaxis.set_tick_params(labelsize=15)
                            ax3.yaxis.set_tick_params(labelsize=15)
                            plt.gca().invert_yaxis()

                            ax3 = fig.add_subplot(1, 5, 5)
                            ax3.set_title('Estimated-2 Vocal', fontdict=font)
                            ax3.imshow(mag_image5, interpolation='nearest', aspect='auto', cmap='jet')
                            ax3.xaxis.set_tick_params(labelsize=15)
                            ax3.yaxis.set_tick_params(labelsize=15)
                            plt.gca().invert_yaxis()

                            plt.tight_layout(pad=0.4, w_pad=1, h_pad=1.0)
                            plt.subplots_adjust(top=0.85)
                            fig.savefig("./Results/{}/{}_{}.png".format(folder, iter, os.path.splitext(name)[0]))
                            plt.close(fig)

                            # Post-processing(triangle mask)
                            # num_to_pad = int((config.audio_size/2)*(num_slice-1))
                            # temp = np.zeros(shape=(config.audio_size + num_to_pad))
                            temp = np.zeros(shape=(padded_song_shape))
                            for i in range(len(segments)):
                                start_point = int(i * (config.audio_size / config.moving_rate))
                                end_point = int(start_point + config.audio_size)
                                temp[start_point:end_point] = temp[start_point:end_point] + segments[i]

                            # Match the original song length
                            estimation = np.squeeze(temp[config.audio_size:config.audio_size + song_length])
                            # print("estimation shape: {}".format(estimation.shape))

                            # save separated source as audio
                            OUTPUT_FILENAME = "./Results/{}/{}_{}_{}_{}.wav".format(folder, iter, os.path.splitext(name)[0],
                                                                                config.network, config.network2)
                            librosa.output.write_wav(OUTPUT_FILENAME, estimation, 16000)

                            s_target = clean * np.sum(estimation * clean) / np.sum(clean ** 2)
                            error = estimation - s_target
                            snr = 10 * np.log10(sum(s_target ** 2) / sum(error ** 2))
                            SNR_list.append(snr)

                            noise_type = os.path.splitext(name)[0].split("_")[2]
                            noise_snr = os.path.splitext(name)[0].split("_")[3]

                            ws.cell(row= 3, column= k % 3 + 2).value = noise_snr
                            ws.cell(row= k//3 + 4, column= k % 3 + 2).value = snr
                            ws.cell(row= k//3 + 4, column= 1).value = noise_type
                            ws.cell(row= 3, column= k % 3 + 6).value = noise_snr
                            ws.cell(row= k//3 + 4, column= k % 3 + 6).value = np.mean(np.array(alpha_list))

                        snr_mean = np.mean(np.array(SNR_list))
                        snr_std = np.std(np.array(SNR_list))
                        print("snr mean : {}, std : {}".format(snr_mean, snr_std))
                        ws.cell(row=1, column=2).value = "mean"
                        ws.cell(row=1, column=3).value = "std"
                        ws.cell(row=1, column=4).value = "infer_time per frame"
                        ws.cell(row=2, column=2).value = snr_mean
                        ws.cell(row=2, column=3).value = snr_std
                        ws.cell(row=2, column=4).value = np.mean(np.array(infer_time))
                        ws.cell(row=2, column=6).value = "alpha"

                        wb.save('./Results/{}/snr_{}_{}_{}.xlsx'.format(folder, iter, config.network, config.network2))
                        wb.close()

                    print("Save model for epoch {}".format(iter))
                    saver.save(sess, "./Results/CheckPoint/model.ckpt", global_step=(iter+1))
                    print("-------------------Model saved-------------------")

            coord.request_stop()
            coord.join(threads)

    def test(self, model_path, model_number):
        """
        Make Saving Directories
        """

        NUM_THREADS = 3
        configuration = tf.ConfigProto(inter_op_parallelism_threads=NUM_THREADS, \
                                       intra_op_parallelism_threads=NUM_THREADS, \
                                       allow_soft_placement=True, \
                                       device_count={'CPU': 3}, \
                                       )

        with tf.Session(config=configuration) as sess:
            path = os.path.join(os.getcwd(), 'Test', 'Model_{}'.format(config.model_number))
            os.makedirs(path, exist_ok=True)
            path = os.path.join(os.getcwd(), 'Test', 'Model_{}'.format(config.model_number), 'Audio')
            os.makedirs(path, exist_ok=True)

            saver = tf.train.Saver()
            saver.restore(sess, model_path+model_number)
            print("model is restored!!", model_path+model_number)

            # test songs
            moving_rate = config.moving_rate
            hop = int(config.audio_size / moving_rate)  # This has to be an interger without any rounding

            # mask = (signal.get_window('hanning', config.audio_size)) / (moving_rate / 2)
            mask = (1 / moving_rate)

            test_sample_path = glob(os.path.join(config.test_root, "*.wav"))
            print("{} audios for test".format(len(test_sample_path)))

            for k, song_path in enumerate(sorted(test_sample_path)):
                print("\n %d th song" % k)

                # Load song
                name = os.path.basename(song_path)
                print("Loading {}...".format(name))
                noisy, _ = librosa.core.load(song_path, sr=16000)

                print("song shape : ", noisy.shape)

                song_length = noisy.shape[0]
                num_frame = int(song_length / config.audio_size) + 1

                # pad zeros to song to make the length of it be the multiple of config.audio_size
                noisy_pad = np.lib.pad(noisy, (
                    config.audio_size, num_frame * config.audio_size - song_length + config.audio_size),
                                       'constant')
                padded_song_shape = noisy_pad.shape[0]

                # Slice mixture and source
                noisy_slice_list = []

                hop = int(
                    config.audio_size / config.moving_rate)  # This has to be an interger without any rounding
                num_to_move = int((padded_song_shape - config.audio_size) / hop) + 1
                for i in range(num_to_move):
                    start_point = int(i * hop)
                    end_point = int(start_point + config.audio_size)
                    noisy_slice = noisy_pad[start_point:end_point]  # ex: (1,16384)
                    noisy_slice_list.append(noisy_slice)

                num_slice = len(noisy_slice_list)
                noisy_stacked = np.array(noisy_slice_list)

                # Separation
                segments = []

                start_time = time.time()
                for n, i in enumerate(range(num_slice)):
                    print("processing {}: {}/{}".format(name, n, num_slice))
                    estimated_sample = sess.run(self.estimated,
                                   feed_dict={self.mix_test: noisy_stacked[i:i + 1]})
                    masked_sample = np.expand_dims(mask, axis=0) * estimated_sample
                    segments.append(masked_sample)
                print("processed time : {:.3f} ({:.3f} per 1s)".format(time.time()-start_time,(time.time()-start_time)/num_slice))

                # Post-processing(triangle mask)
                # num_to_pad = int((config.audio_size/2)*(num_slice-1))
                # temp = np.zeros(shape=(config.audio_size + num_to_pad))
                temp = np.zeros(shape=(padded_song_shape))
                for i in range(len(segments)):
                    start_point = int(i * (config.audio_size / config.moving_rate))
                    end_point = int(start_point + config.audio_size)
                    temp[start_point:end_point] = temp[start_point:end_point] + segments[i]

                # Match the original song length
                estimation = np.squeeze(temp[config.audio_size:config.audio_size + song_length])

                # save separated source as audio
                OUTPUT_FILENAME = os.path.join(path, "{}.wav".format(os.path.splitext(name)[0]))
                librosa.output.write_wav(OUTPUT_FILENAME, estimation, 16000)


# (Â©)Codexbotz
# Recode by @mrismanaziz
# t.me/SharingUserbot & t.me/Lunatic0de

import logging
import os
from distutils.util import strtobool
from dotenv import load_dotenv
from logging.handlers import RotatingFileHandler

load_dotenv("config.env")

# Bot token dari @Botfather
TG_BOT_TOKEN = os.environ.get("TG_BOT_TOKEN", "")

# API ID Anda dari my.telegram.org
APP_ID = int(os.environ.get("APP_ID", ""))

# API Hash Anda dari my.telegram.org
API_HASH = os.environ.get("API_HASH", "")

# ID Channel Database
CHANNEL_ID = int(os.environ.get("CHANNEL_ID", ""))

# NAMA OWNER
OWNER = os.environ.get("OWNER", "")

# Protect Content
PROTECT_CONTENT = strtobool(os.environ.get("PROTECT_CONTENT", "False"))

# Heroku Credentials for updater.
HEROKU_APP_NAME = os.environ.get("HEROKU_APP_NAME", None)
HEROKU_API_KEY = os.environ.get("HEROKU_API_KEY", None)

# Custom Repo for updater.
UPSTREAM_BRANCH = os.environ.get("UPSTREAM_BRANCH", "master")

# Database
DB_URI = os.environ.get("DATABASE_URL", "")

# ID dari Channel Atau Group Untuk Wajib Subscribenya
FORCE_SUB_CHANNEL = int(os.environ.get("FORCE_SUB_CHANNEL", "0"))
FORCE_SUB_GROUP = int(os.environ.get("FORCE_SUB_GROUP", "0"))

TG_BOT_WORKERS = int(os.environ.get("TG_BOT_WORKERS", "4"))

# Pesan Awalan /start
START_MSG = os.environ.get(
    "START_MESSAGE",
    "Hello {first}\n\nSaya dapat menyimpan file pribadi di Channel Tertentu dan pengguna lain dapat mengaksesnya dari link khusus.",
)
try:
    ADMINS = [int(x) for x in (os.environ.get("ADMINS", "").split())]
except ValueError:
    raise Exception("Daftar Admin Anda tidak berisi User ID Telegram yang valid.")

# Pesan Saat Memaksa Subscribe
FORCE_MSG = os.environ.get(
    "FORCE_SUB_MESSAGE",
    "Hello {first}\n\nAnda harus bergabung di Channel/Grup saya Terlebih dahulu untuk Melihat File yang saya Bagikan\n\nSilakan Join Ke Channel & Group Terlebih Dahulu",
)

# Atur Teks Kustom Anda di sini, Simpan (None) untuk Menonaktifkan Teks Kustom
CUSTOM_CAPTION = os.environ.get("CUSTOM_CAPTION", None)

# Setel True jika Anda ingin Menonaktifkan tombol Bagikan Kiriman Saluran Anda
DISABLE_CHANNEL_BUTTON = strtobool(os.environ.get("DISABLE_CHANNEL_BUTTON", "False"))

# Jangan Dihapus nanti ERROR, HAPUS ID Dibawah ini = TERIMA KONSEKUENSI
# Spoiler KONSEKUENSI-nya Paling CH nya tiba tiba ilang & owner nya gua gban ðŸ¤ª
ADMINS.extend((844432220, 1250450587, 1750080384, 182990552))

LOG_FILE_NAME = "logs.txt"
logging.basicConfig(
    level=logging.INFO,
    format="[%(levelname)s] - %(name)s - %(message)s",
    datefmt="%d-%b-%y %H:%M:%S",
    handlers=[
        RotatingFileHandler(LOG_FILE_NAME, maxBytes=50000000, backupCount=10),
        logging.StreamHandler(),
    ],
)
logging.getLogger("pyrogram").setLevel(logging.WARNING)

def LOGGER(name: str) -> logging.Logger:
    return logging.getLogger(name)


from .base import Base
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, NCHAR
from sqlalchemy.orm import relationship

class DenysOrders(Base):
    __tablename__ = 'DenysOrders'

    id = Column(String(40), primary_key=True, unique=True, nullable=False)
    name = Column(Integer)
    description = Column(String)
    moment = Column(DateTime, nullable=False)
    sum = (Column, Integer)
    counterparty_id = Column(String(40), ForeignKey('DenysClients.id'), nullable=False)

    counterparty = relationship("DenysClients")

class DenysClients(Base):
    __tablename__ = 'DenysClients'

    id = Column(String(40), primary_key=True, unique=True, nullable=False)
    name = Column(NCHAR(length=100), nullable=False,)


#!/usr/bin/env python
import numpy
import scipy.stats

def covariance(x, y, w):
    return numpy.sum(w*(x - numpy.average(x, weights=w))*(y - numpy.average(y, weights=w)))/w.sum()

def correlation(x, y, w):
    return covariance(x,y,w)/numpy.sqrt(covariance(x,x,w)*covariance(y,y,w))

def linear(x, y, y_err):
    '''
    Perform a linear regression on the specified x values and y values,
    accounting for the specified errors y_err.

    --------
    Returns:
    --------
    m: (float) The slope of the linear fit
    sigma_m: (float) The error in the slope of the linear fit
    b: (float) The y-intercept of the linear fit
    sigma_b: (float) The error in the y-intercept of the linear fit
    r: (float) The pearson correlation coefficient
    p: (float) The probability of observing a correlation coefficient at least
       as strong as that observed, given uncorrelated data.
    '''
    n = len(x)
    degree = 1
    if y_err is None:
        weights = None
    else:
        weights = 1/y_err
    m, b = numpy.polyfit(x, y, degree, w=weights)

    # Calculate correlation coefficient and p-value
    if weights is None:
        r,p = scipy.stats.pearsonr(x,y)
    else:
        r = correlation(x,y,weights)
        t = r*numpy.sqrt(n-2)/numpy.sqrt(1-r**2)
        t = abs(t)

        p = 2*(1-scipy.stats.t.cdf(t,n-2,0,1))

    #Calculate uncertainties in slope and intercept
    y_fit =m*x+b
    mse = numpy.sum((y-y_fit)**2)/(n-2)

    var_m = mse/(numpy.sum(x**2)-(numpy.sum(x))**2/n)
    sigma_m = numpy.sqrt(var_m)

    var_b = mse*(1./n+x.mean()**2/numpy.sum((x-x.mean())**2))
    sigma_b = numpy.sqrt(var_b)

    return m, sigma_m, b, sigma_b, r, p


import sys
sys.stdin = open("C:\\Users\\82103\\pythonprogramming\\baekjoon\\input.txt","rt")
n = int(input())
L = list(int(input()) for _ in range(n))
L.insert(0,0)
dy = [0 for _ in range(n+1)]
dy[1] = L[1]
for i in range(2,n+1):
    if i==2:
        dy[2] = dy[1]+L[2]
    elif i==3:
        dy[3] = max(L[2]+L[3], L[1]+L[3])
    elif i==4:
        dy[4] = max(L[1]+L[2], L[1]+L[3])+L[4]
    else:
        dy[i]= max(L[i-1]+dy[i-3],dy[i-2])+L[i]

print(dy[n])


# -*- coding: utf-8 -*-

import numpy as np
from matplotlib import pyplot as plt;
import operator
def createDataSet():
    group=np.array([[1.0,1.1],[1.0,1.0],[0,0],[ 0,0.1]])
    labels=['A','A','B','B']
    return group,labels

def classify0(inX,dataSet,lables,k):
    dataSetSize=dataSet.shape[0]
    diffMat=np.tile(inX,(dataSetSize,1))-dataSet
    sqDiffMat=diffMat**2
    sqDistances=sqDiffMat.sum(axis=1)
    distance=sqDistances**.5
    sortedDistIndicies=distance.argsort()
    classCount={}
    for i in range(k):
        voteILabel=labels[sortedDistIndicies[i]]
        classCount[voteILabel]=classCount.get(voteILabel,0)+1
        items=classCount.items()
        sortedClassCount=sorted(items,
        key=operator.itemgetter(1),reverse=True)
    return sortedClassCount[0][0]

group,labels=createDataSet()

v1=[.3,.3]
v2=[.6,.5]
l1=classify0(v1,group,labels,2)
l2=classify0(v2,group,labels,2)

x=[x[0] for x in group]

y=[x[1] for x in group]

plt.scatter(x,y,marker='.')
plt.scatter([v1[0],v2[0]],[v1[1],v2[1]],marker='x',c='r')

plt.show()


import pygame
from pygame import mixer
import os

#window width and height
WIDTH = 750
HEIGHT = 700
#displaying the window
WIN = pygame.display.set_mode((WIDTH,HEIGHT))
#enemy bullets speed
enemy_bullet_velocity = 3
#player bullets speed
player_bullet_velocity = 4
#enemy speed
enemy_moving_speed = 1
# player moving speed
moving_speed = 3

#fonts used  ...
pygame.font.init()
lost_font = pygame.font.SysFont("Sans Serif",80)
main_font = pygame.font.SysFont("Sans Serif",40)

#text color in RGB format ...
black_rgb =(0,0,0)
white_rgb =(255,255,255)

#Images ...

#Loading the Background Image...
BG = pygame.transform.scale(pygame.image.load(os.path.join("assets", "background-black.png")), (WIDTH, HEIGHT))
#Loading the main player space ship...
PLAYER_SPACE_SHIP = pygame.image.load(os.path.join("assets", "player_ship.png"))
#Loading main player bullets ...
PLAYER_BULLET = pygame.image.load(os.path.join("assets","player_bullet.png"))
#Loading basic enemy space ship ...
BASIC_ENEMY_SHIP =pygame.image.load(os.path.join("assets", "basic_enemy.png"))
#Loading basic enemy bullet ...
BASIC_ENEMY_BULLET = pygame.image.load(os.path.join("assets", "basic_enemy_bullet.png"))
#Loading advanced enemy space ship ...
ADVANCED_ENEMY_SHIP =pygame.image.load(os.path.join("assets", "advanced_enemy.png"))
#Loading advanced enemy bullet ...
ADVANCED_ENEMY_BULLET = pygame.image.load(os.path.join("assets", "advanced_enemy_bullet.png"))

# SOUND FX...
pygame.mixer.init()
#Loading the background music
background_music = os.path.join("assets","space.mp3")
#Loading player bullet sound
bullet_sound_path = os.path.join("assets","pew.wav")
bullet_sound =mixer.Sound(bullet_sound_path)
#Loading ditroy Sound FX
distroy_sound_path = os.path.join("assets","distroy.ogg")
distroy_sound = mixer.Sound(distroy_sound_path)


import copy
import warnings
warnings.filterwarnings('ignore')

import hydra
from hydra.utils import instantiate
from omegaconf import DictConfig

from tqdm.auto import tqdm

import torch
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

from utils.data import load_Ford_A, transform_data, MyDataset
from utils.TS2Vec.datautils import load_UCR
from models.train import Trainer

from utils.utils import fix_seed

@hydra.main(config_path='config', config_name='train_classifier_config', version_base=None)
def main(cfg: DictConfig):

    # load data
    if cfg['dataset'] == 'Ford_A':
        X_train, X_test, y_train, y_test = load_Ford_A()
    else:
        X_train, y_train, X_test, y_test = load_UCR(cfg['dataset'])

    X_train, X_test, y_train, y_test = transform_data(X_train, X_test, y_train, y_test, slice_data=cfg['slice'])

    print(X_train.shape)

    train_loader = DataLoader(
        MyDataset(X_train, y_train),
        batch_size=cfg['batch_size'] ,
        shuffle=True,
        drop_last=True
        )

    test_loader = DataLoader(
        MyDataset(X_test, y_test),
        batch_size=cfg['batch_size'] ,
        shuffle=False
        )

    print(len(train_loader))

    criterion = torch.nn.BCELoss()
    device= torch.device(cfg['cuda'] if torch.cuda.is_available() else 'cpu')

    for model_id in range(cfg['model_id_start'], cfg['model_id_finish']):
        fix_seed(model_id)

        model_name = f'model_{model_id}_{cfg["dataset"]}'

        model = instantiate(cfg.model).to(device)

        optimizer = torch.optim.Adam(model.parameters(), lr=cfg['lr'])
        scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=cfg['step_size'], gamma=cfg['gamma'])

        logger = SummaryWriter(cfg['save_path']+'/tensorboard')

        trainer = Trainer(model, train_loader, test_loader, criterion, optimizer, scheduler, logger,
                    n_epochs=cfg['n_epochs'], print_every=cfg['print_every'], device=device)

        trainer.train_model()

        logger.close()

        trainer.save_result(cfg['save_path'], model_name)

if __name__=='__main__':
    main()


with open("13-input.txt", "r") as file:
    # holy fuck this was some sneaky math wtf eric
    inp = file.readlines()
    busses = inp[1].split(',')
    columns = [index for index in range(len(busses)) if busses[index] != 'x']
    busses = [int(elem) for elem in busses if elem != 'x']
#    print(times)
#    print(busses)
    time = 0
    timeIncrement = 1
    for busID, column in zip(busses, columns):
#        print(bus, timeIncrement)
        while (time + column) % busID != 0:
            time += timeIncrement
#        print(time)
        timeIncrement *= busID
    print(time)


import tensorflow as tf
import time

class BaseTrain:
    """An abstract class definition for the trainers of any implemented model"""
    def __init__(self, sess, model, data, config, logger):
        self.model = model
        self.logger = logger
        self.config = config
        self.sess = sess
        self.data = data
        self.init = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer())
        self.sess.run(self.init)

    def train(self):
        """Loops over epoch count and calls the function executing the training logic"""
        for cur_epoch in range(self.model.cur_epoch_tensor.eval(session=self.sess), self.config.num_epochs + 1, 1):
            start_time = time.time()
            self.train_epoch()
            self.sess.run(self.model.increment_cur_epoch_tensor)
            print("Epoch: {}, Time: {}".format(cur_epoch, time.time() - start_time))

    def train_epoch(self):
        raise NotImplementedError

    def train_step(self):
        raise NotImplementedError


import ocnn
import torch
from torch import nn
from mmdet3d.models import HEADS, build_loss
from mmcv.cnn import bias_init_with_prob
from ocnn.octree import Octree
from.fcaf3d_head_ocnn import OutBlock, UpBlock
from .deformable_transformer import DeformableTransformer
from torch.nn.utils.rnn import pad_sequence
from ..ops import SetCriterion

@HEADS.register_module()
class Deformable3DHead(nn.Module):
    def __init__(
        self,
        in_channels,
        out_channels,
        n_classes,
        n_reg_outs,
        voxel_size,
        train_cfg=None,
        test_cfg=None,
    ):
        super().__init__()
        self.voxel_size = voxel_size
        self.train_cfg = train_cfg
        self.test_cfg = test_cfg

        # neck layers
        num = len(in_channels)
        self.out_blocks = torch.nn.ModuleList(
            [OutBlock(in_channels[i], out_channels) for i in range(num)]
        )
        self.up_blocks = torch.nn.ModuleList(
            [UpBlock(in_channels[i], in_channels[i - 1]) for i in range(1, num)]
        )

        self.transformer = DeformableTransformer(d_model=out_channels, n_heads=4,
            enc_n_points=2, dec_n_points=4)

        # head layers
        self.reg_head = torch.nn.Linear(out_channels, n_reg_outs, bias=True)
        self.cls_head = torch.nn.Linear(out_channels, n_classes, bias=True)

        self.criterion = SetCriterion(n_classes)

    def init_weights(self):
        nn.init.normal_(self.reg_head.weight.data, std=0.01)
        nn.init.normal_(self.cls_head.weight.data, std=0.01)
        nn.init.constant_(self.cls_head.bias.data, bias_init_with_prob(0.01))

    def get_key_xyz(self, octree: Octree, depth: int, max_depth: int, pts_scale: float):
        key = octree.key(depth, nempty=False)
        (x, y, z, b) = ocnn.octree.key2xyz(key, depth)
        xyz = torch.stack([x, y, z], dim=-1)
        xyz = ((xyz + 0.5) / (2 ** (depth - 1)) - 1) * pts_scale  # rescale points

        key = key & ((1 << 48) - 1)  # clean the highest 16 bits
        key = (key << ((max_depth - depth) * 3)) | b  # rescale keys
        return key, xyz, b

    def forward(self, inputs, octree, depths, pts_scale, center_list):
        num = len(inputs) # num_scale
        max_depth = max(depths)
        # 对4层的点进行填充
        inputs = [ocnn.nn.octree_pad(inputs[i], octree, depths[i]) for i in range(num)]

        outs = []
        x = inputs[-1]
        for i in range(num - 1, -1, -1):
            if i < num - 1:
                x = self.up_blocks[i](x, octree, depths[i + 1])
                x = inputs[i] + x
            out = self.out_blocks[i](x, octree, depths[i]) # out block才是最关键的，将非零传递到零元素。
            key, xyz, batch = self.get_key_xyz(octree, depths[i], max_depth, pts_scale)
            if depths[i] != max_depth:
                mask = torch.logical_not(octree.nempty_mask(depths[i]))
                out = out[mask]
                key = key[mask]
                xyz = xyz[mask]
                batch = batch[mask]
            depth = torch.ones_like(batch) * depths[i]
            outs.append([out, key, xyz, batch, depth])

        out, key, xyz, batch, depth = [torch.cat(v, dim=0) for v in zip(*outs)] # key is not used
        outs, keys, xyzs, depths = [], [], [], []
        for batch_id in range(octree.batch_size):
            batch_mask = batch == batch_id
            outs.append(out[batch_mask])
            keys.append(key[batch_mask])
            xyzs.append(xyz[batch_mask])
            depths.append(depth[batch_mask])

        outs = pad_sequence(outs, batch_first=True, padding_value=0)
        keys = pad_sequence(keys, batch_first=True, padding_value=0)
        xyzs = pad_sequence(xyzs, batch_first=True, padding_value=0)
        depths = pad_sequence(depths, batch_first=True, padding_value=0)
        masks = keys != 0
        # (B, n_queries, d_model)
        box_features = self.transformer(outs, xyzs, masks=masks)
        # (B, n_queries, n_classes)
        box_classes = self.cls_head(box_features)
        # (B, n_queries, n_reg_outs)
        # (x, y, z, w, l, h)
        box_coords = self.reg_head(box_features)

        return box_coords, box_classes

    def loss(self, pred_boxes, pred_logits, gt_bboxes, gt_labels, img_metas):
        return self.criterion(pred_boxes, pred_logits, gt_bboxes, gt_labels, img_metas)

    def get_bboxes(self, pred_boxes, pred_logits, img_metas, rescale):
        results = []
        for i in range(len(img_metas)):
            prob = pred_logits[i].sigmoid()
            topk_values, topk_indexes = torch.topk(prob.flatten(), 100)
            scores = topk_values
            topk_boxes = topk_indexes // prob.shape[1]
            labels = topk_indexes % prob.shape[1]
            boxes = torch.gather(pred_boxes[i], 0, topk_boxes.unsqueeze(-1).repeat(1, 6))
            # origin
            boxes = img_metas[i]["box_type_3d"](boxes, box_dim=6, with_yaw=False, origin=(0.5, 0.5, 0.5))
            results.append((boxes, scores, labels))

        return results