# unlicense

# alpha world Animation Exporter

import os
import bpy
from math import degrees
from mathutils import *

"""
def get_pose_bone_matrix(pose_bone)
by: Graeme Hill's
http://graemehill.ca/exporting-armature-animation-with-the-blender-25-python-api/
"""

def get_pose_bone_matrix(pose_bone):
    if pose_bone.parent is None:
        return pose_bone.matrix_channel.transposed()
    else:
        return pose_bone.parent.matrix_channel.transposed() @ pose_bone.matrix_channel.transposed().inverted()

def export(filepath):
    file = open( filepath, 'w' )
    fscanf = file.write
    armature = [object for object in bpy.data.objects if object.type == 'ARMATURE']

    scene_context = bpy.context.scene

    if armature:
       for arm in armature:
           root = arm.data.bones
           range_frame = scene_context.frame_end - scene_context.frame_start + 1
           fscanf('frame ')
           if scene_context.frame_start == 0:
               fscanf('%i+0 \n' % (range_frame - 1))
           else:
               fscanf('%i \n' % range_frame)
           fscanf('fps ')
           fscanf('%i ' % scene_context.render.fps)
           fscanf('%.3f \n' % scene_context.render.fps_base)
           fscanf('\n')

           for frame in range(range_frame+1):
               if frame == 0:
                   if scene_context.frame_start == 0:
                       fscanf('frameid %d\n' % frame)
                       scene_context.frame_set(frame)

                       for pose_bone in arm.pose.bones:
                           pose_bone_rotation = get_pose_bone_matrix(pose_bone).to_euler()

                           id = root.find(pose_bone.name)
                           fscanf('boneid %d\n' % id)
                           local_euler = pose_bone.matrix_channel.to_euler()
                           fscanf('rotation ')
                           if pose_bone.parent is None:
                               fscanf('%.3f %.3f %.3f \n' % ( -pose_bone_rotation[0], -pose_bone_rotation[2], -pose_bone_rotation[1]))
                           else:
                               fscanf('%.3f %.3f %.3f \n' % ( -pose_bone_rotation[0], -pose_bone_rotation[2], -pose_bone_rotation[1]))

                       fscanf('\n')
               else:
                   fscanf('frameid %d\n' % frame)
                   scene_context.frame_set(frame)

                   for pose_bone in arm.pose.bones:
                       pose_bone_rotation = get_pose_bone_matrix(pose_bone).to_euler()

                       id = root.find(pose_bone.name)
                       fscanf('boneid %d\n' % id)
                       local_euler = pose_bone.matrix_channel.to_euler()
                       fscanf('rotation ')
                       if pose_bone.parent is None:
                           fscanf('%.3f %.3f %.3f \n' % ( -pose_bone_rotation[0], -pose_bone_rotation[2], -pose_bone_rotation[1]))
                       else:
                           fscanf('%.3f %.3f %.3f \n' % ( -pose_bone_rotation[0], -pose_bone_rotation[2], -pose_bone_rotation[1]))

                   fscanf('\n')

    file.close()

    return {'FINISHED'}


import math

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable
# from model.CNN import CNN_only

import numpy as np

class PositionEncoder(nn.Module):
    def __init__(self, f_dim, max_seq_len, dropout_rate=0.5):
        super(PositionEncoder, self).__init__()

        self.max_seq_len = max_seq_len
        self.f_dim = f_dim
        self.dropout = nn.Dropout(dropout_rate)
        # self.LayerNorm = nn.LayerNorm([max_seq_len, f_dim])

        self.position_embeddings = nn.Embedding(max_seq_len, f_dim)
        # initialize_weight(self.position_embeddings)

    def forward(self, x):
        position_ids = torch.arange(self.max_seq_len, dtype=torch.long, device=x.device)

        position_ids = position_ids.unsqueeze(0).expand(x.shape[0], self.max_seq_len)

        position_embeddings = self.position_embeddings(position_ids)

        x = x + position_embeddings
        return self.dropout(x)

def initialize_weight(x):
    nn.init.xavier_uniform_(x.weight)
    if x.bias is not None:
        nn.init.constant_(x.bias, 0)

class GEGLU(nn.Module):
    # https://arxiv.org/pdf/2002.05202.pdf
    # 有关于GEGLU函数的定义：GEGLU(x, W, V, b, c) = GELU(xW + b) ⊗ (xV + c)
    # GLU = gated linear units

    def forward(self, x):
        # print('in geglu x={}'.format(x.shape)) # x=[1, 256, 4096]
        x, gates = x.chunk(2, dim = -1)
        # 按照最后一列切割成两个tensor
        # print('in middle of geglu x={}, gates={}'.format(x.shape, gates.shape))
        # x=[1, 256, 2048], gates=[1, 256, 2048]

        out = x * F.gelu(gates)
        # print('out geglu out={}'.format(out.shape))
        # out=[1, 256, 2048]
        return out

def fourier_encode(x, max_freq, num_bands = 4, base = 2):
    x = x.unsqueeze(-1)
    device, dtype, orig_x = x.device, x.dtype, x

    scales = torch.logspace(1., np.log(max_freq / 2) / np.log(base), num_bands,
                            base = base, device = device, dtype = dtype)
    scales = scales[(*((None,) * (len(x.shape) - 1)), Ellipsis)]

    x = x * scales * np.pi
    x = torch.cat([x.sin(), x.cos()], dim=-1)
    x = torch.cat((x, orig_x), dim = -1)
    return x

class MultiHeadAtten(nn.Module):
    """
    The multi-head attention module in transformer.

    f_dim: the dimension of input data;
    atten_layer_type: the type of the layers to generate Q, K, V. (1D-Conv, Linear);
    n_heads: the number of heads in the multi-head attention module;
    mask: the mask added to the attentional score;
    """
    def __init__(self, f_dim, atten_layer_type, dim_per_head, n_heads=8, need_mask=False, dropout_rate=0.5):
        super(MultiHeadAtten, self).__init__()
        self.f_dim = f_dim
        self.n_heads = n_heads
        self.dim_per_head = dim_per_head

        self.atten_layer_type = atten_layer_type
        self.need_mask = need_mask
        self.dropout = nn.Dropout(dropout_rate)

        self.K_layer = self.kqv_generate_layer(atten_layer_type, f_dim, dim_per_head*n_heads)
        # initialize_weight(self.K_layer)
        self.Q_layer = self.kqv_generate_layer(atten_layer_type, f_dim, dim_per_head*n_heads)
        # initialize_weight(self.Q_layer)
        self.V_layer = self.kqv_generate_layer(atten_layer_type, f_dim, dim_per_head*n_heads)
        # initialize_weight(self.V_layer)
        self.combine_heads = nn.Linear(in_features=self.n_heads*self.dim_per_head, out_features=f_dim)
        # initialize_weight(self.combine_heads)

    def forward(self, x):
        batch_size = x.size(0)
        # the shape of x: [batch_size, num_segments, f_dim]
        # separated shape: [batch_size, n_heads, number_segments, f_dim/n_heads]
        K = self.K_layer(x)
        K = self.seperate_heads(K, self.n_heads, self.dim_per_head)
        Q = self.Q_layer(x)
        Q = self.seperate_heads(Q, self.n_heads, self.dim_per_head)
        V = self.V_layer(x)
        V = self.seperate_heads(V, self.n_heads, self.dim_per_head)

        attn_x = self.attention(K, Q, V, self.need_mask)
        attn_x = attn_x.transpose(1,2).contiguous().view(batch_size, -1, self.n_heads*self.dim_per_head)

        attn_x = self.combine_heads(attn_x)

        return attn_x

    def kqv_generate_layer(self, atten_layer_type, f_dim,  out_dim):
        if atten_layer_type == "Linear":
            return nn.Linear(in_features=f_dim, out_features=out_dim)
        elif atten_layer_type == '1D-Conv':
            return None
        else:
            print("The 'atten_layer_type' must be the one of {'Linear', '1D-Conv'}!")
            return None

    def seperate_heads(self, x, num_heads, dim_per_head):
        batch_size = x.size(0)
        x = x.view(batch_size, -1, num_heads, dim_per_head)
        return x.permute(0, 2, 1, 3)

    def generate_mask(self, mask):
        pass

    def attention(self, K, Q, V, need_mask):
        if need_mask:
            pass
        else:
            weight = F.softmax(torch.matmul(Q, K.permute(0, 1, 3, 2))/np.power(K.shape[-1], 0.5), dim=-1)
            output = torch.matmul(weight, V)

            return output

class FeedForwardLayer(nn.Module):
    def __init__(self, f_dim, ffn_dim, dropout_rate=0.5):
        super(FeedForwardLayer, self).__init__()
        self.f_dim = f_dim
        self.ffn1 = nn.Linear(f_dim, ffn_dim)
        # initialize_weight(self.ffn1)
        self.dropout = nn.Dropout(dropout_rate)
        # self.ffn2 = nn.Linear(ffn_dim, ffn_dim)
        # # initialize_weight(self.ffn2)
        # self.ffn3 = nn.Linear(ffn_dim, ffn_dim)
        # initialize_weight(self.ffn3)

        self.ffn6 = nn.Linear(ffn_dim, f_dim)
        # initialize_weight(self.ffn6)

        self.geglu = GEGLU()

    def forward(self, x):
        batch_size = x.shape[0]
        seq_len = x.shape[1]
        x = x.view(batch_size*seq_len, self.f_dim)

        x = F.relu(self.dropout(self.ffn1(x)))
        # x = F.relu(self.dropout(self.ffn2(x)))
        # x = F.relu(self.dropout(self.ffn3(x)))

        output = F.relu(self.dropout(self.ffn6(x)))
        output = output.view(batch_size, seq_len, self.f_dim)
        return output

class EncoderLayer(nn.Module):
    def __init__(self, max_seq_len, f_dim, dim_per_head, num_heads, ffn_dim, dropout_rate):
        super(EncoderLayer, self).__init__()

        self.attention = MultiHeadAtten(f_dim=f_dim, atten_layer_type='Linear',
                                        dim_per_head=dim_per_head, n_heads=num_heads)
        self.LayerNorm = nn.LayerNorm([max_seq_len, f_dim])
        self.FeedForwardLayer = FeedForwardLayer(f_dim, ffn_dim=ffn_dim, dropout_rate=dropout_rate)
        self.dropout = nn.Dropout(dropout_rate)

    def forward(self, x):
        atten_x = self.attention(x)
        resnorm_x = self.dropout(self.LayerNorm(atten_x))
        ffn_x = self.dropout(self.FeedForwardLayer(resnorm_x)) + x

        return ffn_x

class Encoder(nn.Module):
    """
    add the encoder linear to control the hidden dimension in transformer
    remove the LayerNorm operation before the classifier
    investigate: using the combine_head layer / remove the combine_layer
    """
    def __init__(self, max_seq_len=251, f_dim=60, dim_per_head=64, num_heads=8, ffn_dim=256, dropout_rate=0.1, num_layers=6):
        super(Encoder, self).__init__()

        # self.PositionEcoder = PositionEncoder(f_dim=f_dim, max_seq_len=max_seq_len, dropout_rate=dropout_rate)

        self.EncodingLayer = EncoderLayer(max_seq_len=max_seq_len,
                                          f_dim=f_dim, dim_per_head=dim_per_head, num_heads=num_heads,
                                          ffn_dim=ffn_dim, dropout_rate=dropout_rate)
        self.LayerNorm = nn.LayerNorm([max_seq_len, f_dim])
        self.Encoders = nn.ModuleList([self.EncodingLayer for _ in range(num_layers)])

        # ffn for classification of emotion and gender

        self.emotion_ffn = nn.Linear(in_features=max_seq_len*f_dim, out_features=4)
        self.emotion_ffn_center = nn.Linear(in_features=max_seq_len*f_dim, out_features=4)
        self.gender_ffn = nn.Linear(in_features=max_seq_len*f_dim, out_features=2)
        self.gender_ffn_center = nn.Linear(in_features=max_seq_len*f_dim, out_features=2)

    def forward(self, x):
        # x_local = self.CNN(x)

        x = x.transpose(2,1)

        # weights = []
        # x = self.encoder_linear(x)
        # pos_x = self.PositionEcoder(x)
        # x = pos_x
        for encoder in self.Encoders:
            x = encoder(x)
            # weights.append(weight.cpu().detach().numpy())

        x = self.LayerNorm(x).view(x.shape[0], -1)

        # x = torch.cat((x_local, x), dim=-1)
        # classifier
        emotion = self.emotion_ffn(x)
        emotion_center = self.emotion_ffn_center(x)
        gender = self.gender_ffn(x)
        gender_center = self.gender_ffn_center(x)

        #

        return emotion, gender, emotion_center, gender_center

class cleanEncoder(nn.Module):
    def __init__(self, max_seq_len, f_dim, dim_per_head, num_heads, ffn_dim, dropout_rate, num_layers):
        super(cleanEncoder, self).__init__()

        # self.PositionEcoder = PositionEncoder(f_dim=f_dim, max_seq_len=max_seq_len, dropout_rate=dropout_rate)
        self.EncodingLayer = EncoderLayer(max_seq_len=max_seq_len,
                                          f_dim=f_dim, dim_per_head=dim_per_head, num_heads=num_heads,
                                          ffn_dim=ffn_dim, dropout_rate=dropout_rate)

        self.Encoders = nn.ModuleList([self.EncodingLayer for _ in range(num_layers)])

    def forward(self, x):
        x = x.transpose(2,1)
        # pos_x = self.PositionEcoder(x)
        # x = pos_x
        # weights = []

        for encoder in self.Encoders:
            x = encoder(x)

            # weights.append(weight.cpu().detach().numpy())

        return x

if __name__ == "__main__":
    x = torch.randn(32, 60, 260)
    # model = Encoder(max_seq_len=260, f_dim=60, dim_per_head=60, num_heads=8, ffn_dim=2048, dropout_rate=0.1, num_layers=6)
    # emotion,  emotion_center, gender, gender_center = model(x)
    x = fourier_encode(x, 15)
    print(x.shape)
    b, *axis, _, device = x.shape

    axis_pos = list(map(lambda size: torch.linspace(-1., 1.,
                                                    steps=size), (60)))
    print(len(axis_pos))
    pos = torch.stack(torch.meshgrid(*axis_pos), dim=-1)
    print('pos={}'.format(pos.shape))  # pos=torch.size([224, 224, 2])


#!/usr/bin/python3

import rospy
import rospkg
import os
import sys
import yaml
import random
from gazebo_msgs.srv import SpawnModel
from gazebo_msgs.srv import DeleteModel
from geometry_msgs.msg import Pose
from geometry_msgs.msg import Point
from geometry_msgs.msg import Quaternion

if __name__ == "__main__":

    # Initialize rospack
    rospack = rospkg.RosPack()
    # Get path to yaml
    # Initialize ROS node
    rospy.init_node("ur3_gazebo_spawner", anonymous=True)
    # Initialize ROS pack
    rospack = rospkg.RosPack()
    # Get path to block
    jenga_bob_path = rospack.get_path("jenga_bob")
    block1_path = os.path.join(jenga_bob_path, "description", "block_red.urdf")
    block2_path = os.path.join(jenga_bob_path, "description", "block_yellow.urdf")
    block3_path = os.path.join(jenga_bob_path, "description", "block_green.urdf")
    block_paths = [block3_path, block3_path, block3_path]
    # Wait for service to start
    rospy.wait_for_service("gazebo/spawn_urdf_model")
    spawn = rospy.ServiceProxy("gazebo/spawn_urdf_model", SpawnModel)
    delete = rospy.ServiceProxy("gazebo/delete_model", DeleteModel)

    # Delete previous blocks
    for stack in range(10):
        for block in range(3):
            block_name = "block" + str(block + 1) + str(stack + 1)
            delete(block_name)

    tower_center = (0.2, 0.25)
    stack_height = 0.03

    # Spawn blocks
    for stack in range(1, 9):
        for block in range(3):
            block_name = "block" + str(block + 1) + str(stack + 1)

            if stack % 2 == 0:
                pose = Pose(
                    Point(
                        tower_center[0],
                        tower_center[1] - 0.033 * (block - 1),
                        stack_height * stack + 0.005,
                    ),
                    Quaternion(0, 0, -(2 ** (0.5)) / 2, 2 ** (0.5) / 2),
                )
            else:
                pose = Pose(
                    Point(
                        tower_center[0] - 0.033 * (block - 1),
                        tower_center[1],
                        stack_height * stack + 0.005,
                    ),
                    Quaternion(0, 0, 0, 0),
                )
            spawn(
                block_name,
                open(block_paths[2 - block], "r").read(),
                "block",
                pose,
                "world",
            )
            print(block_name)


from fastapi import Depends, Security, APIRouter, Query, Response, Body, HTTPException
from sqlmodel import select
from app.db import get_session, AsyncSession
from app.auth import get_api_key
from app.services.runresults.models import (
    RunResult,
    RunResultCreate,
    RunResultRead,
    RunResultUpdate,
)
from sqlalchemy import func
import json

router = APIRouter()

@router.get("/{run_result_id}", response_model=RunResultRead)
async def get_run_result(
    session: AsyncSession = Depends(get_session),
    *,
    run_result_id: int,
) -> RunResultRead:
    """Get a run result by id"""
    res = await session.exec(
        select(RunResult).where(RunResult.id == run_result_id)
    )
    run_result = res.one_or_none()

    return run_result

@router.get("", response_model=list[RunResultRead])
async def get_run_results(
    response: Response,
    filter: str = Query(None),
    sort: str = Query(None),
    range: str = Query(None),
    session: AsyncSession = Depends(get_session),
):
    """Get all run results"""

    sort = json.loads(sort) if sort else []
    range = json.loads(range) if range else []
    filter = json.loads(filter) if filter else {}

    query = select(RunResult)

    # Do a query to satisfy total count for "Content-Range" header
    count_query = select(func.count(RunResult.id))
    if len(filter):  # Have to filter twice for some reason? SQLModel state?
        for field, value in filter.items():
            for qry in [query, count_query]:  # Apply filter to both queries
                if isinstance(value, list):
                    qry = qry.where(getattr(RunResult, field).in_(value))
                elif field == "id" or field == "experiment_id":
                    qry = qry.where(getattr(RunResult, field) == value)
                else:
                    qry = qry.where(
                        getattr(RunResult, field).like(f"%{value}%")
                    )

    # Execute total count query (including filter)
    total_count_query = await session.exec(count_query)
    total_count = total_count_query.one()

    # Order by sort field params ie. ["name","ASC"]
    if len(sort) == 2:
        sort_field, sort_order = sort
        if sort_order == "ASC":
            query = query.order_by(getattr(RunResult, sort_field))
        else:
            query = query.order_by(getattr(RunResult, sort_field), getattr(RunResult, sort_field).desc())

    # Filter by filter field params ie. {"name":"bar"}
    if len(filter):
        for field, value in filter.items():
            if isinstance(value, list):
                query = query.where(getattr(RunResult, field).in_(value))
            elif field == "id" or field == "experiment_id":
                query = query.where(getattr(RunResult, field) == value)
            else:
                query = query.where(
                    getattr(RunResult, field).like(f"%{value}%")
                )

    if len(range) == 2:
        start, end = range
        query = query.offset(start).limit(end - start + 1)
    else:
        start, end = [0, total_count]  # For content-range header

    # Execute query
    results = await session.exec(query)
    run_results = results.all()

    response.headers[
        "Content-Range"
    ] = f"run_results {start}-{end}/{total_count}"
    return run_results

@router.post("", response_model=RunResultRead)
async def create_run_result(
    run_result: RunResultCreate = Body(...),
    session: AsyncSession = Depends(get_session),
    api_key: str = Security(get_api_key),
) -> RunResultRead:
    """Creates a run result"""
    print(run_result)
    run_result = RunResult.from_orm(run_result)
    session.add(run_result)
    await session.commit()
    await session.refresh(run_result)

    return run_result

@router.put("/{run_result_id}", response_model=RunResultRead)
async def update_run_result(
    run_result_id: int,
    run_result_update: RunResultUpdate,
    session: AsyncSession = Depends(get_session),
    api_key: str = Security(get_api_key)
) -> RunResultRead:
    res = await session.exec(
        select(RunResult).where(RunResult.id == run_result_id)
    )
    run_result_db = res.one()
    run_result_data = run_result_update.dict(exclude_unset=True)

    if not run_result_db:
        raise HTTPException(status_code=404, detail="RunResult not found")

    # Update the fields from the request
    for field, value in run_result_data.items():
        print(f"Updating: {field}, {value}")
        setattr(run_result_db, field, value)

    session.add(run_result_db)
    await session.commit()
    await session.refresh(run_result_db)

    return run_result_db

@router.delete("/{run_result_id}")
async def delete_run_result(
    run_result_id: int,
    session: AsyncSession = Depends(get_session),
    filter: dict[str, str] | None = None,
    api_key: str = Security(get_api_key),
) -> None:
    """Delete a run result by id"""
    res = await session.exec(
        select(RunResult).where(RunResult.id == run_result_id)
    )
    run_result = res.one_or_none()

    if run_result:
        await session.delete(run_result)
        await session.commit()


import os
import re
import json
import requests

from slackbot.bot import respond_to

from hiarcbot import sched, bot
import slack_config

headers = {
    "Accept-Language": "ko_KR",
    "Accept": "application/json"
}

data = {
    "user_key": "hi-arc slackbot",
    "type": "text",
    "content": "오늘의 식단"
}

def get_schoolcafe_menu():
    r = requests.post(url=slack_config.SCHOOL_CAFE_API,
                      headers=headers, data=data)
    if r.status_code != 200:
        print("error")

    return json.loads(r.text)['message']['text']

@respond_to('^학식$', re.IGNORECASE)
def menu_reply(message):
    menu_summary = get_schoolcafe_menu()
    message.send(menu_summary)

@sched.scheduled_job('cron', hour=8, minute=0)
def notify_schoolcafe_menu():
    menu_summary = get_schoolcafe_menu()
    slack_client = getattr(bot, "_client", None)
    channel_id = slack_client.find_channel_by_name(u'gourmat')
    slack_client.send_message(channel_id, menu_summary)


"""Estrtutura inicial

Revision ID: 9cc0564d755d
Revises:
Create Date: 2023-04-02 14:19:33.777120

"""
import sqlalchemy as sa
import sqlmodel

from alembic import op

# revision identifiers, used by Alembic.
revision = "9cc0564d755d"
down_revision = None
branch_labels = None
depends_on = None

def upgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table(
        "empresa",
        sa.Column("id", sqlmodel.sql.sqltypes.GUID(), nullable=False),
        sa.Column("nome", sqlmodel.sql.sqltypes.AutoString(length=250), nullable=False),
        sa.Column(
            "logradouro", sqlmodel.sql.sqltypes.AutoString(length=250), nullable=True
        ),
        sa.Column(
            "cidade", sqlmodel.sql.sqltypes.AutoString(length=150), nullable=True
        ),
        sa.Column("estado", sqlmodel.sql.sqltypes.AutoString(length=50), nullable=True),
        sa.Column("matriz", sa.Boolean(), nullable=False),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(op.f("ix_empresa_id"), "empresa", ["id"], unique=False)
    op.create_table(
        "pessoa",
        sa.Column("id", sqlmodel.sql.sqltypes.GUID(), nullable=False),
        sa.Column("nome", sqlmodel.sql.sqltypes.AutoString(length=200), nullable=False),
        sa.Column("email", sqlmodel.sql.sqltypes.AutoString(length=250), nullable=True),
        sa.Column(
            "telefone", sqlmodel.sql.sqltypes.AutoString(length=20), nullable=True
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(op.f("ix_pessoa_id"), "pessoa", ["id"], unique=False)
    op.create_table(
        "departamento",
        sa.Column("id", sqlmodel.sql.sqltypes.GUID(), nullable=False),
        sa.Column("nome", sqlmodel.sql.sqltypes.AutoString(length=200), nullable=False),
        sa.Column(
            "local", sqlmodel.sql.sqltypes.AutoString(length=200), nullable=False
        ),
        sa.Column("id_empresa", sqlmodel.sql.sqltypes.GUID(), nullable=False),
        sa.ForeignKeyConstraint(
            ["id_empresa"],
            ["empresa.id"],
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(op.f("ix_departamento_id"), "departamento", ["id"], unique=False)
    # ### end Alembic commands ###

def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index(op.f("ix_departamento_id"), table_name="departamento")
    op.drop_table("departamento")
    op.drop_index(op.f("ix_pessoa_id"), table_name="pessoa")
    op.drop_table("pessoa")
    op.drop_index(op.f("ix_empresa_id"), table_name="empresa")
    op.drop_table("empresa")
    # ### end Alembic commands ###


import torch
import torch.nn as nn
from einops import rearrange
import numpy as np
from models.op.common import *
import xformers.ops as xops
class Upsample(nn.Module):
    def __init__(self, in_channels, with_conv):
        super().__init__()
        self.with_conv = with_conv
        if self.with_conv:
            self.conv = torch.nn.Conv2d(in_channels,
                                        in_channels,
                                        kernel_size=3,
                                        stride=1,
                                        padding=1)

    def forward(self, x):
        x = torch.nn.functional.interpolate(x, scale_factor=2.0, mode="nearest")
        if self.with_conv:
            x = self.conv(x)
        return x

class ResnetBlock(nn.Module):
    def __init__(self, *, in_channels, out_channels=None, conv_shortcut=False,
                 dropout, temb_channels=512):
        super().__init__()
        self.in_channels = in_channels
        out_channels = in_channels if out_channels is None else out_channels
        self.out_channels = out_channels
        self.use_conv_shortcut = conv_shortcut

        self.norm1 = Normalize(in_channels)
        self.conv1 = torch.nn.Conv2d(in_channels,
                                     out_channels,
                                     kernel_size=3,
                                     stride=1,
                                     padding=1)
        if temb_channels > 0:
            self.temb_proj = torch.nn.Linear(temb_channels,
                                             out_channels)
        self.norm2 = Normalize(out_channels)
        self.dropout = torch.nn.Dropout(dropout)
        self.conv2 = torch.nn.Conv2d(out_channels,
                                     out_channels,
                                     kernel_size=3,
                                     stride=1,
                                     padding=1)
        if self.in_channels != self.out_channels:
            if self.use_conv_shortcut:
                self.conv_shortcut = torch.nn.Conv2d(in_channels,
                                                     out_channels,
                                                     kernel_size=3,
                                                     stride=1,
                                                     padding=1)
            else:
                self.nin_shortcut = torch.nn.Conv2d(in_channels,
                                                    out_channels,
                                                    kernel_size=1,
                                                    stride=1,
                                                    padding=0)

    def forward(self, x, temb):
        h = x
        h = self.norm1(h)
        h = nonlinearity(h)
        h = self.conv1(h)
        if temb is not None:
            h = h + self.temb_proj(nonlinearity(temb))[:,:,None,None]

        h = self.norm2(h)
        h = nonlinearity(h)
        h = self.dropout(h)
        h = self.conv2(h)

        if self.in_channels != self.out_channels:
            if self.use_conv_shortcut:
                x = self.conv_shortcut(x)
            else:
                x = self.nin_shortcut(x)

        return x+h

class Downsample(nn.Module):
    def __init__(self, in_channels, with_conv):
        super().__init__()
        self.with_conv = with_conv
        if self.with_conv:
            # no asymmetric padding in torch conv, must do it ourselves
            self.conv = torch.nn.Conv2d(in_channels,
                                        in_channels,
                                        kernel_size=3,
                                        stride=2,
                                        padding=0)

    def forward(self, x):
        if self.with_conv:
            pad = (0,1,0,1)
            x = torch.nn.functional.pad(x, pad, mode="constant", value=0)
            x = self.conv(x)
        else:
            x = torch.nn.functional.avg_pool2d(x, kernel_size=2, stride=2)
        return x

class AttnBlock(nn.Module):
    def __init__(self, in_channels):
        super().__init__()
        self.in_channels = in_channels

        self.norm = Normalize(in_channels)
        self.q = torch.nn.Conv2d(in_channels,
                                 in_channels,
                                 kernel_size=1,
                                 stride=1,
                                 padding=0)
        self.k = torch.nn.Conv2d(in_channels,
                                 in_channels,
                                 kernel_size=1,
                                 stride=1,
                                 padding=0)
        self.v = torch.nn.Conv2d(in_channels,
                                 in_channels,
                                 kernel_size=1,
                                 stride=1,
                                 padding=0)
        self.proj_out = torch.nn.Conv2d(in_channels,
                                        in_channels,
                                        kernel_size=1,
                                        stride=1,
                                        padding=0)

    def forward(self, x):
        b, c, h, w = x.shape
        h_ = x
        h_ = self.norm(h_)
        q = self.q(h_)
        k = self.k(h_)
        v = self.v(h_)
        q, k, v = map(lambda t: rearrange(t, 'b c h w -> b (h w) c').contiguous(), (q, k, v))
        h_ = xops.memory_efficient_attention(q, k, v)
        h_ = rearrange(h_, 'b (h w) d -> b d h w', h=h, w=w)
        h_ = self.proj_out(h_)
        return x+h_

class LinearAttention(nn.Module):
    def __init__(self, dim, heads=4, dim_head=32):
        super().__init__()
        self.heads = heads
        hidden_dim = dim_head * heads
        self.to_qkv = nn.Conv2d(dim, hidden_dim * 3, 1, bias = False)
        self.to_out = nn.Conv2d(hidden_dim, dim, 1)

    def forward(self, x):
        b, c, h, w = x.shape
        qkv = self.to_qkv(x)
        q, k, v = rearrange(qkv, 'b (qkv heads c) h w -> qkv b heads c (h w)', heads = self.heads, qkv=3)
        k = k.softmax(dim=-1)
        context = torch.einsum('bhdn,bhen->bhde', k, v)
        out = torch.einsum('bhde,bhdn->bhen', context, q)
        out = rearrange(out, 'b heads c (h w) -> b (heads c) h w', heads=self.heads, h=h, w=w)
        return self.to_out(out)
class LinAttnBlock(LinearAttention):
    """to match AttnBlock usage"""
    def __init__(self, in_channels):
        super().__init__(dim=in_channels, heads=1, dim_head=in_channels)

def make_attn(in_channels, attn_type="vanilla"):
    assert attn_type in ["vanilla", "linear", "none"], f'attn_type {attn_type} unknown'
    print(f"making attention of type '{attn_type}' with {in_channels} in_channels")
    if attn_type == "vanilla":
        return AttnBlock(in_channels)
    elif attn_type == "none":
        return nn.Identity(in_channels)
    else:
        return LinAttnBlock(in_channels)

class Encoder(nn.Module):
    def __init__(self, *, ch, out_ch, ch_mult=(1,2,4,8), num_res_blocks,
                 attn_resolutions, dropout=0.0, resamp_with_conv=True, in_channels,
                 resolution, z_channels, double_z=True, use_linear_attn=False, attn_type="vanilla",
                 **ignore_kwargs):
        super().__init__()
        if use_linear_attn: attn_type = "linear"
        self.ch = ch
        self.temb_ch = 0
        self.num_resolutions = len(ch_mult)
        self.num_res_blocks = num_res_blocks
        self.resolution = resolution
        self.in_channels = in_channels
        # downsampling
        self.conv_in = torch.nn.Conv2d(in_channels,
                                       self.ch,
                                       kernel_size=3,
                                       stride=1,
                                       padding=1)
        curr_res = resolution
        in_ch_mult = (1,)+tuple(ch_mult)
        self.in_ch_mult = in_ch_mult
        self.down = nn.ModuleList()
        for i_level in range(self.num_resolutions):
            block = nn.ModuleList()
            attn = nn.ModuleList()
            block_in = ch*in_ch_mult[i_level]
            block_out = ch*ch_mult[i_level]
            for i_block in range(self.num_res_blocks):
                block.append(ResnetBlock(in_channels=block_in,
                                         out_channels=block_out,
                                         temb_channels=self.temb_ch,
                                         dropout=dropout))
                block_in = block_out
                if curr_res in attn_resolutions:
                    attn.append(make_attn(block_in, attn_type=attn_type))
            down = nn.Module()
            down.block = block
            down.attn = attn
            if i_level != self.num_resolutions-1:
                down.downsample = Downsample(block_in, resamp_with_conv)
                curr_res = curr_res // 2
            self.down.append(down)
        # middle
        self.mid = nn.Module()
        self.mid.block_1 = ResnetBlock(in_channels=block_in,
                                       out_channels=block_in,
                                       temb_channels=self.temb_ch,
                                       dropout=dropout)
        self.mid.attn_1 = make_attn(block_in, attn_type=attn_type)
        self.mid.block_2 = ResnetBlock(in_channels=block_in,
                                       out_channels=block_in,
                                       temb_channels=self.temb_ch,
                                       dropout=dropout)
        # end
        self.norm_out = Normalize(block_in)
        self.conv_out = torch.nn.Conv2d(block_in,
                                        2*z_channels if double_z else z_channels,
                                        kernel_size=3,
                                        stride=1,
                                        padding=1)

    def forward(self, x):
        # timestep embedding
        temb = None
        # downsampling
        hs = [self.conv_in(x)]

        for i_level in range(self.num_resolutions):
            for i_block in range(self.num_res_blocks):
                h = self.down[i_level].block[i_block](hs[-1], temb)
                if len(self.down[i_level].attn) > 0:
                    h = self.down[i_level].attn[i_block](h)
                hs.append(h)
            if i_level != self.num_resolutions-1:
                hs.append(self.down[i_level].downsample(hs[-1]))
        # middle
        h = hs[-1]
        h = self.mid.block_1(h, temb)
        h = self.mid.attn_1(h)
        h = self.mid.block_2(h, temb)

        # end
        h = self.norm_out(h)
        h = nonlinearity(h)
        h = self.conv_out(h)
        return h

class Decoder(nn.Module):
    def __init__(self, *, ch, out_ch, ch_mult=(1,2,4,8), num_res_blocks,
                 attn_resolutions, dropout=0.0, resamp_with_conv=True, in_channels,
                 resolution, z_channels, give_pre_end=False, tanh_out=False, use_linear_attn=False,
                 attn_type="vanilla", **ignorekwargs):
        super().__init__()
        if use_linear_attn: attn_type = "linear"
        self.ch = ch
        self.temb_ch = 0
        self.num_resolutions = len(ch_mult)
        self.num_res_blocks = num_res_blocks
        self.resolution = resolution
        self.in_channels = in_channels
        self.give_pre_end = give_pre_end
        self.tanh_out = tanh_out

        # compute in_ch_mult, block_in and curr_res at lowest res
        in_ch_mult = (1,)+tuple(ch_mult)
        block_in = ch*ch_mult[self.num_resolutions-1]
        curr_res = resolution // 2**(self.num_resolutions-1)
        self.z_shape = (1,z_channels,curr_res,curr_res)
        print("Working with z of shape {} = {} dimensions.".format(
            self.z_shape, np.prod(self.z_shape)))

        # z to block_in
        self.conv_in = torch.nn.Conv2d(z_channels,
                                       block_in,
                                       kernel_size=3,
                                       stride=1,
                                       padding=1)

        # middle
        self.mid = nn.Module()
        self.mid.block_1 = ResnetBlock(in_channels=block_in,
                                       out_channels=block_in,
                                       temb_channels=self.temb_ch,
                                       dropout=dropout)
        self.mid.attn_1 = make_attn(block_in, attn_type=attn_type)
        self.mid.block_2 = ResnetBlock(in_channels=block_in,
                                       out_channels=block_in,
                                       temb_channels=self.temb_ch,
                                       dropout=dropout)

        # upsampling
        self.up = nn.ModuleList()
        for i_level in reversed(range(self.num_resolutions)):
            block = nn.ModuleList()
            attn = nn.ModuleList()
            block_out = ch*ch_mult[i_level]
            for i_block in range(self.num_res_blocks+1):
                block.append(ResnetBlock(in_channels=block_in,
                                         out_channels=block_out,
                                         temb_channels=self.temb_ch,
                                         dropout=dropout))
                block_in = block_out
                if curr_res in attn_resolutions:
                    attn.append(make_attn(block_in, attn_type=attn_type))
            up = nn.Module()
            up.block = block
            up.attn = attn
            if i_level != 0:
                up.upsample = Upsample(block_in, resamp_with_conv)
                curr_res = curr_res * 2
            self.up.insert(0, up) # prepend to get consistent order

        # end
        self.norm_out = Normalize(block_in)
        self.conv_out = torch.nn.Conv2d(block_in,
                                        out_ch,
                                        kernel_size=3,
                                        stride=1,
                                        padding=1)

    def forward(self, z):
        #assert z.shape[1:] == self.z_shape[1:]
        self.last_z_shape = z.shape

        # timestep embedding
        temb = None

        # z to block_in
        h = self.conv_in(z)

        # middle
        h = self.mid.block_1(h, temb)
        h = self.mid.attn_1(h)
        h = self.mid.block_2(h, temb)

        # upsampling
        for i_level in reversed(range(self.num_resolutions)):
            for i_block in range(self.num_res_blocks+1):
                h = self.up[i_level].block[i_block](h, temb)
                if len(self.up[i_level].attn) > 0:
                    h = self.up[i_level].attn[i_block](h)
            if i_level != 0:
                h = self.up[i_level].upsample(h)

        # end
        if self.give_pre_end:
            return h

        h = self.norm_out(h)
        h = nonlinearity(h)
        h = self.conv_out(h)
        if self.tanh_out:
            h = torch.tanh(h)
        return h

class DiagonalGaussianDistribution(object):
    def __init__(self, parameters, deterministic=False):
        self.parameters = parameters
        self.mean, self.logvar = torch.chunk(parameters, 2, dim=1)
        self.logvar = torch.clamp(self.logvar, -30.0, 20.0)
        self.deterministic = deterministic
        self.std = torch.exp(0.5 * self.logvar)
        self.var = torch.exp(self.logvar)
        if self.deterministic:
            self.var = self.std = torch.zeros_like(self.mean).to(device=self.parameters.device)

    def sample(self):
        x = self.mean + self.std * torch.randn(self.mean.shape).to(device=self.parameters.device)
        return x

    def kl(self, other=None):
        if self.deterministic:
            return torch.Tensor([0.])
        else:
            if other is None:
                return 0.5 * torch.sum(torch.pow(self.mean, 2)
                                       + self.var - 1.0 - self.logvar,
                                       dim=[1, 2, 3])
            else:
                return 0.5 * torch.sum(
                    torch.pow(self.mean - other.mean, 2) / other.var
                    + self.var / other.var - 1.0 - self.logvar + other.logvar,
                    dim=[1, 2, 3])

    def nll(self, sample, dims=[1,2,3]):
        if self.deterministic:
            return torch.Tensor([0.])
        logtwopi = np.log(2.0 * np.pi)
        return 0.5 * torch.sum(
            logtwopi + self.logvar + torch.pow(sample - self.mean, 2) / self.var,
            dim=dims)

    def mode(self):
        return self.mean

class AutoencoderKLX(nn.Module):
    def __init__(self,
                 ddconfig,
                 embed_dim,
                 **kwargs
                 ):
        super().__init__()
        self.encoder = Encoder(**ddconfig)
        self.decoder = Decoder(**ddconfig)
        assert ddconfig["double_z"]
        self.quant_conv = torch.nn.Conv2d(2*ddconfig["z_channels"], 2*embed_dim, 1)
        self.post_quant_conv = torch.nn.Conv2d(embed_dim, ddconfig["z_channels"], 1)
        self.embed_dim = embed_dim
        if kwargs.get("pretrain", None):
            load_pretrained_model(self, kwargs["pretrain"])

    @torch.inference_mode()
    def encode(self, x):
        h = self.encoder(x)
        moments = self.quant_conv(h)
        posterior = DiagonalGaussianDistribution(moments)
        return posterior

    @torch.inference_mode()
    def decode(self, z):
        z = self.post_quant_conv(z)
        dec = self.decoder(z)
        return dec

    def map(self, x):
        h = self.encoder(x)
        moments = self.quant_conv(h)
        return moments

    def forward(self, input, sample_posterior=True):
        posterior = self.encode(input)
        if sample_posterior:
            z = posterior.sample()
        else:
            z = posterior.mode()
        dec = self.decode(z)
        return dec, posterior

    def del_decoder(self):
        del self.decoder
        del self.post_quant_conv

    @torch.inference_mode()
    def get_scale_encoding(self, x, scale_factor = 0.18215):
        z = self.encode(x)
        z = z.sample()
        return scale_factor * z

    @torch.inference_mode()
    def get_scale_decoding(self, z, scale_factor = 0.18215):
        z = z / scale_factor
        x = self.decode(z)
        return x

if __name__ == "__main__":
    # params:
    #     embed_dim: 4
    #     ddconfig:
    #         double_z: true
    #         z_channels: 4
    #         resolution: *image_size
    #         in_channels: 3
    #         out_ch: 3
    #         ch: 128
    #         num_res_blocks: 2
    #         attn_resolutions: []
    #         dropout: 0.0
    #         ch_mult: [1, 2, 4, 4]
    #     pretrain: "pretrain/autoencoder_kl_v2.ckpt"
    params = {
        "embed_dim": 4,
        "ddconfig": {
            "double_z": True,
            "z_channels": 4,
            "resolution": 256,
            "in_channels": 3,
            "out_ch": 3,
            "ch": 128,
            "num_res_blocks": 2,
            "attn_resolutions": [],
            "dropout": 0.0,
            "ch_mult": [1, 2, 4, 4]
        },
        "pretrain": "pretrain/autoencoder_kl_v2.ckpt"
    }
    model = AutoencoderKLX(**params)
    device = "cuda"
    model = model.to(device)
    def test_error(video_path, id, text):
        import torchvision as tv
        from einops import rearrange
        from dataset.common import read_video
        video = read_video(video_path, 16, 3)
        transform = tv.transforms.Compose([
            tv.transforms.Resize(256),
            tv.transforms.CenterCrop(256),
        ])
        video = video.to(device)
        video = transform(video)
        # normalize
        _video = video / 255
        _video = (_video - 0.5) / 0.5
        out, posterior = model(_video)
        out1 = ((out * 0.5 + 0.5) * 255).clamp(0, 255)
        out1 = rearrange(out1, "t c h w -> t h w c")
        out1 = out1.detach().cpu()

        _video = video / 127.5 - 1
        out, posterior = model(_video)
        out2 = ((out + 1) * 127.5).clamp(0, 255)
        out2 = rearrange(out2, "t c h w -> t h w c")
        out2 = out2.detach().cpu()

        out = torch.cat([out1, out2], dim=2)
        tv.io.write_video(os.path.join("tmp", f"'{text}'_{id}.mp4"), out, fps=16/2)
    import pandas as pd
    csv_path = "tmp.csv"
    df = pd.read_csv(csv_path)
    for i, row in df.iterrows():
        video_path = row["video_path"]
        video_path = os.path.join("data/webvid/data/videos/", video_path)
        text = row["text"]
        test_error(video_path, i, text)


import numpy as np
import argparse
import tensorflow as tf
import matplotlib.pyplot as plt
from sklearn.utils import shuffle
from sklearn.model_selection import StratifiedKFold
import math
from datetime import datetime

NUM_LABELS = 47
rnd = np.random.RandomState(123)
tf.set_random_seed(123)

#hyper parameters
learning_rate = 0.001
momentum = 0.9
BATCH_SIZE = 256

learning_rate_tune = [ 0.01, 0.001,0.0001]
batch_size_tune = [32, 256, 512]
momentum_factor_tune = [0.1, 0.5, 0.9]

#settings
NUM_ITERATIONS= 50
STEP_VALIDATE_EPOCH=1 # check performance on the validation set every EPOCH_VALIDATE_STEP epochs
NUM_FOLD = 5

#MODEL_NAME = ""
CNN_MODEL_PATH = "../checkpoints/cnn/cnn_model"

# Following functions are helper functions that you can feel free to change
def convert_image_data_to_float(image_raw):
    #[None, 28, 28] -> [None, 28, 28, 1] and normalize 255 to 1
    img_float = tf.expand_dims(tf.cast(image_raw, tf.float32) / 255, axis=-1)
    return img_float

def visualize_ae(i, x, features, reconstructed_image):
    '''
    This might be helpful for visualizing your autoencoder outputs
    :param i: index
    :param x: original data
    :param features: feature maps
    :param reconstructed_image: autoencoder output
    :return:
    '''
    plt.figure("input img " + str(i))
    plt.imshow(x[i, :, :], cmap="gray")
    plt.title("input image", fontsize=16)
    plt.figure("reconstructed image"+str(i))
    plt.imshow(reconstructed_image[i, :, :, 0], cmap="gray")
    plt.title("reconsturcted image", fontsize=16)
    plt.figure("encoded features "+str(i))
    plt.imshow(np.reshape(features[i, :, :, :], (7, -1), order="F"), cmap="gray",)
    plt.title("encoded features", fontsize=16)

def build_cae_model(placeholder_x):
    with tf.variable_scope("cae") as scope:
        shapes=[]
        #input layer
        img_float = convert_image_data_to_float(placeholder_x)

        shapes.append(img_float.get_shape().as_list()) #shape[0], input shape of conv1

        #conv1
        w_conv1 = tf.get_variable("conv1_weight", shape=(5, 5, 1, 32),
                                  initializer=tf.contrib.layers.xavier_initializer())
        b_conv1 = tf.get_variable("conv1_bias", shape=(32), initializer=tf.contrib.layers.xavier_initializer())
        y_conv1 = tf.nn.conv2d(img_float, w_conv1, strides=[1, 2, 2, 1], padding='SAME') + b_conv1
        conv1= tf.nn.relu(y_conv1)
        shapes.append(conv1.get_shape().as_list()) #shape[1]

        #conv2
        w_conv2 = tf.get_variable("conv2_weight", shape=(5,5,32,64), initializer=tf.contrib.layers.xavier_initializer())
        b_conv2 = tf.get_variable("conv2_bias", shape=(64), initializer=tf.contrib.layers.xavier_initializer())
        y_conv2 = tf.nn.conv2d(conv1, w_conv2, strides=[1,2,2,1], padding='SAME') + b_conv2
        conv2 = tf.nn.relu(y_conv2)
        shapes.append(conv2.get_shape().as_list())  #shape[2]

        #conv3
        w_conv3 = tf.get_variable("conv3_weight", shape=(3,3,64,2), initializer=tf.contrib.layers.xavier_initializer())
        b_conv3 = tf.get_variable("conv3_bias", shape=(2), initializer=tf.contrib.layers.xavier_initializer())
        y_conv3 = tf.nn.conv2d(conv2, w_conv3, strides=[1,1,1,1], padding='SAME') + b_conv3
        conv3 = tf.nn.relu(y_conv3)

        print("encoder layer shape : %s" % conv3.get_shape())
        encode_result = conv3
        #shapes.reverse()

        #deconv1
        w_deconv1 = tf.get_variable("deconv1_weight", shape=(3, 3, 64, 2), initializer=tf.contrib.layers.xavier_initializer())
        b_deconv1 = tf.get_variable("deconv1_bias", shape=(64), initializer=tf.contrib.layers.xavier_initializer())
        shape=shapes[2]
        output_shape = tf.stack([tf.shape(img_float)[0], shape[1], shape[2], shape[3]]) #[batch_size, size_of_output_feature_map_of_conv2 x y, conv2_chs]
        deconv1 = tf.nn.relu( tf.nn.conv2d_transpose(conv3, w_deconv1, output_shape, strides=[1,1,1,1], padding='SAME') + b_deconv1 ) #TODO: strides

        #deconv2
        w_deconv2 = tf.get_variable("deconv2_weight", shape=(5, 5, 32, 64), initializer=tf.contrib.layers.xavier_initializer())
        b_deconv2 = tf.get_variable("deconv2_bias", shape=(32), initializer=tf.contrib.layers.xavier_initializer())
        shape=shapes[1]
        output_shape = tf.stack([tf.shape(img_float)[0], shape[1], shape[2], shape[3]]) #[batch_size, size_of_output_feature_map1_conv1 x y, conv1_chs]
        deconv2 = tf.nn.relu( tf.nn.conv2d_transpose(deconv1, w_deconv2, output_shape, strides=[1,2,2,1], padding='SAME') + b_deconv2 )

        #deconv3
        w_deconv3 = tf.get_variable("deconv3_weight", shape=(5, 5, 1, 32), initializer=tf.contrib.layers.xavier_initializer())
        b_deconv3 = tf.get_variable("deconv3_bias", shape=(1), initializer=tf.contrib.layers.xavier_initializer())
        shape=shapes[0]
        output_shape = tf.stack([tf.shape(img_float)[0], shape[1], shape[2], shape[3]]) #[batch_size, 28, 28, 1]
        deconv3 = tf.nn.relu( tf.nn.conv2d_transpose(deconv2, w_deconv3, output_shape, strides=[1,2,2,1], padding='SAME') + b_deconv3 )

        img_reconstructed = deconv3

        print("reconstruct layer shape : %s" % img_reconstructed.get_shape())

        #loss
        loss = tf.reduce_mean(tf.square(img_reconstructed - img_float))
        optimizer = tf.train.AdamOptimizer(learning_rate)
        #optimizer = tf.train.MomentumOptimizer(learning_rate, momentum) # doesn't work for cae model
        train_op = optimizer.minimize(loss,global_step = tf.train.get_global_step())

        return train_op, loss, encode_result, img_reconstructed

def build_cnn_model(placeholder_x, placeholder_y):
    with tf.variable_scope("cnn") as scope:

        img_float = convert_image_data_to_float(placeholder_x)
        #input_layer = tf.reshape(img_float, [-1, 28, 28, 1])
        #conv1
        w_conv1 = tf.get_variable("conv1_weight", shape=(3, 3, 1, 32),
                                  initializer=tf.contrib.layers.xavier_initializer())
        b_conv1 = tf.get_variable("conv1_bias", shape=(32), initializer=tf.contrib.layers.xavier_initializer())
        y_conv1 = tf.nn.conv2d(img_float, w_conv1, strides=[1, 1, 1, 1], padding='SAME') + b_conv1
        conv1= tf.nn.relu(y_conv1)
        #conv2
        w_conv2 = tf.get_variable("conv2_weight", shape=(5,5,32,32), initializer=tf.contrib.layers.xavier_initializer())
        b_conv2 = tf.get_variable("conv2_bias", shape=(32), initializer=tf.contrib.layers.xavier_initializer())
        y_conv2 = tf.nn.conv2d(conv1, w_conv2, strides=[1,2,2,1], padding='SAME') + b_conv2
        conv2 = tf.nn.relu(y_conv2)
        #conv3
        w_conv3 = tf.get_variable("conv3_weight", shape=(3,3,32,64), initializer=tf.contrib.layers.xavier_initializer())
        b_conv3 = tf.get_variable("conv3_bias", shape=(64), initializer=tf.contrib.layers.xavier_initializer())
        y_conv3 = tf.nn.conv2d(conv2, w_conv3, strides=[1,1,1,1], padding='SAME') + b_conv3
        conv3 = tf.nn.relu(y_conv3)
        #conv 4
        w_conv4 = tf.get_variable("conv4_weight", shape=(5,5,64,64), initializer=tf.contrib.layers.xavier_initializer())
        b_conv4 = tf.get_variable("conv4_bias", shape=(64), initializer=tf.contrib.layers.xavier_initializer())
        y_conv4 = tf.nn.conv2d(conv3, w_conv4, strides=[1,2,2,1], padding='SAME') + b_conv4
        conv4 = tf.nn.relu(y_conv4)

        # Flatten
        features_flattened = tf.reshape(conv4, [-1, np.prod(conv4.shape[1:])])

        # FC Layer
        w_fc = tf.get_variable("fc_weight", shape=(features_flattened.shape[1], NUM_LABELS),
                                 initializer=tf.contrib.layers.xavier_initializer())
        logits = tf.matmul(features_flattened, w_fc)
        # loss
        loss = tf.losses.sparse_softmax_cross_entropy(labels=placeholder_y, logits=logits)

        params = [w_conv1, b_conv1, w_conv2, b_conv2, w_conv3, b_conv3, w_conv4, b_conv4, w_fc]

        #optimizeation, SGD with momentum, using learning rate decay after x epoch
        #test 1: simple high-level simple SGD with momentum, learning rate fixed in each step.
        '''
        optimizer = tf.train.MomentumOptimizer(learning_rate,momentum)
        train_op = optimizer.minimize(loss, global_step = tf.train.get_global_step())
        '''
        #test 2: self-implement
        train_op = []
        v = []
        for i,param in enumerate(params):
            grad = tf.gradients(loss, param)[0]
            v.append(tf.Variable(tf.zeros(param.shape), dtype=tf.float32))
            v_temp = momentum * v[i] - learning_rate * grad
            train_op.append( tf.assign_add(param, v_temp) )
            train_op.append( tf.assign(v[i], v_temp))

        #calc accuracy
        predictions = tf.argmax(logits, 1)
        one_hot_y = tf.one_hot(placeholder_y, NUM_LABELS)
        correct_prediction = tf.equal(predictions, tf.argmax(one_hot_y, 1))
        correct_cnt =  tf.reduce_sum(tf.cast(correct_prediction, tf.int32)) #tf.reduce_mean(tf.cast(correct_prediction, tf.float31))
        #acc, acc_op = tf.metrics.accuracy(placeholder_y, predictions) #TODO: this API seems to give a wrong answer in debugging.

        return params, train_op, loss, correct_cnt,predictions

def build_linear_model(placeholder_x,placeholder_y):
    with tf.variable_scope("linear") as scope:
        img_float = convert_image_data_to_float(placeholder_x)

        # This is a simple fully connected network
        img_flattened = tf.reshape(img_float,[-1,np.prod(placeholder_x.shape[1:])])
        weight = tf.get_variable("fc_weight",shape=(img_flattened.shape[1],NUM_LABELS),
                                 initializer=tf.random_normal_initializer(stddev=0.01))
        logits = tf.matmul(img_flattened, weight)
        loss = tf.losses.sparse_softmax_cross_entropy(
            labels=placeholder_y, logits=logits)

        # gradient decent algorithm
        params = [weight]
        learning_rate = 0.001
        grad = tf.gradients(loss, weight)[0]
        train_op = tf.assign_add(weight, -learning_rate * grad)

        #calc accuracy
        predictions = tf.argmax(logits, 1)
        one_hot_y = tf.one_hot(placeholder_y, NUM_LABELS)
        correct_prediction = tf.equal(predictions, tf.argmax(one_hot_y, 1))
        correct_cnt =  tf.reduce_sum(tf.cast(correct_prediction, tf.int32)) #tf.reduce_mean(tf.cast(correct_prediction, tf.float31))
        #acc, acc_op = tf.metrics.accuracy(placeholder_y, predictions)

    return params, train_op, loss, correct_cnt, predictions

test_full_training_set = False

CAE_MODEL_PATH = "../checkpoints/cae/cae_model"
#lr_cae = 0.001
#bs_cae = 256

def train_ae(x, placeholder_x, x_evualate = None):
    # TODO: implement autoencoder training
    train_op, loss, encode_result, img_reconstructed = build_cae_model(placeholder_x)
    cae_saver = tf.train.Saver(max_to_keep=50)
    #x = x[0:512]
    NUM_ITERATIONS = 150    #it takes more time to converge
    NUM_BATCHES = int(math.ceil(x.shape[0]/BATCH_SIZE)) #ceil, make sure to ultilize all the data. Size of each fold may not perfectly align
    loss_changes = np.zeros(NUM_ITERATIONS)

    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        sess.run(tf.local_variables_initializer())
        start_time = datetime.now()
        print("---------------------{} Training CAE -------------------".format(start_time))
        print("Num samples to train: {}, num_batches: {}".format(x.shape[0], NUM_BATCHES))
        for epoch in range(NUM_ITERATIONS):
            # 1) sample-2: shuffle with fixed random seed in each epoch and split into batches. TODO: it's not efficiency to copy data in each epoch. indexing is more efficient.
            shuffledX = shuffle(x,  random_state=epoch)
            loss_val= 0.0; acc_val= 0.0; num_trained_sample = 0; end_time=[]

            for bi  in range(NUM_BATCHES):
                batch_x = shuffledX[bi * BATCH_SIZE : (bi+1)*BATCH_SIZE]
                feed_dict = {placeholder_x: batch_x}
                #2) training
                _, loss_batch, feature_maps, img_rec = sess.run([train_op, loss, encode_result, img_reconstructed],  feed_dict=feed_dict)
                loss_val += loss_batch
            loss_val = loss_val/NUM_BATCHES
            end_time.append(datetime.now())
            print("{}: Epoch {} finished, Training loss: {:.6f}".format(end_time[-1], epoch, loss_val))

            # validation
            if(( (epoch+1) % STEP_VALIDATE_EPOCH== 0) or (epoch+1 == NUM_ITERATIONS)):
                loss_eva, feature_maps, img_rec = sess.run([loss, encode_result, img_reconstructed], feed_dict={placeholder_x:x_evualate})
                loss_changes[epoch] = loss_eva
                print("**** Loss in evaluation set: {:.6f}".format(loss_eva))

            cae_saver.save(sess=sess, save_path=CAE_MODEL_PATH, global_step=epoch)

        print("\r\nFinish Training under setting: lr={} batch_size={}".format(learning_rate, BATCH_SIZE))
        print("==> Training time consumed: {}".format(end_time[-1] - start_time))
        print("==> Training loss: {:.6f}".format(loss_val))
        print("==> Best evaluation loss: {:.6f} in epoch {}" .format(np.min(loss_changes),np.argmin(loss_changes)))

def evaluate_ae(x,placeholder_x):
    # TODO: evaluate your autoencoder

    train_op, loss, encode_result, img_reconstructed = build_cae_model(placeholder_x)
    saver = tf.train.Saver()
    with tf.Session() as sess:
        #saver.restore(sess,tf.train.latest_checkpoint("../checkpoints/well_trained_cae"))
        saver.restore(sess, "../checkpoints/well_trained_cae/cae_model-140") # select the model generated in epoch 3

        loss_eva, feature_maps, img_rec = sess.run([loss, encode_result, img_reconstructed], feed_dict={placeholder_x:x})
        print("==>  Loss in evaluation set: {:.6f}".format(loss_eva))
        #idxs=[1,10,100] # random
        idxs = np.floor(np.random.random(2) * x.shape[0]).astype(int)
        for i in idxs:
            visualize_ae(i, x, feature_maps, img_rec)
        plt.show()
    # show feature map and reconstructed images

# Major interfaces
def train_cnn(x, y, placeholder_x, placeholder_y, cross_validate=False):
    #TODO: reduce size for debug
    #x = x[0:512]
    #y = y[0:512]

    params, train_op, loss, correct_cnt, predictions = build_cnn_model(placeholder_x, placeholder_y)
    cnn_saver = tf.train.Saver(max_to_keep=40) #(var_list=params)

    # 1) sample-1: for cross-validation, split into 5-fold.
    skf = StratifiedKFold(n_splits=NUM_FOLD, random_state=10, shuffle=True)
    fold_idx = 0
    if(cross_validate==True):
        fold_settings = list(skf.split(x,y)) # the index settings of the 5 folds
    else:
        fold_settings = list(skf.split(x,y))[0:1] #pick the first fold
    #set up variables to record performance change
    loss_train_changes = np.zeros((len(fold_settings), NUM_ITERATIONS), dtype = np.float32) #np.zeros((len(fold_settings), int(NUM_ITERATIONS/STEP_VALIDATE_EPOCH)), dtype = np.float32)
    acc_train_changes = np.zeros((len(fold_settings), NUM_ITERATIONS),  dtype = np.float32)
    loss_validate_changes = np.zeros((len(fold_settings), NUM_ITERATIONS),  dtype = np.float32)
    acc_validate_changes = np.zeros((len(fold_settings), NUM_ITERATIONS),  dtype = np.float32)

    print("\r\nStart training\r\nParams setting: learning_rate={}, batch size={}, momentum={}".format(learning_rate, BATCH_SIZE, momentum))
    start_time_cross = datetime.now()
    for fold_idx, [train_index, validation_index] in enumerate(fold_settings):
        #print("TRAIN:", train_index, len(train_index),  "TEST:", validation_index, len(validation_index))
        x_train, y_train = x[train_index],y[train_index]
        x_validate, y_validate = x[validation_index],y[validation_index]

        if(test_full_training_set==True):
            x_train = x
            y_train = y

        NUM_BATCHES = int(math.ceil(x_train.shape[0]/BATCH_SIZE)) #ceil, make sure to ultilize all the data. Size of each fold may not perfectly align

        with tf.Session() as sess:
            sess.run(tf.global_variables_initializer())
            sess.run(tf.local_variables_initializer())
            start_time = datetime.now()
            print("---------------------{} Training Fold {} -------------------".format(start_time, fold_idx))
            print("Num samples to train: {}, num_batches: {}".format(x_train.shape[0], NUM_BATCHES))
            for epoch in range(NUM_ITERATIONS):
                # 1) sample-2: shuffle with fixed random seed in each epoch and split into batches. TODO: it's not efficiency to copy data in each epoch. indexing is more efficient.
                shuffledX, shuffledY = shuffle(x_train, y_train, random_state=epoch)
                loss_val= 0.0; acc_val= 0.0; num_trained_sample = 0; end_time=[]

                for bi  in range(NUM_BATCHES):
                    batch_x = shuffledX[bi * BATCH_SIZE : (bi+1)*BATCH_SIZE]
                    batch_y = shuffledY[bi * BATCH_SIZE : (bi+1)*BATCH_SIZE]
                    feed_dict = {placeholder_x: batch_x, placeholder_y: batch_y}
                    #2) training
                    _,loss_batch, correct_batch , pred_val = sess.run([train_op, loss, correct_cnt, predictions],  feed_dict=feed_dict)

                    loss_val += loss_batch # or loss.eval(feed_dict = feed_dict)
                    acc_val += correct_batch # add up the number of correct predictions in each batch
                    num_trained_sample += batch_x.shape[0] #secure, since it may not equal to NUM_BATCHES * BATCH_SIZE
                    #print("debug: ",  batch_y, pred_val, acc_batch)

                #report performance in training set
                end_time.append(datetime.now())
                acc_val = acc_val/num_trained_sample
                loss_val = loss_val/NUM_BATCHES
                print("{}: Epoch {} finished, Training loss: {:.4f}, acc: {:.4f}".format(end_time[-1], epoch, loss_val, acc_val))

                #store the performance and the model
                loss_train_changes[fold_idx][epoch] = loss_val
                acc_train_changes[fold_idx][epoch] = acc_val
                if(epoch>3):
                    cnn_saver.save(sess=sess, save_path=CNN_MODEL_PATH, global_step=epoch)

                # 3) validate and save every 5 epoches
                if(( (epoch+1) % STEP_VALIDATE_EPOCH== 0) or (epoch+1 == NUM_ITERATIONS)):
                    #NUM_BATCHES_VALIDATE = int(math.ceil(x_train.shape[0]/BATCH_SIZE))
                    #for bi in range(NUM_BATCHES_VALIDATE):
                    if(test_full_training_set==True): #validate directly on the test set
                        x_validate, y_validate = get_test_set()
                    feed_dict_validate={placeholder_x: x_validate, placeholder_y: y_validate}
                    loss_validate, correct_cnt_validate  = sess.run([loss, correct_cnt],  feed_dict=feed_dict_validate)
                    acc_validate = correct_cnt_validate/x_validate.shape[0]
                    print("**** Validation loss: {:.4f}, acc: {:.4f}".format(loss_validate, acc_validate))

                    loss_validate_changes[fold_idx][epoch] = loss_validate
                    acc_validate_changes[fold_idx][epoch] = acc_validate

            print("==> Training time consumed: {}".format(end_time[-1] - start_time))
            print("==> Best acc: {} in epoch {}" .format(np.max(acc_validate_changes[fold_idx]),np.argmax(acc_validate_changes[fold_idx])))

    end_time_cross = datetime.now()
    # comput the performance of the training set
    print("\r\nFinish training in {} \r\nParams setting: learning_rate={}, batch size={}, momentum={}".format(end_time_cross - start_time_cross, learning_rate, BATCH_SIZE, momentum))
    #best_epoch = np.argmax(acc_train_changs[])
    print("==> Loss on training set of fold 0: {:.4f}".format(loss_train_changes[0][-1]))
    print("==> Accuarcy on training set of fold 0: {:.4f}".format(acc_train_changes[0][-1]))
    print("==> Loss on validation set of fold 0: {:.4f}".format(loss_validate_changes[0][-1]))
    print("==> Accuarcy on valiationc set of fold 0: {:.4f}".format(acc_validate_changes[0][-1]))

    # average performance on 5-folds
    if(cross_validate==True):
        #loss_folds = loss_validate_changes[:, -1] #TODO: acc in last epoch may not be the best and stable enough to represent the performance in current fold. Use average filter.
        loss_folds = np.min(loss_validate_changes, axis=1)
        # acc of each validatation set in  k-folds
        #acc_folds = acc_validate_changes[:,-1]
        acc_folds = np.max(acc_validate_changes, axis=1)
        print("\r\n==> {}-fold cross_validation result (best acc among each fold): {} \r\n==>Average acc over 5-fold: {:.4f} ".format(NUM_FOLD, acc_folds, np.mean(acc_folds)))
        print("==>Average loss over 5-fold: {:.4f}".format(np.mean(loss_folds)))
    # store the performance change over time into npz
    hyper_param_str = "lr{}bs{}mf{}".format(learning_rate, BATCH_SIZE, momentum)
    np.savez_compressed('./performance_change_'+hyper_param_str+'.npz',
                            loss_train = loss_train_changes, acc_train = acc_train_changes,
                            loss_validate = loss_validate_changes, acc_validate = acc_validate_changes)
    verbose=True
    if(verbose==True):
        # plot performance change over time for different param settings
        print("\r\nPerformace changes over time under: learning_rate={}, batch size={}, momentum={}".format(learning_rate, BATCH_SIZE, momentum))
        print("loss changes in training set:\r\n",loss_train_changes[0])
        print("acc changes in training set:\r\n",acc_train_changes[0])
        print("loss changes (every {} epochs) in validation set:\r\n{}".format(STEP_VALIDATE_EPOCH, loss_validate_changes[0]))
        print("acc changes (every {} epochs) in validation set:\r\n{}".format(STEP_VALIDATE_EPOCH, acc_validate_changes[0]))

def get_test_set():
    file_test = np.load("../datasets/data_classifier_test.npz")
    x_test = file_test["x_test"]
    y_test = file_test["y_test"]

    return x_test, y_test

def test_cnn(x, y, placeholder_x, placeholder_y):
    # TODO: implement CNN testing

    params, train_op, loss, correct_cnt, predictions = build_cnn_model(placeholder_x, placeholder_y)
    with tf.Session() as sess:
        #saver = tf.train.import_meta_graph(CNN_MODEL_PATH + "-4.meta")
        saver = tf.train.Saver()
        #saver.restore(sess,tf.train.latest_checkpoint("../checkpoints/well_trained"))
        saver.restore(sess, "../checkpoints/well_trained/cnn_model-12") # select the model generated in epoch 3
        #print(tf.train.latest_checkpoint("../checkpoints/"))

        NUM_BATCHES = int(math.ceil(x.shape[0]/BATCH_SIZE))
        loss_val = 0; acc_val=0; num_trained_sample=0
        feed_dict = {placeholder_x: x, placeholder_y: y}
        result_loss, correct_val = sess.run([loss, correct_cnt],feed_dict=feed_dict)
        result_accuracy = correct_val / x.shape[0]
        print("\r\nPerformance on test set.")
        print("==> Loss: {:.4f}, Acc: {:.4f}".format(result_loss, result_accuracy))

        #TODO: ensemble the 5 model of the 5-fold
        '''
        for bi in range(NUM_BATCHES):
            batch_x = x[bi * BATCH_SIZE : (bi+1)*BATCH_SIZE]
            batch_y = y[bi * BATCH_SIZE : (bi+1)*BATCH_SIZE]
            feed_dict = {placeholder_x: batch_x, placeholder_y: batch_y}

            loss_cur, acc_cur = sess.run([loss, acc_op],feed_dict=feed_dict)

            loss_val += loss_cur
            acc_val += acc_cur
            num_trained_sample += batch_x.shape[0]

        result_accuracy = acc_val/num_trained_sample
        '''
    return result_accuracy

def main():
    global BATCH_SIZE, learning_rate, momentum

    parser = argparse.ArgumentParser(description='COMP5212 Programming Project 2')
    parser.add_argument('--task', default="train_cnn", type=str,
                        help='Select the task, train_cnn, test_cnn, '
                             'train_ae, evaluate_ae, ')
    parser.add_argument('--datapath',default="../datasets",type=str, required=False, help='Select the path to the data directory')
    parser.add_argument('--cross_validate',default=1,type=int, required=False, help='Set 1 to use cross validation for tuning')
    parser.add_argument('--lr',default=0.001,type=float, required=False, help='learning rate')
    parser.add_argument('--momentum',default=0.9,type=float, required=False, help='momentum facotr of SGD optimizer')
    parser.add_argument('--batch_size',default=256,type=int, required=False, help='batch size')
    args = parser.parse_args()

    datapath = args.datapath
    flag_cross_validate = args.cross_validate
    BATCH_SIZE = args.batch_size
    learning_rate = args.lr
    momentum = args.momentum

    # set up the input image size, create the correspond place holder.
    with tf.variable_scope("placeholders"):
        img_var = tf.placeholder(tf.uint8, shape=(None, 28, 28), name="img")
        label_var = tf.placeholder(tf.int32, shape=(None,), name="true_label")

    if args.task == "train_cnn":
        file_train = np.load(datapath+"/data_classifier_train.npz")
        x_train = file_train["x_train"]
        y_train = file_train["y_train"]
        train_cnn(x_train, y_train, img_var, label_var, cross_validate=flag_cross_validate)

    elif args.task == "test_cnn":
        file_test = np.load(datapath+"/data_classifier_test.npz")
        x_test = file_test["x_test"]
        y_test = file_test["y_test"]
        accuracy = test_cnn(x_test, y_test,img_var,label_var)
        print("accuracy = {}\n".format(accuracy))
    elif args.task == "train_ae":
        file_unsupervised = np.load(datapath + "/data_autoencoder_train.npz")
        x_ae_train = file_unsupervised["x_ae_train"]
        file_unsupervised = np.load(datapath + "/data_autoencoder_eval.npz")
        x_ae_eval = file_unsupervised["x_ae_eval"]
        train_ae(x_ae_train, img_var, x_evualate = x_ae_eval)
    elif args.task == "evaluate_ae":
        file_unsupervised = np.load(datapath + "/data_autoencoder_eval.npz")
        x_ae_eval = file_unsupervised["x_ae_eval"]
        evaluate_ae(x_ae_eval, img_var)

if __name__ == "__main__":
    main()


from typing import Optional

import torch
from torch import nn

from vision_models_playground.utility.config import build_object_from_config_path

def load_model_from_weights(
        model: nn.Module,
        weights_path: str,
        device: Optional[torch.device] = None
):
    """
    Load the weights of a model

    Arguments
    ---------
    model: nn.Module
        The model to load the weights into. It needs to be the same model as the one used to save the weights

    weights_path: str
        The path to the weights

    device: Optional[torch.device]
        The device to load the weights to. If None, it will be loaded to the device the model is on
    """

    if device is None:
        device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

    model.load_state_dict(
        torch.load(weights_path, map_location=device)
    )

    return model

def load_model_from_config(
        config_path: str,
        weights_path: str,
        device: Optional[torch.device] = None,
):
    """
    Load a model from a config file and weights

    Arguments
    ---------
    config_path: str
        The path to the config file

    weights_path: str
        The path to the weights

    device: Optional[torch.device]
        The device to load the weights to. If None, it will be loaded to the device the model is on
    """

    model = build_object_from_config_path(config_path)
    model = load_model_from_weights(model, weights_path, device)

    return model

def load_model_from_dir(
        save_dir: str,
        device: Optional[torch.device] = None,
        file_name: str = 'best'
):
    """
    Load the best model from a save directory

    Arguments
    ---------
    save_dir: str
        The directory to load the model from

    device: Optional[torch.device]
        The device to load the weights to. If None, it will be loaded to the device the model is on

    file_name: str
        The name of the file to load the weights from
    """
    config_path = f'{save_dir}/config.json'
    weights_path = f'{save_dir}/{file_name}.pt'

    return load_model_from_config(config_path, weights_path, device)


#!/usr/bin/python3
"""
Module containing ways of pronouncing a word,
using howjsay website (online) and pyttsx3 (local)
"""
from playsound import playsound
import pyttsx3

engine = pyttsx3.init()
engine.setProperty("rate", 125)

try:
    with open("blacklist", "r") as f:
        blacklist = f.read().split("\n")
    if blacklist[-1] == "":
        blacklist = blacklist[:-1]
except FileNotFoundError:
    print("Can't find 'blacklist' file")
    blacklist = []

def pronounce(raw_word):
    """pronounces the given word"""
    word = ""
    for i in raw_word:
        if i in "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz":
            word += i.lower()
        else:
            word += " "
    if " " in word:
        split_word = word.split(" ")
        for i in split_word:
            pronounce(i)
    else:
        if word != "" and word not in blacklist:
            url = "https://howjsay.com/mp3/" + word + ".mp3"
            playsound(url)

def tts(word):
    """says the selected word using pyttsx3 module"""
    engine.say(word)
    engine.runAndWait()


from collections import defaultdict
import os
import torch
import errno
class Analysis_Util:
    @staticmethod
    def mkdir_if_missing(dirname):
        """Create dirname if it is missing."""
        if not os.path.exists(dirname):
            try:
                os.makedirs(dirname)
            except OSError as e:
                if e.errno != errno.EEXIST:
                    raise

    @staticmethod
    def save_results(content, output_dir,fname):
        """Writes to a json file."""
        Analysis_Util.mkdir_if_missing(output_dir)
        filename = os.path.join(output_dir,fname)
        torch.save(content,filename)


import tensorflow as tf
import config as cfg
from tensorflow.python.framework import graph_util
WEIGHTS_INIT = cfg.CKPT2PB_CKPT_FILE
__weights_init = WEIGHTS_INIT

output_node_sbbox = "yolov3/pred_sbbox/concat_2"
output_node_mbbox = "yolov3/pred_mbbox/concat_2"
output_node_lbbox = "yolov3/pred_lbbox/concat_2"
output_node_name = "yolov3/pred_sbbox/concat_2,yolov3/pred_mbbox/concat_2,yolov3/pred_lbbox/concat_2"
moving_ave_decay = cfg.MOVING_AVE_DECAY

output_graph = cfg.CKPT2PB_PB_NAME

saver = tf.train.import_meta_graph(__weights_init + '.meta', clear_devices=True)
graph = tf.get_default_graph()  # 获得默认的图
input_graph_def = graph.as_graph_def()  # 返回一个序列化的图代表当前的图

with tf.Session() as sess:
    saver.restore(sess, __weights_init)  # 恢复图并得到数据
    output_graph_def = graph_util.convert_variables_to_constants(  # 模型持久化，将变量值固定
        sess=sess,
        input_graph_def=sess.graph_def,  # 等于:sess.graph_def
        output_node_names=output_node_name.split(","))  # 如果有多个输出节点，以逗号隔开
        #output_node_names=[output_node_sbbox, output_node_mbbox, output_node_lbbox])

    with tf.gfile.GFile(output_graph, "wb") as f:  # 保存模型
        f.write(output_graph_def.SerializeToString())  # 序列化输出
    print("%d ops in the final graph." % len(output_graph_def.node))  # 得到当前图有几个操作节点

"""

org_weights_mess = []

G = tf.Graph()
with G.as_default():
    load = tf.train.import_meta_graph(__weights_init + '.meta', clear_devices=True)
    with tf.Session(graph=G) as sess_G:
        load.restore(sess_G, __weights_init)
        for var in tf.global_variables():
            var_name = var.op.name
            var_name_mess = str(var_name).split('/')
            var_shape = var.shape
            #if var_name_mess[-1] != 'pred_sbbox':
                #continue
            # print(var_name_mess[0])
            org_weights_mess.append([var_name, var_shape])
            print(var_name)
            print("\n")
print(org_weights_mess)
"""


from sys import platform
from babel.dates import format_date
try:
    import tkinter as tk
    from tkinter import ttk
except ImportError:
    import Tkinter as tk
    import ttk
from tkcalendar import Calendar,DateEntry
import re

class CustomCalendar(Calendar):
    def _get_date_pattern(self,date_pattern,locale=None):
        """
        Return the babel pattern corresponding to date_pattern.

        If date_pattern is 'short', return the pattern correpsonding to the
        locale, else return date_pattern if valid.

        A valid pattern is a sequence of y, m and d
        separated by non letter characters, e.g. yyyy-mm-dd or d/m/yy
        """
        if locale is None:
            locale = self._properties['locale']
        if date_pattern == 'short':
            return get_date_format('short',locale).pattern
        pattern = date_pattern.lower()
        ymmd = r'^y+[^a-zA-Z]*m{1,3}&m{1,3}[^a-z]*d{1,2}[^mdy]*$'
        ymd = r'^y+[^a-zA-Z]*m{1,3}[^a-z]*d{1,2}[^mdy]*$'
        mdy = r'^m{1,2}[^a-zA-Z]*d{1,2}[^a-z]*y+[^mdy]*$'
        dmy = r'^d{1,2}[^a-zA-Z]*m{1,2}[^a-z]*y+[^mdy]*$'
        res = ((re.search(ymmd,pattern) is not None)
               or (re.search(ymd,pattern) is not None)
               or (re.search(mdy,pattern) is not None)
               or (re.search(dmy,pattern) is not None))
        if res:
            return pattern.replace('m','M')
        raise ValueError('{} is not a valid date pattern'.format(date_pattern))

    def format_date(self,date=None):
        """Convert date (datetime.date) to a string in the locale."""
        return format_date(date,self._properties['date_pattern'],self._properties['locale']).replace('&','')

    def parse_date(self,date):
        """Parse string date in the locale format and return the corresponding datetime.date."""
        try:
            date_format = self._properties['date_pattern'].lower()
            ny = date_format.count('y')
            nm = date_format.count('m')
            nd = date_format.count('d')
            if nm == 5:
                ymd = r'^y+([^a-zA-Z]*)mm\&mmm([^a-z]*)d{1,2}([^mdy]*)$'
                m = re.search(ymd,date_format)
                if not m:
                    raise ValueError('{} is not a valid date format'.format(date_format))
                sep1 = m.group(1)
                sep2 = m.group(2)
                sep3 = m.group(3)
                ymd = '^('+'\d'*ny+')'+sep1+'\d\d('+'[a-zA-Z]'*3+')'+sep2+'('+'\d'*nd+')'+sep3+'$'
                m = re.search(ymd,date)
                if not m:
                    raise ValueError('{} is not a valid date'.format(date))
                year = m.group(1)
                if len(year) == 2:
                    year = 2000 + int(year)
                else:
                    year = int(year)
                month = self.strptime(m.group(2),'%b').month
                day = int(m.group(3))
            elif nm == 3:
                ymd = r'^y+([^a-zA-Z]*)mmm([^a-z]*)d{1,2}([^mdy]*)$'
                m = re.search(ymd,date_format)
                if not m:
                    raise ValueError('{} is not a valid date format'.format(date_format))
                sep1 = m.group(1)
                sep2 = m.group(2)
                sep3 = m.group(3)
                ymd = '^('+'\d'*ny+')'+sep1+'('+'[a-zA-Z]'*nm+')'+sep2+'('+'\d'*nd+')'+sep3+'$'
                m = re.search(ymd,date)
                if not m:
                    raise ValueError('{} is not a valid date'.format(date))
                year = m.group(1)
                if len(year) == 2:
                    year = 2000 + int(year)
                else:
                    year = int(year)
                month = self.strptime(m.group(2),'%b').month
                day = int(m.group(3))
            else:
                year_idx = date_format.index('y')
                month_idx = date_format.index('m')
                day_idx = date_format.index('d')
                indexes = [(year_idx,'Y'),(month_idx,'M'),(day_idx,'D')]
                indexes.sort()
                indexes = dict([(item[1],idx) for idx,item in enumerate(indexes)])
                numbers = re.findall(r'(\d+)',date)
                year = numbers[indexes['Y']]
                if len(year) == 2:
                    year = 2000 + int(year)
                else:
                    year = int(year)
                month = int(numbers[indexes['M']])
                day = int(numbers[indexes['D']])
                if month > 12:
                    month,day = day,month
            return self.date(year,month,day)
        except Exception:
            return self.datetime.today()

class CustomDateEntry(DateEntry):
    def __init__(self,master=None,**kw):
        """
        Create an entry with a drop-down calendar to select a date.

        When the entry looses focus, if the user input is not a valid date,
        the entry content is reset to the last valid date.

        Keyword Options
        ---------------

        usual ttk.Entry options and Calendar options.
        The Calendar option 'cursor' has been renamed
        'calendar_cursor' to avoid name clashes with the
        corresponding ttk.Entry option.

        Virtual event
        -------------

        A ``<<DateEntrySelected>>`` event is generated each time
        the user selects a date.

        """
        # sort keywords between entry options and calendar options
        kw['selectmode'] = 'day'
        entry_kw = {}

        style = kw.pop('style','DateEntry')

        for key in self.entry_kw:
            entry_kw[key] = kw.pop(key,self.entry_kw[key])
        entry_kw['font'] = kw.get('font',None)
        self._cursor = entry_kw['cursor']  # entry cursor
        kw['cursor'] = kw.pop('calendar_cursor',None)

        ttk.Entry.__init__(self,master,**entry_kw)

        self._determine_downarrow_name_after_id = ''

        # drop-down calendar
        self._top_cal = tk.Toplevel(self)
        self._top_cal.withdraw()
        if platform == 'linux':
            self._top_cal.attributes('-type','DROPDOWN_MENU')
        self._top_cal.overrideredirect(True)
        self._calendar = CustomCalendar(self._top_cal,**kw)
        self._calendar.pack()

        # locale date parsing / formatting
        self.format_date = self._calendar.format_date
        self.parse_date = self._calendar.parse_date

        # style
        self._theme_name = ''   # to detect theme changes
        self.style = ttk.Style(self)
        self._setup_style()
        self.configure(style=style)

        # add validation to Entry so that only dates in the locale's format
        # are accepted
        validatecmd = self.register(self._validate_date)
        self.configure(validate='focusout',
                       validatecommand=validatecmd)

        # initially selected date
        self._date = self._calendar.selection_get()
        if self._date is None:
            today = self._calendar.date.today()
            year = kw.get('year',today.year)
            month = kw.get('month',today.month)
            day = kw.get('day',today.day)
            try:
                self._date = self._calendar.date(year,month,day)
            except ValueError:
                self._date = today
        self._set_text(self.format_date(self._date))

        # --- bindings
        # reconfigure style if theme changed
        self.bind('<<ThemeChanged>>',
                  lambda e: self.after(10,self._on_theme_change))
        # determine new downarrow button bbox
        self.bind('<Configure>',self._determine_downarrow_name)
        self.bind('<Map>',self._determine_downarrow_name)
        # handle appearence to make the entry behave like a Combobox but with
        # a drop-down calendar instead of a drop-down list
        self.bind('<Leave>',lambda e: self.state(['!active']))
        self.bind('<Motion>',self._on_motion)
        self.bind('<ButtonPress-1>',self._on_b1_press)
        # update entry content when date is selected in the Calendar
        self._calendar.bind('<<CalendarSelected>>',self._select)
        # hide calendar if it looses focus
        self._calendar.bind('<FocusOut>',self._on_focus_out_cal)

    def _validate_date(self):
        """Date entry validation: only dates in locale '%x' format are accepted."""
        try:
            date = self.parse_date(self.get())
            self._date = self._calendar.check_date_range(date)
            if self._date != date:
                self._set_text(self.format_date(self._date))
                return False
            else:
                return True
        except (ValueError,IndexError):
            #self._set_text(self.format_date(self._date))
            return False


#!/usr/bin/python
#-*- coding: utf-8 -*-

import pygame

class Effect(pygame.sprite.Sprite):
    """ Effect"""

    def __init__(self, frames, x_pos, y_pos, fps=100):

        pygame.sprite.Sprite.__init__(self)
        self._images = frames

        self._frame = 0
        self.image = self._images[self._frame]

        self.x, self.y = x_pos, y_pos
        self.rect = self.image.get_rect()
        self.rect.center = (self.x, self.y)
        self.remove_flag = 0

    def update(self, shift=0):
        if self._frame < len(self._images) - 1:
            self._frame += 1
            self.x -= shift
            self.image = self._images[self._frame]
            self.rect.center = self.x, self.y
        else:
            self.remove_flag = 1

    def render(self, screen):
        """ drawing Unit on screen"""
        screen.blit(self.image, self.rect)


import pygame
from constant import *

class PygameApp:
    def __init__(self):
        pygame.init()

        # 游戏窗口大小
        self.WINDOW_WIDTH = 800
        self.WINDOW_HEIGHT = 600

        # 创建游戏窗口
        self.window = pygame.display.set_mode((self.WINDOW_WIDTH, self.WINDOW_HEIGHT))
        pygame.display.set_caption("Pygame 示例")

        # 图像加载器
        self.image_loader = self.ImageLoader(self.window)

    # 图像加载器类
    class ImageLoader:
        def __init__(self, window):
            self.images = []
            self.window = window  # 传递窗口对象

            # 请替换以下路径为你的图像文件路径
            for path in IMAGE_NAME_LIST:
                image = pygame.image.load(path)
                self.images.append(image)

        def get_item_image_by_ID(self, index, row, col):
            rect = pygame.Rect(IMAGE_LOCATION_LIST[index][0], IMAGE_LOCATION_LIST[index][1], 32, 32)
            self.window.blit(self.images[1].subsurface(rect), (6 * 32, 2 * 32))
            return self.images[1].subsurface(rect)

    def draw_image(self):
        # 绘制图像
        self.image_loader.get_item_image_by_ID(1, 6 * 32, 2 * 32)
        self.image_loader.get_item_image_by_ID(5, 6 * 32, 2 * 32)

    def clear_image(self):
        # 清空屏幕
        self.window.fill((0, 0, 0))

    def run(self):
        running = True
        clock = pygame.time.Clock()

        while running:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False

            # 清空屏幕
            self.window.fill((0, 0, 0))
            self.draw_image()

            # 刷新屏幕
            pygame.display.flip()

            # 控制游戏帧率
            clock.tick(60)

        # 游戏结束后，关闭 Pygame
        pygame.quit()


import boto3
import json
import os

dynamodb_client = boto3.client('dynamodb')
sqs_client = boto3.client('sqs')

def lambda_handler(event, context):
    order_item = json.loads(event["body"])
    if order_item['receiptHandle']:
        queue_name = os.getenv("QUEUE_NAME")
        queue = sqs_client.get_queue_url(QueueName=queue_name)
        queue_url = queue['QueueUrl']
        response = sqs_client.delete_message(
            QueueUrl=queue_url,
            ReceiptHandle=order_item['receiptHandle']
        )

    response = {
        'statusCode': 200,
        'body': 'successfully handle order!',
        'headers': {
            'Content-Type': 'application/json',
            "Access-Control-Allow-Headers": "Access-Control-Allow-Headers, Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method,X-Access-Token, XKey, Authorization",
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Methods": "GET,PUT,POST,DELETE,OPTIONS"
        },
    }

    return response


import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from config import SMTP_CONFIG
try:
    from mainconfig import ACCOUNT, MAIL_SERVER, CC
except Exception as e:
    from testconfig import ACCOUNT, MAIL_SERVER, CC

def send_email(email=None, subject=None, body=None, include_cc=False):
    mimemsg = MIMEMultipart()
    mimemsg['From'] = 'HR_MANAGER' + '<' + ACCOUNT['email'] + '>'
    mimemsg['To'] = email
    if include_cc and CC:
        mimemsg['Cc'] = CC
    mimemsg['Subject'] = subject
    mimemsg.attach(MIMEText(body, 'plain'))
    try:
        connection = smtplib.SMTP(host=MAIL_SERVER['host'], port=MAIL_SERVER['port'])
        connection.starttls()
        if MAIL_SERVER['host'] == 'smtp.office365.com':
            connection.login(ACCOUNT['email'], ACCOUNT['password'])
        connection.send_message(mimemsg)
        connection.quit()
        return True

    except Exception as e:
        print(e)
        return False


import argparse
import a_star_search as search
from environments import gridEnvP1

parser = argparse.ArgumentParser(prog = 'python3 main.py',
                                 description = 'Implements A* search on a specified dataset.')
parser.add_argument('-d', '--data',
                    default = "./data/100 nodes.csv",
                    dest = "path_to_data",
                    required = True,
                    help = "path to states/environment data.")
parser.add_argument('-s', '--start-state',
                    type = int,
                    required = True,
                    help = "an integer that indicates the starting state.")
parser.add_argument('-g', '--goal-state',
                    type = int,
                    required = True,
                    help = "an integer that indicates the goal state.")
parser.add_argument('-w', '--weight',
                    type = float,
                    required = True,
                    help = "the weight parameter for A* search\
                            to calculate f = w*g + (1-w)*h.\
                            must be between 0 and 1.")
parser.add_argument('-v', '--verbose',
                    action = 'store_true',
                    help = "prints information such as frontier details and best node for every iteration.")

args = vars(parser.parse_args())
filepath = args["path_to_data"]
start = args["start_state"]
goal = args["goal_state"]
w = args["weight"]
v = args["verbose"]

env = gridEnvP1()
env.load(filepath)
env.initialize(start, goal)
result = search.astar_tree_search(env, w, v)

if result:
	result_node = result[0]
	result_frontier = result[1]
	print("Path length: " + str(len(result_node.path)))
	print("Path cost: " + str(result_node.cost))
	print("Path: " + str(result_node.path))
	print("Nodes generated: " + str(result_frontier.generated_nodes))
else:
	print("There is no path")


import torch

DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
TRAIN_DIR = "data/clean/cleaned_train.csv"
PRED_DIR = "data/clean/cleaned_test.csv"
LEARNING_RATE = 1e-3
BATCH_SIZE = 20
NUM_WORKERS = 1
LOAD_MODEL = False
SAVE_MODEL = True
CHECKPOINT = "checkpoints/neural_network/checkpoint.tar"
EPOCHS = 150
FOLDS = 5
EXPERIMENT = False
TRAIN = True
INFERENCE = True


from __future__ import absolute_import

import struct
import logging

log = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)

from wcf.datatypes import *
from wcf.records.base import *
from wcf.dictionary import *

class ShortElementRecord(Element):
    type = 0x40

    def __init__(self, name, *args, **kwargs):
        self.childs = []
        self.name = name
        self.attributes = []

    def to_bytes(self):
        """
        >>> ShortElementRecord('Envelope').to_bytes()
        '@\\x08Envelope'
        """
        string = Utf8String(self.name)

        bytes= (super(ShortElementRecord, self).to_bytes() +
                string.to_bytes())

        for attr in self.attributes:
            bytes += attr.to_bytes()
        return bytes

    def __str__(self):
        #return '<%s[name=%s]>' % (type(self).__name__, self.name)
        return '<%s %s>' % (self.name,
                ' '.join([str(a) for a in self.attributes]))

    @classmethod
    def parse(cls, fp):
        name = Utf8String.parse(fp).value
        return cls(name)

class ElementRecord(ShortElementRecord):
    type = 0x41

    def __init__(self, prefix, name, *args, **kwargs):
        super(ElementRecord, self).__init__(name)
        self.prefix = prefix

    def to_bytes(self):
        """
        >>> ElementRecord('x', 'Envelope').to_bytes()
        'A\\x01x\\x08Envelope'
        """
        pref = Utf8String(self.prefix)
        data = super(ElementRecord, self).to_bytes()
        type = data[0]
        return (type + pref.to_bytes() + data[1:])

    def __str__(self):
        return '<%s:%s %s>' % (self.prefix, self.name,
                ' '.join([str(a) for a in self.attributes]))

    @classmethod
    def parse(cls, fp):
        prefix = Utf8String.parse(fp).value
        name = Utf8String.parse(fp).value
        return cls(prefix, name)

class ShortDictionaryElementRecord(Element):
    type = 0x42

    def __init__(self, index, *args, **kwargs):
        self.childs = []
        self.index = index
        self.attributes = []
        self.name = dictionary[self.index]

    def __str__(self):
        return '<%s %s>' % (self.name, ' '.join([str(a) for a in
            self.attributes]))

    def to_bytes(self):
        """
        >>> ShortDictionaryElementRecord(2).to_bytes()
        'B\\x02'
        """
        string = MultiByteInt31(self.index)

        bytes= (super(ShortDictionaryElementRecord, self).to_bytes() +
                string.to_bytes())

        for attr in self.attributes:
            bytes += attr.to_bytes()
        return bytes

    @classmethod
    def parse(cls, fp):
        index = MultiByteInt31.parse(fp).value
        return cls(index)

class DictionaryElementRecord(Element):
    type = 0x43

    def __init__(self, prefix, index, *args, **kwargs):
        self.childs = []
        self.prefix = prefix
        self.index = index
        self.attributes = []
        self.name = dictionary[self.index]

    def __str__(self):
        """
        >>> str(DictionaryElementRecord('x', 2))
        '<x:Envelope >'
        """
        return '<%s:%s %s>' % (self.prefix, self.name,
                ' '.join([str(a) for a in self.attributes]))

    def to_bytes(self):
        """
        >>> DictionaryElementRecord('x', 2).to_bytes()
        'C\\x01x\\x02'
        """
        pref = Utf8String(self.prefix)
        string = MultiByteInt31(self.index)

        bytes = (super(DictionaryElementRecord, self).to_bytes() +
                pref.to_bytes() +
                string.to_bytes())

        for attr in self.attributes:
            bytes += attr.to_bytes()
        return bytes

    @classmethod
    def parse(cls, fp):
        prefix = Utf8String.parse(fp).value
        index = MultiByteInt31.parse(fp).value
        return cls(prefix, index)

class PrefixElementRecord(ElementRecord):
    def __init__(self, name):
        super(PrefixElementRecord, self).__init__(self.char, name)

    def to_bytes(self):
        string = Utf8String(self.name)

        bytes = (struct.pack('<B', self.type) +
                string.to_bytes())

        for attr in self.attributes:
            bytes += attr.to_bytes()
        return bytes

    @classmethod
    def parse(cls, fp):
        name = Utf8String.parse(fp).value
        return cls(name)

class PrefixDictionaryElementRecord(DictionaryElementRecord):
    def __init__(self, index):
        super(PrefixDictionaryElementRecord, self).__init__(self.char, index)

    def to_bytes(self):
        string = MultiByteInt31(self.index)

        bytes = (struct.pack('<B', self.type) +
                string.to_bytes())

        for attr in self.attributes:
            bytes += attr.to_bytes()
        return bytes

    @classmethod
    def parse(cls, fp):
        index = MultiByteInt31.parse(fp).value
        return cls(index)

Record.add_records((
        ShortElementRecord,
        ElementRecord,
        ShortDictionaryElementRecord,
        DictionaryElementRecord,
    ))

__records__ = []

for c in range(0x44, 0x5D + 1):
    char = chr(c - 0x44 + ord('a'))
    cls = type(
           'PrefixDictionaryElement' + char.upper() + 'Record',
           (PrefixDictionaryElementRecord,),
           dict(
                type=c,
                char=char,
            )
           )
    __records__.append(cls)

for c in range(0x5E, 0x77 + 1):
    char = chr(c - 0x5E + ord('a'))
    cls = type(
           'PrefixElement' + char.upper() + 'Record',
           (PrefixElementRecord,),
           dict(
                type=c,
                char=char,
            )
           )
    __records__.append(cls)

Record.add_records(__records__)
del __records__