#vim: set expandtab ts=4 sw=4 filetype=python:

import datetime
import logging
import textwrap

import psycopg2

from budgetbot.webapp.framework.handler import Handler
from budgetbot.webapp.framework.response import Response

log = logging.getLogger(__name__)

module_template_prefix = 'shoppinglist'
module_template_package = 'budgetbot.webapp.shoppinglist.templates'

__all__ = ['AllLists', 'AllItems', 'AllStores', 'ShoppingListDeets',
    'ShoppingListUsers', 'InsertShoppingItem', 'InsertShoppingList',
    'DeleteShoppingList',
    'DeleteShoppingItem', 'InsertShoppingListUser' ]

class AllLists(Handler):

    route_strings = set(['GET /api/shopping-lists'])
    route = Handler.check_route_strings

    @Handler.require_login
    def handle(self, req):
        pgconn = self.cw.get_pgconn()

        cursor = pgconn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)

        cursor.execute(textwrap.dedent("""

            select *

            from shopping_lists sl

            where creator_uuid = %(person_uuid)s

            and removed = false

        """), {'person_uuid': req.user.person_uuid})

        my_lists = cursor.fetchall()

        cursor.execute(textwrap.dedent("""

            select *

            from shopping_lists sl

            join shopping_lists_people slp
            on slp.shopping_list_id = sl.shopping_list_id

            where

            slp.person_uuid = %(person_uuid)s

            and sl.removed = false

        """), {'person_uuid': req.user.person_uuid})

        shared_with_me = cursor.fetchall()

        return Response.json(dict(
            reply_timestamp=datetime.datetime.now(),
            success=True,
            message="Returning Shopping Lists",
            shared_lists=shared_with_me,
            lists=my_lists))

class InsertShoppingList(Handler):

    route_strings = set(['POST /api/insert-shopping-list'])
    route = Handler.check_route_strings

    @Handler.require_login
    def handle(self, req):

        log.info("adding new shopping list {0}".format(req.json))
        pgconn = self.cw.get_pgconn()

        cursor = pgconn.cursor()

        cursor.execute(textwrap.dedent("""

            insert into shopping_lists

            (shopping_list_name, store, creator_uuid)

            values

            (%(shopping_list_name)s, %(store)s, %(person_uuid)s)

            returning shopping_list_id

        """), dict(shopping_list_name=req.json['shopping_list_name'],
            store=req.json['store'],
            person_uuid=req.user.person_uuid))

        result = cursor.fetchone()

        return Response.json(dict(
            reply_timestamp=datetime.datetime.now(),
            success=True,
            message="Inserted list",
            shopping_list_id=result.shopping_list_id))

class DeleteShoppingList(Handler):

    route_strings = set(['POST /api/delete-shopping-list'])
    route = Handler.check_route_strings

    @Handler.require_login
    def handle(self, req):

        log.info("deleting shopping list {0}".format(req.json))
        pgconn = self.cw.get_pgconn()

        cursor = pgconn.cursor()

        cursor.execute(textwrap.dedent("""

            update shopping_lists

            set removed = true

            where shopping_list_id = %(shopping_list_id)s

            returning shopping_list_id

        """), dict(shopping_list_id=req.json['shopping_list_id']))

        result = cursor.fetchone()

        return Response.json(dict(
            reply_timestamp=datetime.datetime.now(),
            success=True,
            message="Removed list",
            shopping_list_id=result.shopping_list_id))

class ShoppingListDeets(Handler):

    route_strings = set(['GET /api/shopping-list-deets'])
    route = Handler.check_route_strings

    @Handler.require_login
    def handle(self, req):
        pgconn = self.cw.get_pgconn()

        log.debug(req.wz_req.args)

        cursor = pgconn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)

        cursor.execute(textwrap.dedent("""

            select shopping_list_name, store

            from shopping_lists

            where shopping_list_id = %(shopping_list_id)s

        """), {'shopping_list_id': req.wz_req.args.get('shopping_list_id')})

        return Response.json(dict(
            reply_timestamp=datetime.datetime.now(),
            success=True,
            message="Shopping list deets",
            deets=cursor.fetchone()))

class ShoppingListUsers(Handler):

    route_strings = set(['GET /api/shopping-list-users'])
    route = Handler.check_route_strings

    @Handler.require_login
    def handle(self, req):
        pgconn = self.cw.get_pgconn()

        log.debug(req.wz_req.args)

        cursor = pgconn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)

        cursor.execute(textwrap.dedent("""

            select p.email_address, p.display_name, p.person_uuid

            from shopping_lists_people slp
            join people p on p.person_uuid = slp.person_uuid

            where slp.shopping_list_id = %(shopping_list_id)s

        """), {'shopping_list_id': req.wz_req.args.get('shopping_list_id')})

        return Response.json(dict(
            reply_timestamp=datetime.datetime.now(),
            success=True,
            message="Shopping list deets",
            people=cursor.fetchall()))

class AllItems(Handler):

    route_strings = set(['GET /api/shopping-list-items'])
    route = Handler.check_route_strings

    @Handler.require_login
    def handle(self, req):
        pgconn = self.cw.get_pgconn()

        # TODO -- Make sure that user has access to shopping list

        cursor = pgconn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)

        cursor.execute(textwrap.dedent("""

            select *

            from shopping_list_items

            where shopping_list_id = %(shopping_list_id)s

        """), {'shopping_list_id': req.wz_req.args.get('shopping_list_id')})

        return Response.json(dict(
            reply_timestamp=datetime.datetime.now(),
            success=True,
            message="Returning Shopping List Items",
            items=cursor.fetchall()))

class AllStores(Handler):

    route_strings = set(['GET /api/all-stores'])
    route = Handler.check_route_strings

    @Handler.require_login
    def handle(self, req):
        pgconn = self.cw.get_pgconn()

        cursor = pgconn.cursor()

        log.info("json req is {0}".format(req.user))

        cursor.execute(textwrap.dedent("""

            select store

            from stores

        """))

        return Response.json(dict(
            reply_timestamp=datetime.datetime.now(),
            success=True,
            message="Shopping list store types",
            stores=[row.store for row in cursor.fetchall()]))

class InsertShoppingItem(Handler):

    route_strings = set(['POST /api/insert-shopping-item'])
    route = Handler.check_route_strings

    @Handler.require_login
    def handle(self, req):

        log.info("adding new shopping item {0}".format(req.json))
        pgconn = self.cw.get_pgconn()

        cursor = pgconn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)

        # IF a user adds an item to a list, we need to make sure
        # They have rights to add that item

        cursor.execute(textwrap.dedent("""

            insert into items

            (item, inserted_by)

            select %(item)s, %(person_uuid)s

            where not exists (
                select item from items where item =  %(item)s)

        """), dict(item=req.json['item'],
            person_uuid=req.user.person_uuid))

        # Then do the actual insert

        cursor.execute(textwrap.dedent("""

            insert into shopping_list_items

            (item, shopping_list_id, inserted_by)

            values

            (%(item)s, %(shopping_list_id)s, %(person_uuid)s)

            returning *

        """), dict(item=req.json['item'],
            shopping_list_id=req.json['shopping_list_id'],
            person_uuid = req.user.person_uuid))

        result = cursor.fetchone()

        return Response.json(dict(
            reply_timestamp=datetime.datetime.now(),
            success=True,
            message="Inserted item",
            item_inserted=result))

class DeleteShoppingItem(Handler):

    route_strings = set(['POST /api/delete-shopping-item'])
    route = Handler.check_route_strings

    @Handler.require_login
    def handle(self, req):

        cursor = self.cw.get_pgconn().cursor()

        # TODO Make sure we have rights to delete this item

        cursor.execute(textwrap.dedent("""

            delete from shopping_list_items

            where item = %(item)s

        """),{'item':req.json['item']})

        return Response.json(dict(
            reply_timestamp=datetime.datetime.now(),
            success=True,
            message="Removed item"))

class InsertShoppingListUser(Handler):

    route_strings = set(['POST /api/insert-shopping-list-user'])
    route = Handler.check_route_strings

    @Handler.require_login
    def handle(self, req):

        # TODO: user request must own shopping list

        log.info("connecting shopping list {0} to person {1}".\
            format(req.json.get('shopping_list_id'),
            req.json.get('person_uuid')))

        cursor = self.cw.get_pgconn().cursor()

        cursor.execute(textwrap.dedent("""

            insert into shopping_lists_people

            (shopping_list_id, person_uuid)

            values

            (%(shopping_list_id)s, %(person_uuid)s)

            """), dict(shopping_list_id=req.json['shopping_list_id'],
                person_uuid=req.json['person_uuid']))

        return Response.json(dict(
            reply_timestamp=datetime.datetime.now(),
            success=True,
            message="Added person to shopping list"))


# -*- coding: utf-8 -*-
import torch.nn as nn
import math

import torch
import torch.nn.functional as F

import numpy as np
import copy

from utils.arch_util import ESA, PA

from RDU import DynamicDiverseBranchBlock as DDBB
from RDU import RepVGGBlock as DRVB
from RDU import DRCB
from RDU import ResDDBB,ResSRB,StaticDCD
import functools

class Unit(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size,
                 stride=1, padding=1, dilation=1, groups=1,
                 internal_channels_1x1_3x3=None, num_experts=4, padding_mode='zeros',
                 deploy=False, dynamic=True, L=None, nonlinear=None, single_init=False, style = 'DBB', res=False, n_channels = None):
        super(Unit,self).__init__()

        #res = true: dynamic = true, style in DBB, VGG
        if n_channels is None:
            n_channels = in_channels

        self.style = style
        self.dynamic = dynamic
        self.res = res

        if style =='DBB':
            self.unit = DDBB(in_channels,out_channels,kernel_size,stride,padding,dilation,groups,internal_channels_1x1_3x3,deploy,dynamic,L,nonlinear,single_init)
        elif style =='VGG':
            self.unit = DRVB(in_channels,out_channels,kernel_size,stride,padding,dilation,groups,padding_mode,nonlinear,deploy,dynamic,L)
        elif style =='CC':
            self.unit = DRCB(in_channels,out_channels,kernel_size,stride,padding,dilation,groups,padding_mode,deploy,num_experts)
        elif style =='ResDBB':
            self.unit = ResDDBB(in_channels,out_channels,n_channels,kernel_size,stride,padding,dilation,groups,internal_channels_1x1_3x3,deploy,dynamic,L,nonlinear,single_init)
        elif style =='SRD':
            self.unit = ResSRB(in_channels,out_channels,kernel_size,stride,padding,dilation,groups,internal_channels_1x1_3x3,deploy,dynamic,L,nonlinear,single_init)
        elif style =='StaticDCD':
            self.unit = StaticDCD(in_channels, out_channels, kernel_size,stride,padding,dilation,groups,dynamic,L,nonlinear)
        else:
            self.unit = nn.Conv2d(in_channels,out_channels,kernel_size,stride,padding,dilation,groups,padding_mode)

        if nonlinear == None:
            self.act = nn.Identity()
        else:
            self.act = nonlinear

    def forward(self, inputs):
        if self.style == 'SRB':
            return self.act(inputs+self.unit(inputs))
        elif self.style == 'Static':
            return self.act(self.unit(inputs))

        if self.dynamic and self.style in {'DBB','VGG','ResDBB','SRD','StaticDCD'}:
            out, res = self.unit(inputs)
            if self.res: return out, res
            else: return out
        else: return self.unit(inputs)

class SeparableConv(nn.Module):
    def __init__(self, n_feats=50, k=3,deploy=True,dynamic=True,L=None,style='DBB',res=False, same = False):
        super(SeparableConv, self).__init__()
        self.res = res

        if not same:
            nf_feats = 2*n_feats
        else:
            nf_feats = n_feats

        if self.res:
             self.conv2 =nn.Conv2d(nf_feats, n_feats, 1, 1, 0)

        self.unit = Unit(n_feats,nf_feats,k,1,(k-1)//2,groups=n_feats,deploy=deploy,dynamic=dynamic,L=L,style=style,res =res)
        self.conv1 =nn.Conv2d(nf_feats, n_feats, 1, 1, 0)

        self.act = nn.LeakyReLU(0.05, True)

    def forward(self, x):
        if self.res:
            out,res = self.unit(x)
            out = self.conv1(self.act(out))
            res = self.conv2(res)
            out += x
            out = self.act(out)
            res = self.act(res)
            return out, res
        else:
            out = self.unit(x)
            out = self.conv1(self.act(out))
            out += x
            out = self.act(out)
            return out

class DFDB(nn.Module):
    def __init__(self, in_channels,deploy=True,dynamic=True,L=None,style='DBB',res=True):
        super(DFDB, self).__init__()
        self.dc = self.distilled_channels = in_channels//2
        self.rc = self.remaining_channels = in_channels
        self.res = res

        self.act = nn.LeakyReLU(0.05, True)

        self.c1_d = nn.Conv2d(in_channels, self.dc, 1, 1, 0, bias=True, dilation = 1, groups=1)
        self.c1_r = Unit(self.remaining_channels, self.rc, 3, deploy=deploy,dynamic=dynamic,L=L,style=style,res=res,nonlinear=self.act)
        self.c2_d = nn.Conv2d(in_channels, self.dc, 1, 1, 0, bias=True, dilation = 1, groups=1)
        self.c2_r = Unit(self.remaining_channels, self.rc, 3, deploy=deploy,dynamic=dynamic,L=L,style=style,res=res,nonlinear=self.act)
        self.c3_d = nn.Conv2d(in_channels, self.dc, 1, 1, 0, bias=True, dilation = 1, groups=1)
        self.c3_r = Unit(self.remaining_channels, self.rc, 3, deploy=deploy,dynamic=dynamic,L=L,style=style,res=res,nonlinear=self.act)
        self.c4 = nn.Conv2d(self.remaining_channels, self.dc, 1, 1, 0, bias=True, dilation = 1, groups=1)
        self.c5 = nn.Conv2d(4*self.dc, in_channels, 1, 1, 0, bias=True, dilation = 1, groups=1)

        if self.res:
            self.PAconv = nn.Conv2d(in_channels, in_channels, 1)
            ##add sconv to enhance res
            #self.sconv = SeparableConv(in_channels,5,deploy,dynamic,L)

            self.conv1x1 = nn.Conv2d(4*in_channels, in_channels, 1, 1, 0, bias=True, dilation = 1, groups=1)
            self.sigmoid = nn.Sigmoid()

        self.esa = ESA(in_channels, nn.Conv2d)

    def forward(self, input):
        if self.res:
            distilled_c1 = self.act(self.c1_d(input))
            r_c1,res1 = self.c1_r(input)

            distilled_c2 = self.act(self.c2_d(r_c1))
            r_c2,res2 = self.c2_r(r_c1)

            distilled_c3 = self.act(self.c3_d(r_c2))
            r_c3,res3 = self.c3_r(r_c2)

            r_c4 = self.c4(r_c3)

            out = torch.cat((distilled_c1, distilled_c2, distilled_c3, r_c4), dim=1)

            out_fused = self.c5(out)

            # dfdb res
            scale = self.sigmoid(self.PAconv(out_fused))
            res = self.conv1x1(torch.cat((input, res1, res2, res3), dim=1))
            res = torch.mul(scale, res)

            out_fused = self.esa(out_fused + res)
            #print(out_fused.size())
            return out_fused , res

        else:
            distilled_c1 = self.act(self.c1_d(input))
            r_c1 = self.c1_r(input)

            distilled_c2 = self.act(self.c2_d(r_c1))
            r_c2 = self.c2_r(r_c1)

            distilled_c3 = self.act(self.c3_d(r_c2))
            r_c3 = self.c3_r(r_c2)

            r_c4 = self.c4(r_c3)

            out = torch.cat((distilled_c1, distilled_c2, distilled_c3, r_c4), dim=1)
            out_fused = self.esa(self.c5(out))

            return out_fused

class DFDB_lite(nn.Module):
    def __init__(self, in_channels,deploy=True,dynamic=True,L=None,style='DBB',res=True):
        super(DFDB_lite, self).__init__()
        self.dc = self.distilled_channels = in_channels//2
        self.rc = self.remaining_channels = in_channels
        self.res = res

        if style == 'ResDBB':
            self.act = nn.LeakyReLU(0.05, True)
            self.c1_d = nn.Conv2d(in_channels, self.dc, 1, 1, 0, bias=True, dilation = 1, groups=1)
            self.c1_r = Unit(self.remaining_channels, self.rc, 7, groups=self.rc, deploy=deploy,dynamic=dynamic,L=L,style=style,res=res,nonlinear=self.act,n_channels=2*self.rc)
            self.c2_d = nn.Conv2d(in_channels, self.dc, 1, 1, 0, bias=True, dilation = 1, groups=1)
            self.c2_r = Unit(self.remaining_channels, self.rc, 5, groups=self.rc, deploy=deploy,dynamic=dynamic,L=L,style=style,res=res,nonlinear=self.act,n_channels=2*self.rc)
            self.c3_d = nn.Conv2d(in_channels, self.dc, 1, 1, 0, bias=True, dilation = 1, groups=1)
            self.c3_r = Unit(self.remaining_channels, self.rc, 3, groups=1, deploy=deploy,dynamic=dynamic,L=L,style=style,res=res,nonlinear=self.act,n_channels=2*self.rc)
            self.c4 = nn.Conv2d(self.remaining_channels, self.dc, 1, 1, 0, bias=True, dilation = 1, groups=1)
            self.c5 = nn.Conv2d(4*self.dc, in_channels, 1, 1, 0, bias=True, dilation = 1, groups=1)

        else:
            self.act = nn.LeakyReLU(0.05, True)
            self.c1_d = nn.Conv2d(in_channels, self.dc, 1, 1, 0, bias=True, dilation = 1, groups=1)
            self.c1_r = SeparableConv(self.remaining_channels, 7, deploy=deploy,dynamic=dynamic,L=L,style=style,res=res)
            self.c2_d = nn.Conv2d(in_channels, self.dc, 1, 1, 0, bias=True, dilation = 1, groups=1)
            self.c2_r = SeparableConv(self.remaining_channels, 5, deploy=deploy,dynamic=dynamic,L=L,style=style,res=res)
            self.c3_d = nn.Conv2d(in_channels, self.dc, 1, 1, 0, bias=True, dilation = 1, groups=1)
            self.c3_r = Unit(self.remaining_channels, self.rc, 3, deploy=deploy,dynamic=dynamic,L=L,style=style,res=res,nonlinear=self.act)
            self.c4 = nn.Conv2d(self.remaining_channels, self.dc, 1, 1, 0, bias=True, dilation = 1, groups=1)
            self.c5 = nn.Conv2d(4*self.dc, in_channels, 1, 1, 0, bias=True, dilation = 1, groups=1)

        if self.res:
            self.PAconv = nn.Conv2d(in_channels, in_channels, 1)
            self.conv1x1 = nn.Conv2d(4*in_channels, in_channels, 1, 1, 0, bias=True, dilation = 1, groups=1)
            #self.sconv = SeparableConv(in_channels,5,deploy,dynamic,L,same = True)
            self.sigmoid = nn.Sigmoid()

        self.esa = ESA(in_channels, nn.Conv2d)

    def forward(self, input):
        distilled_c1 = self.act(self.c1_d(input))
        r_c1,res1 = self.c1_r(input)

        distilled_c2 = self.act(self.c2_d(r_c1))
        r_c2,res2 = self.c2_r(r_c1)

        distilled_c3 = self.act(self.c3_d(r_c2))
        r_c3,res3 = self.c3_r(r_c2)

        r_c4 = self.c4(r_c3)

        out = torch.cat((distilled_c1, distilled_c2, distilled_c3, r_c4), dim=1)
        out_fused = self.c5(out)

        if self.res:
            scale = self.sigmoid(self.PAconv(out_fused))
            res = self.conv1x1(torch.cat((input, res1, res2, res3), dim=1))
            res = torch.mul(scale, res)

            out_fused = self.esa(out_fused + res)
            return out_fused , res

        else: return self.esa(out_fused)

def pixelshuffle_block(in_channels, out_channels, upscale_factor=2, kernel_size=3, stride=1):
    #pa = PA(in_channels)
    conv = nn.Conv2d(in_channels, out_channels* (upscale_factor ** 2), 3, 1, 1, bias=True)
    pixel_shuffle = nn.PixelShuffle(upscale_factor)

    return nn.Sequential(conv, pixel_shuffle)

def pixelshuffle_block_cpc(in_channels, out_channels, upscale_factor=2, kernel_size=3, stride=1):
    #pa = PA(in_channels)
    conv = nn.Conv2d(in_channels, out_channels* (upscale_factor ** 2), 3, 1, 1, bias=True)
    pixel_shuffle = nn.PixelShuffle(upscale_factor)
    #new add
    conv1 = nn.Conv2d(out_channels, out_channels, 3, 1, 1, bias=True)

    return nn.Sequential(conv, pixel_shuffle, conv1)

class DDistill_SR(nn.Module):
    def __init__(self, in_nc=3, out_nc=3, nf=50, num_modules=4, scale=4,lite=False, deploy=True,dynamic=True,L=None,style='DBB',res=True):
        super(DDistill_SR, self).__init__()

        self.scale = scale
        self.fea_conv = nn.Conv2d(3, nf, 3, 1, 1, bias=True)
        self.res = res

        if lite:
            self.B1 = DFDB_lite(nf,deploy,dynamic,L,style,res)
            self.B2 = DFDB_lite(nf,deploy,dynamic,L,style,res)
            self.B3 = DFDB_lite(nf,deploy,dynamic,L,style,res)
            self.B4 = DFDB_lite(nf,deploy,dynamic,L,style,res)
        else:
            self.B1 = DFDB(nf,deploy,dynamic,L,style,res)
            self.B2 = DFDB(nf,deploy,dynamic,L,style,res)
            self.B3 = DFDB(nf,deploy,dynamic,L,style,res)
            self.B4 = DFDB(nf,deploy,dynamic,L,style,res)

        if self.res:
            self.PAconv = nn.Conv2d(nf, nf, 1)
            self.sigmoid = nn.Sigmoid()
            self.cres = nn.Sequential(
                nn.Conv2d(num_modules*nf, nf, 1, 1, 0, bias=True),
                nn.LeakyReLU(negative_slope=0.1, inplace=True),
            )

        self.c =  nn.Sequential(
            nn.Conv2d(num_modules*nf, nf, 1, 1, 0, bias=True),
            nn.LeakyReLU(negative_slope=0.1, inplace=True),
        )

        self.LR_conv = Unit(nf, nf, 3, deploy=deploy,dynamic=dynamic,L=L,style=style)
        #self.LR_conv = nn.Conv2d(nf, nf, 3, 1, 1, bias=True)
        #self.esa = ESA(nf, nn.Conv2d)

        upsample_block = pixelshuffle_block_cpc
        #self.upsampler = upsample_block(nf, out_nc, self.scale)
        if self.scale == 2:
            self.upsamplerx2 = upsample_block(nf, out_nc, self.scale)
        elif self.scale ==3:
            self.upsamplerx3 = upsample_block(nf, out_nc, self.scale)
        else:
            self.upsamplerx4 = upsample_block(nf, out_nc, self.scale)
        #self.FConv = nn.Conv2d(out_nc, out_nc, 3, 1, 1, bias=True)

    def forward(self, input):
        out_fea = self.fea_conv(input)

        if self.res:
            out_B1, res1 = self.B1(out_fea)
            out_B2, res2 = self.B2(out_B1)
            out_B3, res3 = self.B3(out_B2)
            out_B4, res4 = self.B4(out_B3)

            out_res = self.cres(torch.cat([res1, res2, res3, res4], dim=1))

            out_B = self.c(torch.cat([out_B1, out_B2, out_B3, out_B4], dim=1))
            #out_B = self.esa(out_B)

            scale = self.sigmoid(self.PAconv(out_B))
            out_res = torch.mul(scale, out_res)

            out_lr = self.LR_conv(out_B + out_res) + out_fea

        else:
            out_B1 = self.B1(out_fea)
            out_B2 = self.B2(out_B1)
            out_B3 = self.B3(out_B2)
            out_B4 = self.B4(out_B3)

            out_B = self.c(torch.cat([out_B1, out_B2, out_B3, out_B4], dim=1))
            #out_B = self.esa(out_B)
            out_lr = self.LR_conv(out_B) + out_fea

        if self.scale == 2:
            output = self.upsamplerx2(out_lr)
        elif self.scale == 3:
            output = self.upsamplerx3(out_lr)
        else:
            output = self.upsamplerx4(out_lr)

        return output.clamp(0,1)

def model_convert(model:torch.nn.Module, save_path=None, do_copy=True):
    if do_copy:
        model = copy.deepcopy(model)
    for module in model.modules():
        if hasattr(module, 'switch_to_deploy'):
            module.switch_to_deploy()
    if save_path is not None:
        torch.save(model.state_dict(), save_path)
    return model

if __name__ == "__main__":

    model = DDistill_SR(in_nc=3, out_nc=3, nf = 56, num_modules=4, scale=4, deploy=False, dynamic=True, L = 16, style = 'DBB')
    model.load_state_dict(torch.load(r'model-backup/DDistillSRx4.pth'))

    from PIL import Image
    import torchvision.transforms as transforms

    model.eval()

    model_inference = model_convert(model)

    img = Image.open(r'Set5/LR_bicubic/X4/babyx4.png').convert('RGB')

    x = transforms.ToTensor()(img)
    x = x.unsqueeze(0)
    out1 = model(x)
    out2 = model_inference(x)
    #print(model)

    img1 = transforms.ToPILImage()(out1.squeeze(0))
    img1.show()
    img2 = transforms.ToPILImage()(out2.squeeze(0))
    img2.show()
    f = torch.nn.L1Loss()

    z = f(out1,out2)
    print(z)


n=int(input())
s=input().rstrip().split(' ')
l=[int(i) for i in s]
t=int(input())
l.sort()
r=1000
for i in range(len(l)):
    if l.count(l[i])==t and r>l[i]:
        r=l[i]
print(r)


"""
Attach columns needed for publishing to open data portal.
Suppress certain rows and columns too.
"""
import datetime
import geopandas as gpd
import pandas as pd

from shared_utils import schedule_rt_utils, utils
from calitp_data_analysis import utils, geography_utils
from segment_speed_utils import helpers
from segment_speed_utils.project_vars import SEGMENT_GCS, CONFIG_PATH

def get_operator_natural_identifiers(
    df: pd.DataFrame,
    analysis_date: str
) -> pd.DataFrame:
    """
    For each gtfs_dataset_key-shape_array_key combination,
    re-attach the natural identifiers and organizational identifiers.
    Return a df that should be merged against speeds_df.
    """
    operator_shape_df = (df[["schedule_gtfs_dataset_key", "shape_array_key"]]
                         .drop_duplicates()
                         .reset_index(drop=True)
                         .rename(columns = {
                             "schedule_gtfs_dataset_key": "gtfs_dataset_key"})
                        )

    # Get shape_id back
    shape_identifiers = helpers.import_scheduled_trips(
        analysis_date,
        columns = ["shape_array_key", "shape_id"],
        get_pandas = True
    )

    df_with_shape = pd.merge(
        operator_shape_df,
        shape_identifiers,
        on = "shape_array_key",
        how = "inner"
    )

    # Get base64_url, uri, organization_source_record_id and organization_name
    crosswalk = schedule_rt_utils.sample_gtfs_dataset_key_to_organization_crosswalk(
        df_with_shape,
        analysis_date,
        quartet_data = "schedule",
        dim_gtfs_dataset_cols = [
            "key",
            "base64_url",
        ],
        dim_organization_cols = ["source_record_id", "name"]
    )

    df_with_org = pd.merge(
        df_with_shape.rename(
            columns = {"gtfs_dataset_key": "schedule_gtfs_dataset_key"}),
        crosswalk,
        on = "schedule_gtfs_dataset_key",
        how = "inner"
    )

    return df_with_org

def finalize_df_for_export(gdf: gpd.GeoDataFrame) -> gpd.GeoDataFrame:
    """
    Sorting, suppressing columns not needed in export.
    """

    RENAME_DICT = {
        "organization_source_record_id": "org_id",
        "organization_name": "agency",
    }

    gdf2 = (gdf.sort_values(["organization_name",
                         "shape_id", "stop_sequence"])
           .reset_index(drop=True)
           .rename(columns = RENAME_DICT)
          )

    return gdf2

def export_average_speeds(
    analysis_date: str,
    dict_inputs: dict
):
    start = datetime.datetime.now()
    INPUT_FILE = f'{dict_inputs["stage5"]}_{analysis_date}'

    gdf = gpd.read_parquet(
        f"{SEGMENT_GCS}{INPUT_FILE}.parquet"
    )

    operator_identifiers = get_operator_natural_identifiers(gdf, analysis_date)

    time1 = datetime.datetime.now()
    print(f"get natural identifiers: {time1 - start}")

    gdf2 = pd.merge(
        gdf,
        operator_identifiers,
        on = ["schedule_gtfs_dataset_key", "shape_array_key"],
        how = "inner"
    )

    final_gdf = finalize_df_for_export(gdf2)

    time2 = datetime.datetime.now()
    print(f"finalize: {time2 - time1}")

    keep_cols = [
        'org_id', 'agency',
        'shape_id', 'stop_sequence', 'stop_id',
        'geometry',
        'p50_mph', 'p20_mph',
        'p80_mph', 'n_trips',
        'time_of_day',
        'base64_url',
        'district_name'
    ]

    utils.geoparquet_gcs_export(
        final_gdf[keep_cols],
        f"{SEGMENT_GCS}export/",
        INPUT_FILE
    )

    # Keep a tabular version (geom is big to save) for us to compare what's published
    # and contains columns we use for internal modeling
    # (shape_array_key, gtfs_dataset_key, etc)
    final_gdf.drop(columns = "geometry").to_parquet(
        f"{SEGMENT_GCS}export/{INPUT_FILE}_tabular.parquet"
    )

    utils.geoparquet_gcs_export(
        final_gdf[keep_cols],
        f"{SEGMENT_GCS}export/",
        "speeds_by_stop_segments"
    )

    end = datetime.datetime.now()
    print(f"execution time: {end - start}")

    return

def average_route_speeds_for_export(
    analysis_date: str,
    dict_inputs: dict
) -> gpd.GeoDataFrame:
    """
    Aggregate trip speeds to route-direction.
    Attach shape geometry to most common shape_id.
    """
    SPEEDS_FILE = f'{dict_inputs["stage6"]}_{analysis_date}'
    EXPORT_FILE = f'{dict_inputs["stage7"]}_{analysis_date}'
    MAX_SPEED = dict_inputs["max_speed"]

    df = pd.read_parquet(
        f"{SEGMENT_GCS}trip_summary/{SPEEDS_FILE}.parquet",
        filters = [[("speed_mph", "<=", MAX_SPEED)]]
    )

    # Aggregate by route-direction
    route_cols = [
        "schedule_gtfs_dataset_key", "time_of_day",
        "route_id", "direction_id",
        "route_name_used",
        "common_shape_id", "shape_array_key"
    ]

    df2 = (df.groupby(route_cols,
                      observed = True, group_keys = False)
           .agg({
               "service_minutes": "mean",
               "rt_trip_min": "mean",
               "speed_mph": "mean",
               "trip_instance_key": "count"
           }).reset_index()
          )

    df3 = df2.assign(
        rt_trip_min = df2.rt_trip_min.round(1),
        service_minutes = df2.service_minutes.round(1),
        speed_mph = df2.speed_mph.round(1)
    ).rename(columns = {
        "service_minutes": "avg_sched_trip_min",
        "rt_trip_min": "avg_rt_trip_min",
        "trip_instance_key": "n_trips",
        "route_name_used": "route_name",
        "schedule_gtfs_dataset_key": "gtfs_dataset_key"
    })

    # Attach org name and source_record_id
    org_crosswalk = (
        schedule_rt_utils.sample_gtfs_dataset_key_to_organization_crosswalk(
            df3,
            analysis_date,
            quartet_data = "schedule",
            dim_gtfs_dataset_cols = ["key", "base64_url"],
            dim_organization_cols = ["source_record_id",
                                     "name", "caltrans_district"])
    )

    df_with_org = pd.merge(
        df3,
        org_crosswalk.rename(columns = {
            "schedule_gtfs_dataset_key": "gtfs_dataset_key"}),
        on = "gtfs_dataset_key",
        how = "inner"
    )

    # Attach shape geometry and make sure it's in WGS84
    shapes = helpers.import_scheduled_shapes(
        analysis_date,
        columns = ["shape_array_key", "geometry"],
        get_pandas = True,
        crs = geography_utils.WGS84
    )

    df_with_shape = pd.merge(
        shapes,
        df_with_org,
        on = "shape_array_key", # once merged, can drop shape_array_key
        how = "inner"
    )

    agency_cols = ['organization_source_record_id', 'organization_name']
    route_cols = ['route_id', 'route_name',
                  'direction_id', 'common_shape_id']

    col_order = agency_cols + route_cols + [
        'time_of_day',
        'speed_mph', 'n_trips',
        'avg_sched_trip_min', 'avg_rt_trip_min',
        'base64_url', 'caltrans_district',
        'geometry'
    ]

    final_df = df_with_shape.reindex(columns = col_order).rename(
        columns = {"organization_source_record_id": "org_id",
                   "organization_name": "agency",
                   "caltrans_district": "district_name"
                  })

    utils.geoparquet_gcs_export(
        final_df,
        f"{SEGMENT_GCS}trip_summary/",
        EXPORT_FILE
    )

    utils.geoparquet_gcs_export(
        final_df,
        f"{SEGMENT_GCS}export/",
        "speeds_by_route_time_of_day"
    )

    return

if __name__ == "__main__":

    from segment_speed_utils.project_vars import analysis_date_list

    STOP_SEG_DICT = helpers.get_parameters(CONFIG_PATH, "stop_segments")

    for analysis_date in analysis_date_list:
        export_average_speeds(analysis_date, STOP_SEG_DICT)
        average_route_speeds_for_export(analysis_date, STOP_SEG_DICT)


"""Utilities and an example of how to make an animated plot to export as a movie."""
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation

import arpes.config
import xarray as xr
from arpes.plotting.utils import path_for_plot
from arpes.provenance import save_plot_provenance

__all__ = ("plot_movie",)

@save_plot_provenance
def plot_movie(data: xr.DataArray, time_dim, interval=None, fig=None, ax=None, out=None, **kwargs):
    """Make an animated plot of a 3D dataset using one dimension as "time"."""
    if not isinstance(data, xr.DataArray):
        raise TypeError("You must provide a DataArray")

    if ax is None:
        fig, ax = plt.subplots(figsize=(7, 7))

    cmap = arpes.config.SETTINGS.get("interactive", {}).get("palette", "viridis")
    vmax = data.max().item()
    vmin = data.min().item()

    if data.S.is_subtracted:
        cmap = "RdBu"
        vmax = np.max([np.abs(vmin), np.abs(vmax)])
        vmin = -vmax

    if "vmax" in kwargs:
        vmax = kwargs.pop("vmax")
    if "vmin" in kwargs:
        vmin = kwargs.pop("vmin")

    plot = data.mean(time_dim).transpose().plot(vmax=vmax, vmin=vmin, cmap=cmap, **kwargs)

    def init():
        plot.set_array(np.asarray([]))
        return (plot,)

    animation_coords = data.coords[time_dim].values

    def animate(i):
        coordinate = animation_coords[i]
        data_for_plot = data.sel(**dict([[time_dim, coordinate]]))
        plot.set_array(data_for_plot.values.G.ravel())
        return (plot,)

    if interval:
        computed_interval = interval
    else:
        computed_interval = 100

    anim = animation.FuncAnimation(
        fig,
        animate,
        init_func=init,
        repeat=500,
        frames=len(animation_coords),
        interval=computed_interval,
        blit=True,
    )

    Writer = animation.writers["ffmpeg"]
    writer = Writer(fps=1000 / computed_interval, metadata=dict(artist="Me"), bitrate=1800)

    if out is not None:
        anim.save(path_for_plot(out), writer=writer)
        return path_for_plot(out)

    # plt.show()
    return anim


from torchvision.models import vgg19, alexnet, resnet50
from tqdm import tqdm

from train_DEns import *
from model import *
from twoAFC import Pretrained_network

def Get_Features(img, net_name=resnet50, layer_num=-1):
    device = img.device
    Extractor = Pretrained_network(net_name, layer_num)
    Extractor = nn.DataParallel(Extractor)
    Extractor.to(device)
    Extractor.eval()
    features = Extractor(img / 2 + 0.5)
    return features

def Get_Feature_DEns(labels, DEns_member_index, net_name=resnet50, layer_num=-1):  # (B, 4, H, W)
    device = labels.device
    netG = UNet(in_channels=4, n_classes=3, depth=5, wf=6, padding=True, batch_norm=True, up_mode='upsample')
    netG = nn.DataParallel(netG)
    netG.to(device)

    resnet = Pretrained_network(net_name, layer_num)
    resnet = nn.DataParallel(resnet)
    resnet.to(device)

    Synth_he_list = []
    for i in DEns_member_index:
        netG.load_state_dict(torch.load(f'outputs/SRS DEns/Ensemble No. {i}/e68 (#30000)/netG W&B'))
        netG.eval()
        Synth_he_list += [netG(labels).detach()]
    Synth_he = torch.stack(Synth_he_list, dim=0)
    N, B, _, H, W = Synth_he.shape

    resnet.eval()
    Synth_he2 = Synth_he.reshape((N*B, 3, H, W))
    features = resnet(Synth_he2/2 + 0.5)
    _, f_channel, f_size, _ = features.shape
    features = features.reshape((N, B, f_channel, f_size, f_size))

    f_median = torch.median(features, dim=0, keepdim=True)[0]
    f_MAD = (torch.median(torch.abs(features - f_median), dim=0)[0] * 1.4826) ** 2 # (B, f_channel, f_size, f_size)
    pu_map = f_MAD.mean(1).unsqueeze(1)  # (B, 1, f_size, f_size)

    return  Synth_he, pu_map, features

def main(file_path="Datasets/SRS/data from same section/test/",
         net_name=resnet50, layer_num=-1
         ):

    os.makedirs(file_path + 'PU', exist_ok=True)
    os.makedirs(file_path + 'Raw Features', exist_ok=True)
    os.makedirs(file_path + 'Raw Features (Ground truth)', exist_ok=True)

    lr_transforms = transforms.Compose([transforms.ToTensor(),])
    hr_transforms = transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((.5, 0.5, 0.5), (0.5, 0.5, 0.5))
    ])

    filesI =  file_path + 'SRS'
    list_I = os.listdir(filesI)

    for I in tqdm(list_I):
        im = sio.loadmat(filesI + '/' + I)
        img = im['ss']
        img[img > 5] = 5
        img[img < 0] = 0
        img = (img - 2.5) / 2.5
        img = lr_transforms(img)
        labels = img[1:,:,:].float().to('cuda')
        _, uq, features = Get_Feature_DEns(labels.unsqueeze(0), list(range(1, 51)), net_name, layer_num)
        torch.save(uq[0, :], file_path + f"PU/{I[:-4]}.pt")
        torch.save(features[:,0,:,:,:], file_path + f"Raw Features/{I[:-4]}.pt")

        he = sio.loadmat(file_path + 'HE' + '/' + I)
        he = he['xx']
        he = hr_transforms(he)
        he[he>1]=1
        he[he<-1]=-1
        he = he.unsqueeze(0).float().to('cuda')
        gt_features = Get_Features(he, net_name, layer_num)
        torch.save(gt_features[0, :], file_path + f"Raw Features (Ground truth)/{I[:-4]}.pt")

        sys.exit()

if __name__ == '__main__':
    main()


#!/usr/bin/python3

"""
Copyright (c) 2016 King Mongkut's University technology Thonburi
Author: Nattawet Sriwichai
Contact: nattawet.sri@mail.kmutt.ac.th
Version: 1.0
License: MIT License

The MIT License

Copyright (c) 2016 King Mongkut's University technology Thonburi

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""

import os
import sys
from optparse import OptionParser

if "--version" in sys.argv[1:]:
	# TODO - Capture version of Select_representative_miRNA
	print("memeXml2bed version 1.0")
	sys.exit(0)

# Parse Command Line
usage = """

Description:
This script designed for convert MEME output to BED.

usage:
$ python3 memeXml2bed.py \\
	--output <out.bed> \\
	--input <meme.xml> \\
	--pvalue <1e-2> \\
"""

parser = OptionParser(usage=usage)
parser.add_option("-o", "--output", dest="file_output",
	default='meme.bed', metavar="FILE",
	help="Output file name of BED, default is meme.out")
parser.add_option("-i", "--input", dest="file_xml",
	default='meme.xml', metavar="FILE",
	help="Input XML file from MEME, default is meme.xml")
parser.add_option("-p", "--pvalue", dest="pvalue",
	default=1e-2, metavar="FILE",
	help="Cut off motif scan p-value that less than, default is 1e-2")

options,args = parser.parse_args()
file_output = options.file_output
file_xml = options.file_xml
pvalue = float(options.pvalue)

if not options.file_output:
	sys.exit("Missing output BED file, -o <FILE> or --output=<FILE>")
if not options.file_xml or not os.path.exists(options.file_xml):
	sys.exit("Missing input XML file from MEME, -i <FILE> or --input=<FILE>")

import xml.etree.ElementTree as ET
tree = ET.parse(file_xml)
root = tree.getroot()

# append input sequence into dict
sequence = {}
for i in range(1, len(root[0])-1):
	sequence[root[0][i].attrib['id']] = root[0][i].attrib

# read command line
command_line = root[1][0].text

# append motif information into dict
motif = {}
for i in range(0, len(root[2])):
	motif[root[2][i].attrib['id']] = root[2][i].attrib

# append motif_sites into dict
motif_sites = {}
for i in range(0, len(root[3])):
	motif_sites_in_sequence = []
	for j in range(len(root[3][i])):
		motif_sites_in_sequence.append(root[3][i][j].attrib)
	sequence[root[3][i].attrib['sequence_id']]['motif_sites'] = motif_sites_in_sequence

# print motif location

file_out = open(file_output, 'w')

for i in sequence:
	name = sequence[i]['name']
	name = name.split('|')[0]
	sequence_length = int(sequence[i]['length'])

	file_out.write(name + '\t' + str(sequence_length) + '\t' + str(sequence_length+10)  + '\t' + 'CDS\n')
	# print(name, sequence_length, sequence_length+10, 'CDS', sep='\t')
	for j in range(len(sequence[i]['motif_sites'])):
		motif_id = sequence[i]['motif_sites'][j]['motif_id']
		motif_position = sequence[i]['motif_sites'][j]['position']
		motif_pvalue = float(sequence[i]['motif_sites'][j]['pvalue'])
		motif_length = motif[motif_id]['width']
		if motif_pvalue < pvalue:
			file_out.write(name + '\t' + str(int(motif_position) + 1) + '\t' + str(int(motif_position) + int(motif_length)) + '\t' + motif_id + '\n')
			# print(name, int(motif_position) + 1, int(motif_position) + int(motif_length), motif_id, sep='\t')


import numpy as np

from source.ch_03.activation_functions import sigmoid
from source.ch_03.activation_functions import softmax
from source.ch_04.loss_function import cross_entropy_error
from source.ch_04.numerical_diff import numerical_gradient

class TwoLayerNet:
    def __init__(self, input_size, hidden_size, output_size, weight_init_std=0.01):
        # W initialize
        self.params = {}
        self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size)
        self.params['b1'] = np.zeros(hidden_size)
        self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size)
        self.params['b2'] = np.zeros(output_size)

    def predict(self, x):
        W1, W2 = self.params['W1'], self.params['W2']
        b1, b2 = self.params['b1'], self.params['b2']

        a1 = np.dot(x, W1) + b1
        z1 = sigmoid(a1)
        a2 = np.dot(z1, W2) + b2
        y = softmax(a2)

        return y

    def loss(self, x, t):
        y = self.predict(x)
        return cross_entropy_error(y, t)

    def accuracy(self, x, t):
        y = self.predict(x)
        y = np.argmax(y, axis=1)
        t = np.argmax(t, axis=1)

        accuracy = np.sum(y == t) / float(x.shape[0])

    def numerical_gradient(self, x, t):
        loss_W = lambda W: self.loss(x, t)

        grads = {}
        grads["b1"] = numerical_gradient(loss_W, self.params["b1"])
        grads["W2"] = numerical_gradient(loss_W, self.params["W2"])
        grads["W1"] = numerical_gradient(loss_W, self.params["W1"])
        grads["b2"] = numerical_gradient(loss_W, self.params["b2"])

        return grads


'''
노션에서 붙여넣은 마크다운 파일 바꾸는 프로그램

'''

import os.path
import os
import re

# 수정
MD_FILE_PATH = './2023-10-10.md'
NOTE_FILE_PATH = 'note'

os.chdir(NOTE_FILE_PATH)
files = os.getcwd()
print('현재 경로:',files)
print('바꿀 파일:', MD_FILE_PATH)
enter = input('현재 경로가 맞으면 y를 입력하세요: ')
if enter == "y" or enter == 'Y':

    # image.png -> image-0.png
    if 'image.png' in os.listdir(files):
        os.rename('image.png', 'image-0.png')

    # 하위로 이동해서 시작번호 알아오기
    os.chdir('note_image')
    note_image_dir = os.getcwd()
    image_files = sorted(os.listdir(note_image_dir))
    start = int((image_files[-1].replace('.png', '')).split('-')[1]) + 1

    # 위로 이동해서 바꾸기
    # 이미지 파일만 모으기
    made_images = [x for x in os.listdir(files) if '.png' in x]
    os.chdir('..')
    # print(made_images)
    for i, x in enumerate(made_images):
        os.rename(f"./{x}", f"./note_image/image-{start+i}.png")

    # # 마크다운 파일 변경
    p = re.compile('image.*[.]png')
    notp = re.compile('[/]image.*[.]png')
    new_file = ''
    # print(start)
    # start = 6
    with open(MD_FILE_PATH, 'r', encoding='utf-8') as f:
        lines  = f.readlines()
        i = 0
        for l in lines:
            m = p.search(l)
            mp = notp.search(l)
            if not mp and m:
                print(f"\t{m.group()}이 note_image/image-{start+i}.png로 변경되었습니다.")
                tmp = l.replace(m.group(), f"note_image/image-{start+i}.png")
                new_file += tmp
                i += 1
            else:
                new_file += l

    with open(MD_FILE_PATH, 'w', encoding='utf-8') as f:
        f.write(new_file)
    print('정상적으로 완료되었습니다.')
else:
    print('종료되었습니다.')


"""Utilities for working with CloudFormation stacks."""
import uuid

import botocore.client
import botocore.exceptions
import click

from . import Deployment, boto3_session
from .s3 import empty_bucket

__all__ = ("artifacts_bucket", "artifact_builder_state_machine", "deploy_stack", "destroy_stack", "update_stack")

def update_stack(*, region: str, stack_name: str, template: str, allow_iam: bool = False, **parameters: str):
    """Update an existing CloudFormation stack in a thread-friendly way.

    :param str region: AWS region to target
    :param str stack_name: Stack name
    :param str template: Stack template body
    :param bool allow_iam: Should this stack be allowed to create IAM resources?
    :param parameters: Stack parameters
    """
    session = boto3_session(region=region)
    cfn_client = session.client("cloudformation")

    kwargs = dict(StackName=stack_name, TemplateBody=template)

    if allow_iam:
        kwargs["Capabilities"] = ["CAPABILITY_IAM"]

    if parameters:
        kwargs["Parameters"] = [dict(ParameterKey=key, ParameterValue=value) for key, value in parameters.items()]

    try:
        cfn_client.update_stack(**kwargs)
    except botocore.exceptions.ClientError as error:
        try:
            message = error.response["Error"]["Message"]
        except KeyError:
            raise error

        if message == "No updates are to be performed.":
            click.echo(f"Stack {stack_name} in {region} is already up to date.")
            return

        raise

    created_waiter = cfn_client.get_waiter("stack_update_complete")
    created_waiter.wait(StackName=stack_name, WaiterConfig=dict(MaxAttempts=50))

def deploy_stack(*, region: str, template: str, allow_iam: bool = False, **parameters: str) -> str:
    """Deploy a new CloudFormation stack in a thread-friendly way.

    :param str region: AWS region to target
    :param str template: Stack template body
    :param bool allow_iam: Should this stack be allowed to create IAM resources?
    :param parameters: Stack parameters
    :return: Name of deployed stack
    :rtype: str
    """
    stack_name = f"Accretion-{uuid.uuid4()}"
    session = boto3_session(region=region)
    cfn_client = session.client("cloudformation")

    kwargs = dict(StackName=stack_name, TemplateBody=template)

    if allow_iam:
        kwargs["Capabilities"] = ["CAPABILITY_IAM"]

    if parameters:
        kwargs["Parameters"] = [dict(ParameterKey=key, ParameterValue=value) for key, value in parameters.items()]

    cfn_client.create_stack(**kwargs)

    created_waiter = cfn_client.get_waiter("stack_create_complete")
    created_waiter.wait(StackName=stack_name, WaiterConfig=dict(MaxAttempts=50))

    return stack_name

def _all_buckets(*, client: botocore.client.BaseClient, stack: str):
    """"""
    complete = False
    next_token = None
    click.echo(f"Looking for buckets in stack {stack}")
    while not complete:
        kwargs = dict(StackName=stack)
        if next_token is not None:
            kwargs["NextToken"] = next_token

        response = client.list_stack_resources(**kwargs)

        try:
            next_token = response["NextToken"]
        except KeyError:
            complete = True

        for resource in response["StackResourceSummaries"]:
            if resource["ResourceType"] == "AWS::S3::Bucket":
                bucket = resource["PhysicalResourceId"]
                click.echo(f"Found bucket {bucket}")
                yield bucket

def destroy_stack(*, region: str, stack_name: str):
    """Destroy the specified stack in the specified region.

    :param str region: AWS region containing stack
    :param str stack_name: Stack name
    """
    session = boto3_session(region=region)
    cfn_client = session.client("cloudformation")

    for bucket in _all_buckets(client=cfn_client, stack=stack_name):
        empty_bucket(region=region, bucket=bucket)

    cfn_client.delete_stack(StackName=stack_name)

    stack_destroyed = cfn_client.get_waiter("stack_delete_complete")
    stack_destroyed.wait(StackName=stack_name, WaiterConfig=dict(MaxAttempts=50))

def _resource_physical_id(*, region: str, stack_name: str, logical_resource_id: str) -> str:
    """"""
    session = boto3_session(region=region)
    cfn_client = session.client("cloudformation")

    response = cfn_client.describe_stack_resource(StackName=stack_name, LogicalResourceId=logical_resource_id)

    return response["StackResourceDetail"]["PhysicalResourceId"]

def artifacts_bucket(*, region: str, regional_record: Deployment) -> str:
    """"""
    return _resource_physical_id(region=region, stack_name=regional_record.Core, logical_resource_id="SourceBucket")

def artifact_builder_state_machine(*, region: str, regional_record: Deployment) -> str:
    """"""
    return _resource_physical_id(
        region=region, stack_name=regional_record.ArtifactBuilder, logical_resource_id="ArtifactBuilderStateMachine"
    )


def solve(text):
    return []

def solve_verbose(text):
    words = text.strip().split('\n')
    words = list(filter(lambda line: len(line) > 0, words))
    min_len = max(map(lambda w: len(w),words))
    ret = []
    for i in range(1,min_len):
        ret.append(''.join(map(lambda w: w[i % len(w)], words)))
    return ret


import numpy as np
import pandas as pd
import itertools
import math
from scipy.stats import mvn
from scipy.stats import multivariate_normal
import quadpy

def create_box_thresholds(num_features, node_count, features, thresholds):
    # Create an empty list of lists to save the decision boundaries for each feature
    BOX = [[] for i in range(num_features)]

    # Get the decision boundaries for each feature
    for i in range(node_count):
        for j in range(num_features):
            if features[i] == j:
                BOX[j].append(thresholds[i])

    # Sort the decision boundaries in ascending order for each feature
    for i in range(num_features):
        BOX[i].sort()

    # Expand the surface by 200 in each direction to cover almost all the probability surface
    for i in range(num_features):
        if BOX[i] != []:
            BOX[i].insert(0,-1000000)
            BOX[i].append(1000000)
        else:
            BOX[i].insert(0,-1000000)
            BOX[i].append(1000000)

    return BOX

def boxes_with_labels(num_features, BOX):
    # Number of upper and lower thresholds for the boxes
    box_thresholds = []
    for i in range(num_features):
        box_thresholds.append('B'+str(i+1))
        box_thresholds.append('T'+str(i+1))

    # Number of boxes the classifier has
    num_boxes = 1
    for i in range(len(BOX)):
        num_boxes *= (len(BOX[i])-1)

    index = np.arange(0,num_boxes,1)

    # Create an empty dataframe for all the decision areas; we call them boxes, stemming from 2D examples
    boxes = pd.DataFrame(columns=box_thresholds, index=index)

    # Create all boxes
    T = []

    for i in range(len(BOX)):
        T.append([])

    for i in range(len(BOX)):
        for j in range(len(BOX[i])-1):
            T[i].append([BOX[i][j],BOX[i][j+1]])

    Z = list(itertools.product(*T))

    Help = []

    for j in range(len(boxes)):
        join = []
        for i in range(len(BOX)):
            join += Z[j][i]
        Help.append(join)

    boxes = pd.DataFrame(Help, columns=box_thresholds)

    return boxes

def input_features(test_coordinates, num_features):
    while len(test_coordinates) < num_features:
        try:
            input_features = float(input('Feature values: '))
            test_coordinates.append(input_features)
        except ValueError:
            print('Enter a number.')

    return test_coordinates

def create_covariance_matrix(num_features):
    A = np.random.rand(num_features, num_features)
    cov = np.dot(A, A.transpose())

    return cov

def calculate_robustness(coord, covariance_matrix, boxes):
    Tops = list(boxes.columns[1::2])
    Bottoms = list(boxes.columns[0::2])[:-1]
    Tops = boxes[Tops]
    Bottoms = boxes[Bottoms]

    rob_fast = 0

    for i in range(boxes.shape[0]):
        low = Bottoms.iloc[i]
        upp = Tops.iloc[i]

        p_box,i_box = mvn.mvnun(low,upp,coord,covariance_matrix)
        rob_fast += p_box

    return rob_fast

def calculate_numerical_robustness(coord, covariance_matrix, boxes, dim):
    val_all = []
    scheme = quadpy.cn.stroud_cn_5_4(dim)

    for i in range(boxes.shape[0]):
        values = boxes.iloc[i][:dim*2]
        my_list = []

        for j in range(0, 2*dim, 2):
            my_list.append(values[j:j+2])
        my_list = tuple(my_list)

        val = scheme.integrate(
            lambda x: multivariate_normal(coord,covariance_matrix).pdf(x.T),
            quadpy.cn.ncube_points(
                *my_list
            ),
        )
        val_all.append(val)

    # Eliminate NaNs
    rob = [item for item in val_all if not(math.isnan(item)) == True]
    res = sum(rob)

    return res


import numpy as np
from PIL import Image
import matplotlib.pyplot as plt

#Step I:The function that returns a 2D Gaussian matrix
def GuassianBlurring(sigma):
    k = int(3 * sigma)
    matrix_size = 2 * k + 1
    keneral = np.zeros((matrix_size, matrix_size))
    for i in range(matrix_size):
        for j in range(matrix_size):
            temp_x = i - k
            temp_y = j - k
            keneral[i][j] = (1 / 2 * np.pi * (sigma ** 2)) * np.exp(-(temp_x ** 2 + temp_y ** 2)/ (2 *sigma **2))

    return keneral

#Step2: The function that return the gradient magnitude of the image
def GradientMagnitude(image):
    sobelX = np.array(([-1, 0, 1], [-2, 0, 2], [-1, 0, 1]))
    sobelY = np.array(([-1, -2, -1], [0, 0, 0], [1, 2, 1]))

    gradientX = np.zeros((image.shape)) #the gradients of image along X-axis
    gradientY = np.zeros((image.shape)) #the gradients of image along y-axis

    #find the gradient for every G(x, y)
    for x in range(image.shape[0] - 2):
        for y in range(image.shape[1] - 2):
            tempMatrix = image[x:x+3, y:y+3]
            gradientX[x][y] = np.sum(np.multiply(sobelX, tempMatrix))
            gradientY[x][y] = np.sum(np.multiply(sobelY, tempMatrix))

    gradientFinal = np.sqrt(gradientY ** 2 + gradientX ** 2)
    return gradientFinal

#Step3: Implement threshold algorithm to find the edge.
def ThresholdAlgorithm(gradientImage):
    #1: initialized tau
    tauOrignal = np.sum(gradientImage) / (gradientImage.shape[0] * gradientImage.shape[1])
    epsilon = 0

    tauTemp = UpdateTau(gradientImage, tauOrignal) #find tau_i then compare.
    while abs(tauTemp - tauOrignal) > epsilon: #iteration for 2-4
        tauOrignal = tauTemp
        tauTemp = UpdateTau(gradientImage, tauOrignal)

    #5, assign value to the edge-mapped image
    edgeImage = np.zeros((gradientImage.shape))
    for x in range(gradientImage.shape[0]):
        for y in range(gradientImage.shape[1]):
            if gradientImage[x][y] >= tauOrignal:
                edgeImage[x][y] = 255
            else:
                edgeImage[x][y] = 0
    return edgeImage

#a helper function to take an image and a gaussian matrix to flur the image
def FlurImage(image, keneral):
    flurImage = np.zeros((image.shape[0] - keneral.shape[0] + 1, image.shape[1]-keneral.shape[0] + 1))

    for x in range(image.shape[0] - keneral.shape[0] + 1):
        for y in range(image.shape[1] - keneral.shape[0] + 1):
            tempMatrix = image[x:x+keneral.shape[0], y:y+keneral.shape[0]]
            flurImage[x][y] = np.sum(np.multiply(keneral, tempMatrix))
    return flurImage

#a helper function to update the latest tau in the ThresholdAlgorithm
def UpdateTau(gradientImage, tauOrignal):
    lower = []
    upper = []
    for x in range(gradientImage.shape[0]):
        for y in range(gradientImage.shape[1]):
            if gradientImage[x][y] < tauOrignal:
                lower.append(gradientImage[x][y])
            else:
                upper.append(gradientImage[x][y])
    mL = sum(lower) / len(lower)
    mH = sum(upper) / len(upper)
    tauTemp = (mL + mH) / 2
    return tauTemp

if __name__ == '__main__':
    #visualize for step 1:
    #for sigma = 1:
    Blur1 = GuassianBlurring(1)
    plt.imshow(Blur1)
    #for sigma = 3:
    Blur2 = GuassianBlurring(3)
    plt.imshow(Blur2)

    #Step4: test
    #test for image 1
    image1 = np.asarray(Image.open('./Q4_image_1.jpg').convert('RGB'))
    #convert the image into grayscle
    gray_image1 = 0.2125 * image1[:, :, 0] + 0.7154 * image1[:, :, 1] + 0.0721 * image1[:, :, 2]
    plt.imshow(gray_image1, cmap='gray')
    plt.show()
    #find the blurred image
    blurImage1 = FlurImage(gray_image1, GuassianBlurring(3))
    plt.imshow(blurImage1, cmap='gray')
    plt.show()
    #find the Gradient image
    gradientImage1 = GradientMagnitude(blurImage1)
    plt.imshow(gradientImage1, cmap='gray')
    plt.show()
    #find the edge image
    edge_image1 = ThresholdAlgorithm(gradientImage1)
    plt.imshow(edge_image1, cmap='gray')
    plt.show()

    #test for image 2
    image2 = np.asarray(Image.open('./Q4_image_2.jpg').convert('RGB'))
    #convert the image into grayscle
    grayImage2 = 0.2125 * image2[:, :, 0] + 0.7154 * image2[:, :, 1] + 0.0721 * image2[:, :, 2]
    plt.imshow(grayImage2, cmap='gray')
    plt.show()
    #find the blurred image
    blurImage2 = FlurImage(grayImage2, GuassianBlurring(3))
    plt.imshow(blurImage2, cmap='gray')
    plt.show()
    #find the Gradient image
    gradientImage2 = GradientMagnitude(blurImage2)
    plt.imshow(gradientImage2, cmap='gray')
    plt.show()
    #find the edge image
    edge_image2 = ThresholdAlgorithm(gradientImage2)
    plt.imshow(edge_image2, cmap='gray')
    plt.show()

    #test for my own image
    image3 = np.asarray(Image.open('./Q4_image_3.jpg').convert('RGB'))
    #convert the image into grayscle
    grayImage3 = 0.2125 * image3[:, :, 0] + 0.7154 * image3[:, :, 1] + 0.0721 * image3[:, :, 2]
    plt.imshow(grayImage3, cmap='gray')
    plt.show()
    #find the blurred image
    blurImage3 = FlurImage(grayImage3, GuassianBlurring(3))
    plt.imshow(blurImage3, cmap='gray')
    plt.show()
    #find the Gradient image
    gradientImage3 = GradientMagnitude(blurImage3)
    plt.imshow(gradientImage3, cmap='gray')
    plt.show()
    #find the edge image
    edge_image3 = ThresholdAlgorithm(gradientImage3)
    plt.imshow(edge_image3, cmap='gray')
    plt.show()


from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QLabel, QLineEdit, QVBoxLayout, QWidget
from PySide6.QtGui import QAction
from PySide6.QtCore import QSize
import sys

class WindowPySide(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('OOP with PySide')
        self.setFixedSize(400,200)

        # Widget

        # Events
        self.event_button = QPushButton('Click me')

        # Signals and Slots
        # Slot
        self.event_button.setCheckable(True)
        # Event Slot
        self.event_button.clicked.connect(self._check)
        # Events
        self.event_button.clicked.connect(self._click_event)

        # Connecting the change on title
        self.windowTitleChanged.connect(self._change_title_window)

        # Connecting elements
        self.label = QLabel()
        self.entry_text = QLineEdit()

        # signal(slot)
        self.entry_text.textChanged.connect(self.label.setText)

        # Publishing layout
        layout = QVBoxLayout()
        layout.addWidget(self.entry_text)
        layout.addWidget(self.label)
        layout.addWidget(self.event_button)

        container = QWidget()
        container.setLayout(layout)

        self.setCentralWidget(container)

    # Slots and Signals
    def _click_event(self):
        print('Button clicked')
        print('Checked button: ', self.checked_button)

        self.event_button.setText('New Text Button')
        self.event_button.setEnabled(False)
        self.setWindowTitle('New Title')

    def _check(self, check):
        self.checked_button = check
        print('Checked?', self.checked_button)

    # Slot change title
    def _change_title_window(self):
        print('Changing title')
        self.setWindowTitle('New Title (Callback)')

if __name__ == '__main__':
    app = QApplication([])
    window = WindowPySide()
    window.show()
    sys.exit(app.exec())


class Solution:
    def maxSubArray(self, nums: list[int]) -> int:
        max_sum = float('-inf')  # Initialize max_sum to negative infinity
        current_sum = 0

        for num in nums:
            # Start a new subarray or extend the current one
            current_sum = max(num, current_sum + num)
            # Update max_sum if the current subarray sum is greater
            max_sum = max(max_sum, current_sum)

        return max_sum


import datetime
import json
import re
from copy import deepcopy
from PyQt5 import QtWidgets, uic, QtCore, QtGui
from QuantLib import Date, China, Period
import traceback

from ui import *
from utils import *
import trade

class Ui(QtWidgets.QMainWindow):
    def __init__(self):
        super(Ui, self).__init__()
        self.resize(1500, 1000)
        layout_1 = QtWidgets.QHBoxLayout()
        layout_2 = QtWidgets.QHBoxLayout()

        self.trader_ui = TraderUi()
        self.counterparty_ui = CounterpartyUi()
        self.bond_info_ui = BondInfoUi()
        self.transfer_ui = TransferUi()

        layout_1.addWidget(self.trader_ui)
        layout_1.addWidget(self.counterparty_ui)
        layout_2.addWidget(self.bond_info_ui)
        layout_2.addWidget(self.transfer_ui)

        mainlayout = QtWidgets.QVBoxLayout()
        mainlayout.addLayout(layout_1, 10)
        mainlayout.addLayout(layout_2, 60)
        widget = QtWidgets.QWidget()
        widget.setLayout(mainlayout)
        self.setCentralWidget(widget)

        self.bond_info_ui.get_position.clicked.connect(self.getPosition)
        self.bond_info_ui.send_order.clicked.connect(self.sendOrder)
        self.bond_info_ui.is_last_trade.clicked.connect(self.updateTplus1)
        self.bond_info_ui.send_settlement.clicked.connect(self.sendSettlement)
        self.bond_info_ui.save_log.clicked.connect(self.saveLog)
        self.bond_info_ui.parent = self

        self.transfer_ui.send_order.clicked.connect(self.sendTransferOrder)
        self.transfer_ui.is_last_trade.clicked.connect(self.updateTransfer)

        self.trader_ui.now_time_button.clicked.connect(self.changeNowtime)
        self.trader_ui.check_info.clicked.connect(self.checkTraderInfo)

        # create Portfolio instances for all accounts.
        self.portfolios = {}
        self.bond_info_ui.initial_portfolios = {}
        portflios = json.load(open('trader.json', encoding='utf-8'))
        for key_1 in portflios.keys():
            for key_2, item_2 in portflios[key_1].items():
                account = key_1 + key_2
                self.portfolios[key_1 + key_2] =\
                    portfolio_utils.create_portfolio(account)
                # Makes it easier to update json file
                self.portfolios[key_1 + key_2].key_1 = key_1
                self.portfolios[key_1 + key_2].key_2 = key_2

                self.bond_info_ui.initial_portfolios[key_1 + key_2] =\
                    portfolio_utils.create_portfolio(account)
                x = self.bond_info_ui.initial_portfolios[key_1 + key_2].bonds
                self.bond_info_ui.initial_portfolios[key_1 + key_2].init = True
                self.bond_info_ui.initial_portfolios[key_1 +
                                                     key_2].initial_value = x
                self.bond_info_ui.initial_portfolios[key_1 +
                                                     key_2].key_1 = key_1
                self.bond_info_ui.initial_portfolios[key_1 +
                                                     key_2].key_2 = key_2

    def getPosition(self):
        trader_position = json.load(open('trader.json', encoding='utf-8'))[
            self.trader_ui.list_type.currentText()]

        trader_id = self.trader_ui.account_list.currentText()
        code = self.bond_info_ui.code.text()

        bond_position = trader_position[trader_id]['position'].get(code, 0)
        cash_position = trader_position[trader_id]['cash']

        self.bond_info_ui.bond_position.setText(str(bond_position))
        self.bond_info_ui.cash_position.setText(str(cash_position))

    def changeNowtime(self):
        list_type = self.trader_ui.list_type.currentText()
        trader_id = self.trader_ui.account_list.currentText()
        key = list_type + trader_id

        date = self.trader_ui.now_time.text()
        self.portfolios[key].now_time = date
        QtWidgets.QMessageBox().about(self, '提示', '账户时间被设置为"{}"'.format(date))

    def checkTraderInfo(self):
        list_type = self.trader_ui.list_type.currentText()
        trader_id = self.trader_ui.account_list.currentText()
        key = list_type + trader_id
        portfolio = self.portfolios[key]

        popup = QtWidgets.QMainWindow(parent=self)
        mainlayout = QtWidgets.QVBoxLayout()
        widget = QtWidgets.QWidget()
        widget.setLayout(mainlayout)
        popup.setCentralWidget(widget)

        trader_info = '''
        账户名称:{}
        内置时间:{}
        全部资金:{}
        可用资金:{}
        '''.format(portfolio.account, portfolio.now_time, portfolio.cash, portfolio.free_cash)
        msg = QtWidgets.QTextBrowser()
        msg.setText(trader_info)
        mainlayout.addWidget(msg)

        df_ = displayDataFrame(portfolio.bonds, key, self)
        mainlayout.addWidget(df_)

        df_2 = displayDataFrame(portfolio.all_trade, key, self)
        mainlayout.addWidget(df_)

        msg_2 = QtWidgets.QMessageBox()
        msg_2.setStandardButtons(QtWidgets.QMessageBox.Ok)
        mainlayout.addWidget(msg_2)
        popup.resize(600, 600)
        popup.show()
        msg_2.exec_()
        popup.close()

    def _export_trader_info(self):
        excel_utils._export_trader_info(self)

    def sendOrder(self):
        self.bond_info_ui._export_info()
        self._export_trader_info()
        x = compliance.check_spot_order()
        if ('失败' in x) or ('不合规' in x) or ('不达标' in x):
            error_message = '报单失败，失败原因：\n'+'!\n'.join(x.split('！'))
            QtWidgets.QMessageBox().about(self, '错误信息', error_message)
            return False

        elif '预警' in x:
            error_message = '交易预警：\n'+'!\n'.join(x.split('！'))
            QtWidgets.QMessageBox().about(self, '预警', error_message)

        try:
            trade = trade_utils.create_spot_trade()
            print(trade.trade_time, type(trade.trade_time))
            print(trade.settlement_date, type(trade.settlement_date))

        except:
            QtWidgets.QMessageBox().about(self, '错误信息', traceback.format_exc())
            return False

        # 更新Portfolio对象
        try:
            account = trade.inside_id
            self.portfolios[account].append_waiting_trade(trade)
            self.portfolios[account].portfolio_update_t0(trade)
            print(self.portfolios[account].all_trade)
            print(self.portfolios[account].now_time)
            # print(self.portfolios[account].now_time, type(self.portfolios[account].now_time))
            # print(type(self.portfolios[account].all_trade.iloc[0, 1]))

            if trade.is_inside_trade:
                account = trade.other_inside_id
                self.portfolios[account].append_waiting_trade(
                    trade.reversed())
                self.portfolios[account].portfolio_update_t0(
                    trade.reversed())

        except:
            QtWidgets.QMessageBox().about(
                self, '错误信息', traceback.format_exc())
            return False

        # 写入Excel和json文件
        if not trade.is_inside_trade:
            self.portfolios[trade.inside_id].to_excel()
            self.portfolios[trade.inside_id].to_json()
        else:
            self.portfolios[trade.inside_id].to_excel()
            self.portfolios[trade.other_inside_id].to_excel()

            self.portfolios[trade.inside_id].to_json()
            portfolio_utils.to_json(self.portfolios[trade.other_inside_id])

        QtWidgets.QMessageBox().about(self, '', '报单完成')

    def sendTransferOrder(self):
        # self.transfer_ui._export_transfer_info()
        x = compliance.check_transfer_order()
        if x != '交易成功':
            error_message = '转托管报单失败，失败原因：\n'+'!\n'.join(x.split('！'))
            QtWidgets.QMessageBox().about(self, '错误信息', error_message)
            return False

        try:
            trade = trade_utils.create_transfer_trade()
            trade_ = deepcopy(trade)
            print(trade.settlement_date)
            trade.settlement_date = trade.trade_time
            print(trade_.settlement_date)
        except:
            QtWidgets.QMessageBox().about(self, '错误信息', traceback.format_exc())
            return False

        # 更新Portfolio对象
        try:
            trade.settlement_days == 'T+1'
            account = trade.inside_id
            self.portfolios[account].append_waiting_trade(trade)
            self.portfolios[account].portfolio_update_t0(trade)

            account = trade.other_inside_id
            self.portfolios[account].append_waiting_trade(
                trade_.reversed())
            self.portfolios[account].portfolio_update_t0(trade_.reversed())

        except:
            QtWidgets.QMessageBox().about(
                self, '错误信息', traceback.format_exc())
            return False

        # 写入Excel和json文件
        if not trade.is_inside_trade:
            portfolio_utils.to_excel(self.portfolios[trade.inside_id])
            portfolio_utils.to_json(self.portfolios[trade.inside_id])
        else:
            portfolio_utils.to_excel(self.portfolios[trade.inside_id])
            portfolio_utils.to_excel(self.portfolios[trade.other_inside_id])

            portfolio_utils.to_json(self.portfolios[trade.inside_id])
            portfolio_utils.to_json(self.portfolios[trade.other_inside_id])

        QtWidgets.QMessageBox().about(self, '', '报单完成')

    def sendSettlement(self):
        # 当前账户提交清算申请
        list_type = self.trader_ui.list_type.currentText()
        trader_id = self.trader_ui.account_list.currentText()
        key = list_type + trader_id

        self.portfolios[key].settle()
        self.portfolios[key].to_json()
        self.portfolios[key].to_excel()

        self.hintFailures()

    def checkSufficiency(self):
        prompt_msg = []
        popup = QtWidgets.QMainWindow(parent=self)
        mainlayout = QtWidgets.QVBoxLayout()
        widget = QtWidgets.QWidget()
        widget.setLayout(mainlayout)
        popup.setCentralWidget(widget)

        for key in self.portfolios:
            temp_portfolio = deepcopy(self.portfolios[key])
            temp_portfolio.settle()
            bonds_not_enough = temp_portfolio.bonds[temp_portfolio.bonds['par_amount'] < 0]
            if not bonds_not_enough.empty:
                x = bonds_not_enough['bond_code'].to_list()
                msg = ['{}-{}现券持仓不足'.format(key, i) for i in x]
                prompt_msg.extend(msg)
            # display current positions
            df_ = displayDataFrame(temp_portfolio.bonds, key, self)
            mainlayout.addWidget(df_)

        msg = QtWidgets.QMessageBox()
        text = "若不进行转托管操作，账户持仓如下，请选择是否进行接下去的操作"
        msg.setText(text)
        msg.setWindowTitle("请选择")
        msg.setStandardButtons(
            QtWidgets.QMessageBox.No | QtWidgets.QMessageBox.Yes)
        mainlayout.addWidget(msg)
        popup.resize(600, 600)
        popup.show()
        retval = msg.exec_()
        popup.close()
        return prompt_msg, retval

    def updateTplus1(self):
        # 更新明天到账的T+1交易，调用后now_time会+1
        # 首先检查是否存在需要弥补交易
        prompt_msg, retval = self.checkSufficiency()
        if retval == QtWidgets.QMessageBox.No:
            # 中止本函数运行
            return

        if prompt_msg:
            msg = QtWidgets.QMessageBox()
            text = "更新持仓中止，以下现券不足，请选择是否进行自动内部转托管\n" + '\n'.join(prompt_msg)
            msg.setText(text)
            msg.setWindowTitle("持仓不足警示")
            msg.setStandardButtons(
                QtWidgets.QMessageBox.No | QtWidgets.QMessageBox.Yes)
            retval = msg.exec_()

            # 若选择Yes，则进入此分支，进行自动转托管
            if retval == QtWidgets.QMessageBox.Yes:
                self.autoTransfer()
                QtWidgets.QMessageBox().about(self, '提示信息', '自动转托管完成，请再次点击“完成今日交易”按钮')
                return
            # 若不选择，则继续更新T+1持仓

        # 更新T+1
        cal = China(China.IB)
        for key in self.portfolios:
            date = self.portfolios[key].now_time
            if isinstance(date, datetime.datetime):
                date = date.date().isoformat().replace('-', '/')
            x = date.split('/')
            ql_date = Date(int(x[2]), int(x[1]), int(x[0]))
            next_trading_day = cal.advance(
                ql_date, Period('1D')).ISO().split('-')
            next_trading_day = ql_date.ISO().replace('-', '/')
            self.portfolios[key].now_time = next_trading_day
            self.portfolios[key].portfolio_update_t1()
            self.portfolios[key].now_time = date

            self.portfolios[key].to_excel()
            self.portfolios[key].to_json()
            self.portfolios[key].save_position()
            self.portfolios[key].log()

        QtWidgets.QMessageBox().about(self, '', '更新完成')

    def updateTransfer(self):
        # 更新明天到账的转托管交易，调用后now_time会+1
        cal = China(China.IB)
        for key in self.portfolios:
            date = self.portfolios[key].now_time
            if isinstance(date, datetime.datetime):
                date = date.date().isoformat().replace('-', '/')
            x = date.split('/')
            ql_date = Date(int(x[2]), int(x[1]), int(x[0]))
            next_trading_day = cal.advance(
                ql_date, Period('1D')).ISO().replace('-', '/')
            self.portfolios[key].now_time = next_trading_day
            other_portfolios = [self.portfolios[i]
                                for i in self.portfolios if i != key]
            self.portfolios[key].portfolio_update_transfer(direction='in',
                                                           other_portfolios=other_portfolios)
            self.portfolios[key].now_time = date

            self.portfolios[key].to_excel()
            self.portfolios[key].to_json()
            self.portfolios[key].save_position()
            self.portfolios[key].log()

        QtWidgets.QMessageBox().about(self, '', '更新完成')

    def autoTransfer(self):
        # 判断各内部账户中是否存在互补，并进行提示
        # 转托管仍需要手动输入
        temp_portfolios = {}
        for key in self.portfolios:
            temp_portfolios[key] = deepcopy(self.portfolios[key])
            temp_portfolios[key].settle()
            bonds_not_enough = temp_portfolios[key].bonds[temp_portfolios.bonds['par_amount'] < 0]
            temp_portfolios[key].unfilled = bonds_not_enough

    def hintFailures(self):
        popup = QtWidgets.QMainWindow(parent=self)
        mainlayout = QtWidgets.QVBoxLayout()
        widget = QtWidgets.QWidget()
        widget.setLayout(mainlayout)
        popup.setCentralWidget(widget)

        msg = QtWidgets.QMessageBox()
        msg.setText("结算报单完成，该账户以下Trade属于Failed Trade")
        mainlayout.addWidget(msg)

        list_type = self.trader_ui.list_type.currentText()
        trader_id = self.trader_ui.account_list.currentText()
        key = list_type + trader_id
        df = self.portfolios[key].failed_trade
        df = displayDataFrame(df, key, self)

        mainlayout.addWidget(df)
        popup.resize(600, 600)
        popup.show()
        msg.exec_()
        popup.close()

    def saveLog(self):
        for x in self.portfolios.values():
            x.log()

class PandasModel(QtCore.QAbstractTableModel):

    def __init__(self, data):
        QtCore.QAbstractTableModel.__init__(self)
        self._data = data

    def rowCount(self, parent=None):
        return self._data.shape[0]

    def columnCount(self, parnet=None):
        return self._data.shape[1]

    def data(self, index, role=QtCore.Qt.DisplayRole):
        if index.isValid():
            if role == QtCore.Qt.DisplayRole:
                return str(self._data.iloc[index.row(), index.column()])
        return None

    def headerData(self, col, orientation, role):
        if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
            return self._data.columns[col]
        return None

def displayDataFrame(df, title='', parent=None):
    popup = QtWidgets.QMainWindow(parent=parent)
    popup.setWindowTitle(title)
    popup.view = QtWidgets.QTableView()
    model = PandasModel(df)
    popup.view.setModel(model)
    popup.view.resize(800, 400)
    popup.setCentralWidget(popup.view)
    return popup


#!/usr/bin/env python
# _*_ coding:UTF-8 _*_
import rospy
import signal
from std_msgs.msg import String
from webots_ros.srv import set_float
from webots_ros.srv import set_int
from geometry_msgs.msg import Twist

TIME_STEP = 32
MAX_SPEED = 5.0
controllerName = ""
v_x = 0
w_z = 0
motorNames = ["wheel1", "wheel2", "wheel3", "wheel4"]

def autoQuit(signum,frame):
    for i_ in range(len(motorNames)):
        serviceName = controllerName+"/"+motorNames[i_] +"/set_velocity"
        setVelClient = rospy.ServiceProxy(serviceName,set_float)
        setVelClient.call(0)

    serviceName = controllerName + "/robot/time_step"
    timeStepClient = rospy.ServiceProxy(serviceName,set_int)
    timeStepClient.call(0)

    rospy.signal_shutdown("closed!")
    rospy.loginfo("用户终止节点运行！" )
    return

def controllerNameCallback(data):
    """webots端控制器名称回调函数"""
    global controllerName
    controllerName = "/" + data.data

def cmdCallback(data):
    """更新小车速度"""
    global v_x
    global w_z
    v_x = data.linear.x
    w_z = data.angular.z

def webots_controller_function():
    # 初始化节点
    rospy.init_node('my_webots_controller', anonymous=True)
    #rospy.wait_for_message("/model_name",String)

    # 订阅控制器名称
    while controllerName == "":
        nameSub = rospy.Subscriber("/model_name", String, controllerNameCallback)

    signal.signal(signal.SIGINT, autoQuit)

    # 设置基本仿真步长
    serviceName = controllerName + "/robot/time_step"
    timeStepClient = rospy.ServiceProxy(serviceName,set_int)
    resp = timeStepClient.call(TIME_STEP)
    if resp.success:
        rospy.loginfo("仿真步长设置成功:%s" %TIME_STEP )
    else:
        rospy.logwarn("服务调用失败!!!" )

    for i_ in range(len(motorNames)):
        # 定义服务
        serviceName =  controllerName + "/"+motorNames[i_] + "/set_position"
        setPosClient = rospy.ServiceProxy(serviceName,set_float)
        # 向server端发送请求，发送的request内容为set_float.srv中定义的
        resp = setPosClient.call(float("inf"))
        if resp.success:
            rospy.loginfo("位置模式设置成功:%s" %motorNames[i_] )
        else:
            rospy.logwarn("调用set_position服务失败:%s"%motorNames[i_] )

        serviceName = controllerName+"/"+motorNames[i_] +"/set_velocity"
        setVelClient = rospy.ServiceProxy(serviceName,set_float)
        resp = setVelClient.call(0)
        if resp.success:
            rospy.loginfo("速度模式设置成功:%s" %motorNames[i_] )
        else:
            rospy.logwarn("调用set_velocity服务失败:%s"%motorNames[i_] )

    while not rospy.is_shutdown():
        cmdSub = rospy.Subscriber("/cmd_vel",Twist,cmdCallback)
        print(str(v_x)+"   "+str(w_z))

        if v_x > 0.0 and w_z == 0.0: # 前
            for i_ in range(len(motorNames)):
                serviceName = controllerName+"/"+motorNames[i_] +"/set_velocity"
                setVelClient = rospy.ServiceProxy(serviceName,set_float)
                setVelClient.call(MAX_SPEED)

        if v_x < 0.0 and w_z == 0.0: # 后
            for i_ in range(len(motorNames)):
                serviceName = controllerName+"/"+motorNames[i_] +"/set_velocity"
                setVelClient = rospy.ServiceProxy(serviceName,set_float)
                setVelClient.call(- MAX_SPEED)

        if v_x == 0.0 and w_z > 0.0: # 左
            serviceName = controllerName+"/"+motorNames[0] +"/set_velocity"
            setVelClient = rospy.ServiceProxy(serviceName,set_float)
            setVelClient.call(- MAX_SPEED)

            serviceName = controllerName+"/"+motorNames[1] +"/set_velocity"
            setVelClient = rospy.ServiceProxy(serviceName,set_float)
            setVelClient.call(MAX_SPEED)

            serviceName = controllerName+"/"+motorNames[2] +"/set_velocity"
            setVelClient = rospy.ServiceProxy(serviceName,set_float)
            setVelClient.call(MAX_SPEED)

            serviceName = controllerName+"/"+motorNames[3] +"/set_velocity"
            setVelClient = rospy.ServiceProxy(serviceName,set_float)
            setVelClient.call(- MAX_SPEED)

        if v_x == 0.0 and w_z < 0.0: # 右
            serviceName = controllerName+"/"+motorNames[0] +"/set_velocity"
            setVelClient = rospy.ServiceProxy(serviceName,set_float)
            setVelClient.call(MAX_SPEED)

            serviceName = controllerName+"/"+motorNames[1] +"/set_velocity"
            setVelClient = rospy.ServiceProxy(serviceName,set_float)
            setVelClient.call(-MAX_SPEED)

            serviceName = controllerName+"/"+motorNames[2] +"/set_velocity"
            setVelClient = rospy.ServiceProxy(serviceName,set_float)
            setVelClient.call(-MAX_SPEED)

            serviceName = controllerName+"/"+motorNames[3] +"/set_velocity"
            setVelClient = rospy.ServiceProxy(serviceName,set_float)
            setVelClient.call(MAX_SPEED)
        if v_x == 0.0 and w_z == 0.0: # 停
            for i_ in range(len(motorNames)):
                serviceName = controllerName+"/"+motorNames[i_] +"/set_velocity"
                setVelClient = rospy.ServiceProxy(serviceName,set_float)
                setVelClient.call(0)

        # 判断webots端是否重置仿真，如果重置则退出运行
        resp = timeStepClient.call(TIME_STEP)
        if (not resp.success):
            rospy.logerr("Failed to call service time_step for next step.")
            rospy.signal_shutdown("closed!")

if __name__ == '__main__':
    webots_controller_function()


import os
import sys

sys.path.append(os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
from exchange_pair_object.exchange_pair import ExchangePair
import env
from exchange.binance import BinanceFuture
from exchange.korbit import Korbit
import asyncio
from alert.bot import TelegramBot

class KorbitBinanceFuture(ExchangePair):
    def __init__(self, korbit: Korbit, binance_future: BinanceFuture):
        super().__init__(korbit, binance_future)
        self.telegram_bot = TelegramBot(chat_id=env.KORBIT_CHAT_ID)
        self.won_exchange_fee = korbit.market_fee
        self.dollar_exchange_fee = binance_future.market_fee

    async def health_check(self):
        while True:
            self.telegram_bot.log("health_check")
            loop.run_in_executor(None, self.telegram_bot.send_logs)
            await asyncio.sleep(10800)  # 3 hour

    def alert_info(self, coin, kimp, time_diff1, time_diff2):
        coin_info = self.kimp_status_dict[coin]
        if coin_info["is_active"]:
            if 0 < kimp < 4:
                self.kimp_status_dict[coin]["is_active"] = False
                self.kimp_status_dict[coin]["kimp"] = kimp
                self.kimp_status_dict[coin]["time_diff1"] = time_diff1
                self.kimp_status_dict[coin]["time_diff2"] = time_diff2
        else:
            if kimp <= 0 or kimp >= 4:
                self.kimp_status_dict[coin]["is_active"] = True
                self.kimp_status_dict[coin]["kimp"] = kimp
                self.kimp_status_dict[coin]["time_diff1"] = time_diff1
                self.kimp_status_dict[coin]["time_diff2"] = time_diff2
                log = f"종목: {coin}\t  김프: {kimp:.2f}%\t  환율:{self.exchange_rate}\t  time_delay: ({time_diff1:.2f},{time_diff2:.2f})"
                self.telegram_bot.log(log)
                self.telegram_bot.send_logs()

if "__main__" == __name__:
    binance_future = BinanceFuture()
    korbit = Korbit()
    korbit_binance_future_obj = KorbitBinanceFuture(korbit=korbit, binance_future=binance_future)

    loop = asyncio.get_event_loop()
    loop.run_until_complete(korbit_binance_future_obj.set_available_coin_list())

    tasks = [asyncio.ensure_future(korbit.socket_order_book(korbit.process_buffer)),
             asyncio.ensure_future(binance_future.socket_order_book(binance_future.process_buffer)),
             asyncio.ensure_future(korbit_binance_future_obj.cal_kimp()),
             asyncio.ensure_future(korbit_binance_future_obj.update_exchange_rate()),
             asyncio.ensure_future(korbit_binance_future_obj.health_check())
             ]
    loop.run_until_complete(asyncio.wait(tasks))


# 这个项目包含了吴恩达机器学习ex3的python实现，主要知识点为多类别逻辑回归、神经网络，题目内容可以查看数据集中的ex3.pdf

# # 1 多分类
# 这个部分需要你实现手写数字（0到9）的识别。你需要扩展之前的逻辑回归，并将其应用于一对多的分类。

# ## 数据集
# 这是一个MATLAB格式的.m文件，其中包含5000个20*20像素的手写字体图像，以及他对应的数字。另外，数字0的y值，对应的是10
# 用Python读取我们需要使用SciPy
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib
from scipy.io import loadmat
from sklearn.metrics import classification_report  # 这个包是评价报告

data = loadmat('ex3data1.mat')
print(data)
print(data['X'].shape, data['y'].shape)   #(5000, 400) (5000, 1)

# ## 1.2 数据可视化
# 随机展示100个数据
sample_idx = np.random.choice(np.arange(data['X'].shape[0]), 100)
sample_images = data['X'][sample_idx, :]
print(np.shape(sample_images))
print(data['y'][sample_idx, :].reshape((10, 10)))
fig, ax_array = plt.subplots(nrows=10, ncols=10, sharey=True, sharex=True, figsize=(12, 12))
for r in range(10):
    for c in range(10):
        ax_array[r, c].matshow(np.array(sample_images[10 * r + c].reshape((20, 20))).T, cmap=matplotlib.cm.binary)
        plt.xticks(np.array([]))
        plt.yticks(np.array([]))
plt.show()

# ## 1.3 将逻辑回归向量化
# 你将用多分类逻辑回归做一个分类器。因为现在有10个数字类别，所以你需要训练10个不同的逻辑回归分类器。为了让训练效率更高，将逻辑回归向量化是非常重要的，不要用循环。
# ### 1.3.1 向量化代价函数
# # sigmoid 函数
def sigmoid(z):
    return 1 / (1 + np.exp(-z))
# 带正则化的代价函数：
def cost(theta, X, y, learningRate):
    theta = np.matrix(theta)
    X = np.matrix(X)
    y = np.matrix(y)
    first = np.multiply(-y, np.log(sigmoid(X * theta.T)))
    second = np.multiply((1 - y), np.log(1 - sigmoid(X * theta.T)))
    reg = (learningRate / (2 * len(X))) * np.sum(np.power(theta[:, 1:theta.shape[1]], 2))#从1开始求和
    return np.sum(first - second) / len(X) + reg

# ### 1.3.3 向量化正则化逻辑回归
# 向量化后的梯度更新公式如下：
def gradient(theta, X, y, learningRate):
    theta = np.matrix(theta)
    X = np.matrix(X)
    y = np.matrix(y)
    parameters = int(theta.ravel().shape[1])  #参数401
    error = sigmoid(X * theta.T) - y
    grad = ((X.T * error) / len(X)).T + ((learningRate / len(X)) * theta)
    # θ(0)个参数不用正则化
    grad[0, 0] = np.sum(np.multiply(error, X[:, 0])) / len(X)
    return np.array(grad).ravel()

# ## 1.4 一对多分类器
# 现在我们已经定义了代价函数和梯度函数，现在是构建分类器的时候了。
# 对于这个任务，我们有10个可能的类，并且由于逻辑回归只能一次在2个类之间进行分类，我们需要多类分类的策略。
# 在本练习中，我们的任务是实现一对一全分类方法，其中具有k个不同类的标签就有k个分类器，每个分类器在“类别 i”和“不是 i”之间决定。
# 我们将把分类器训练包含在一个函数中，该函数计算10个分类器中的每个分类器的最终权重，并将权重返回为k*(n + 1)数组，其中n是参数数量。
from scipy.optimize import minimize

def one_vs_all(X, y, num_labels, learning_rate):
    rows = X.shape[0]
    params = X.shape[1]
    # k * (n + 1) array for the parameters of each of the k classifiers
    all_theta = np.zeros((num_labels, params + 1))  #[10,401]
    # insert a column of ones at the beginning for the intercept term
    X = np.insert(X, 0, values=np.ones(rows), axis=1) #[5000,401]
    # labels are 1-indexed instead of 0-indexed
    for i in range(1, num_labels + 1):     #i取1-10    等效成10个2分类问题，训练10个分类器
        theta = np.zeros(params + 1)      #401
        y_i = np.array([1 if label == i else 0 for label in y])
        y_i = np.reshape(y_i, (rows, 1))  #[5000,1]
        # minimize the objective function
        fmin = minimize(fun=cost, x0=theta, args=(X, y_i, learning_rate), method='TNC', jac=gradient)
        all_theta[i - 1, :] = fmin.x
    return all_theta

# 这里需要注意的几点：首先，我们为theta添加了一个额外的参数（与训练数据一列），以计算截距项（常数项）。
# 其次，我们将y从类标签转换为每个分类器的二进制值（要么是类i，要么不是类i）。
# 最后，我们使用SciPy的较新优化API来最小化每个分类器的代价函数。
# 如果指定的话，API将采用目标函数，初始参数集，优化方法和jacobian（渐变）函数。 然后将优化程序找到的参数分配给参数数组。
# 实现向量化代码的一个更具挑战性的部分是正确地写入所有的矩阵，保证维度正确。
rows = data['X'].shape[0]
params = data['X'].shape[1]
all_theta = np.zeros((10, params + 1))
X = np.insert(data['X'], 0, values=np.ones(rows), axis=1)
theta = np.zeros(params + 1)
y_0 = np.array([1 if label == 0 else 0 for label in data['y']])
y_0 = np.reshape(y_0, (rows, 1))
print(X.shape, y_0.shape, theta.shape, all_theta.shape)  #(5000, 401) (5000, 1) (401,) (10, 401)

# 注意，theta是一维数组，因此当它被转换为计算梯度的代码中的矩阵时，它变为（1×401）矩阵。 我们还检查y中的类标签，以确保它们看起来像我们想象的一致。
print(np.unique(data['y']))  # 看下有几类标签  [ 1  2  3  4  5  6  7  8  9 10]   10表示0
# 让我们确保我们的训练函数正确运行，并且得到合理的输出。
all_theta = one_vs_all(data['X'], data['y'], 10, 1)
print(all_theta.shape)   #(10, 401)

# ### 1.4.1 一对多预测
# 我们现在准备好最后一步 - 使用训练完毕的分类器预测每个图像的标签。
# 对于这一步，我们将计算每个类的类概率，对于每个训练样本（使用当然的向量化代码），并将输出类标签为具有最高概率的类。
def predict_all(X, all_theta):
    rows = X.shape[0]
    params = X.shape[1]
    num_labels = all_theta.shape[0]
    # same as before, insert ones to match the shape
    X = np.insert(X, 0, values=np.ones(rows), axis=1)
    # convert to matrices
    X = np.matrix(X)
    all_theta = np.matrix(all_theta)
    # compute the class probability for each class on each training instance
    h = sigmoid(X * all_theta.T)
    # create array of the index with the maximum probability
    h_argmax = np.argmax(h, axis=1)
    # because our array was zero-indexed we need to add one for the true label prediction
    h_argmax = h_argmax + 1
    return h_argmax

# 现在我们可以使用predict_all函数为每个实例生成类预测，看看我们的分类器是如何工作的。
y_pred = predict_all(data['X'], all_theta)
print(classification_report(data['y'], y_pred))

# # 2 神经网络
# 在前面一个部分，我们已经实现了多分类逻辑回归来识别手写数字。但是，逻辑回归并不能承载更复杂的假设，因为他就是个线性分类器。
# 这部分，你需要实现一个可以识别手写数字的神经网络。神经网络可以表示一些非线性复杂的模型。权重已经预先训练好，你的目标是在现有权重基础上，实现前馈神经网络。
# ## 2.1 模型表达

# 输入是图片的像素值，20*20像素的图片有400个输入层单元，不包括需要额外添加的加上常数项。
# 材料已经提供了训练好的神经网络的参数  400个输入单元有25个隐层单元和10个输出单元（10个输出）

# ## 2.2 前馈神经网络和预测
# 你需要实现前馈神经网络预测手写数字的功能。和之前的一对多分类一样，神经网络的预测会把输出单元中值最大的，作为预测输出

weight = loadmat("ex3weights.mat")
theta1, theta2 = weight['Theta1'], weight['Theta2']
print(theta1.shape, theta2.shape)  #(25, 401) (10, 26)
# 插入常数项
X2 = np.matrix(np.insert(data['X'], 0, values=np.ones(X.shape[0]), axis=1))
y2 = np.matrix(data['y'])
print(X2.shape, y2.shape)   #(5000, 401) (5000, 1)

a1 = X2
z2 = a1 * theta1.T
print('z2shape:',z2.shape)
a2 = sigmoid(z2)
print('a2shape:',a2.shape)
a2 = np.insert(a2, 0, values=np.ones(a2.shape[0]), axis=1)
z3 = a2 * theta2.T
print('z3shape:',z3.shape)
a3 = sigmoid(z3)
print('a3shape:',a3.shape)

y_pred2 = np.argmax(a3, axis=1) + 1
print(y_pred2.shape)
print(classification_report(y2, y_pred))

裸写逻辑回归多个分类手写数字识别.py