"""
A* grid planning has been improved
Author: Grizi-ju
The tutorials at bilibili, ID:小巨同学zz https://www.bilibili.com/video/BV1FL4y1M7PM?spm_id_from=333.999.0.0
See Wikipedia article (https://en.wikipedia.org/wiki/A*_search_algorithm)
For reference only, it is forbidden to sell codes in a commercial manner
Please give me a Star or Fork, thank u
"""

import math
import numpy as np
from math import factorial
import matplotlib.pyplot as plt

show_animation = True

class AStarPlanner:

    def __init__(self, ox, oy, reso, rr):

        self.reso = reso   # grid resolution [m]
        self.rr = rr       # robot radius [m]
        self.calc_obstacle_map(ox, oy)
        self.motion = self.get_motion_model()

    # 创建一个节点类，节点的信息包括：xy坐标，cost代价, parent_index
    class Node:
        def __init__(self, x, y , cost, parent_index):
            self.x = x
            self.y = y
            self.cost = cost  # g(n)
            self.parent_index = parent_index

        def __str__(self):     # 返回字符串类型
            return str(self.x) + "," + str(self.y) + "," + str(
                self.cost) + "," + str(self.parent_index)

    # planning函数，传入起始点坐标sx,sy,gx,gy, 返回pathx,pathy(最终的路径)
    def planning(self, sx, sy, gx, gy):
        """
        1、sx = nstart  sy = ngoal
        2、open_set  closed_set
        3、open_set = nstart
        4、将open表中代价最小的子节点=当前节点，并在plot上动态显示，按esc退出
        5、如果当前节点等于ngoal，提示找到目标点
        6、删除open表中的内容，添加到closed表中
        7、基于运动模型定义搜索方式
        8、pathx,pathy = 最终路径(传入ngoal,closed_set)，返回pathx,pathy
        """
        # 1、sx = nstart  sy = ngoal  初始化nstart、ngoal坐标作为一个节点，传入节点全部信息
        nstart = self.Node(self.calc_xyindex(sx, self.minx),  # position min_pos
                           self.calc_xyindex(sy, self.miny),
                           0.0,
                           -1)
        ngoal = self.Node(self.calc_xyindex(gx, self.minx),
                           self.calc_xyindex(gy, self.miny),
                           0.0,
                           -1)

        # 2、open表、closed表
        # 3、起点加入open表
        open_set, closed_set = dict(), dict()
        open_set[self.calc_grid_index(nstart)] = nstart

        while 1:
            if len(open_set) == 0:
                print("Open set is empty...")
                break

        # 4、将open表中代价最小的子节点 = 当前节点，并在plot上动态显示，按esc退出
            # f(n)=g(n)+h(n)  实际代价+预估代价
            # 第几个子节点 child_node_id
            c_id = min(
                open_set,
                key=lambda o: open_set[o].cost + self.calc_heuristic(ngoal, open_set[o]))
            current = open_set[c_id]   # open表中当前节点 = 当前节点

            # 将当前节点显示出来
            if show_animation:
                plt.plot(self.calc_grid_position(current.x, self.minx),
                         self.calc_grid_position(current.y, self.miny),
                         "xc")   # 青色x 搜索点
                # 按esc退出
                plt.gcf().canvas.mpl_connect('key_release_event',
                                              lambda event: [exit(0) if event.key == 'escape' else None]
                                            )
                if len(closed_set.keys()) % 10 == 0:
                    plt.pause(0.001)

            if current.x == ngoal.x and current.y == ngoal.y:
                print("Find goal!")
                ngoal.parent_index = current.parent_index
                ngoal.cost = current.cost
                break

            # 删除open表中的节点,并把它添加到closed表
            del open_set[c_id]
            closed_set[c_id] = current

            # 基于motion model做栅格扩展，也就是搜索方式，可进行改进
            for i, _ in enumerate(self.motion):
                node = self.Node(current.x + self.motion[i][0],    # 当前x+motion列表中第0个元素dx
                                 current.y + self.motion[i][1],
                                 current.cost + self.motion[i][2],c_id)
                n_id = self.calc_grid_index(node)   # 返回该节点位置index

                # If the node is not safe, do nothing
                if not self.verify_node(node):
                    continue

                if n_id in closed_set:
                    continue

                if n_id not in open_set:
                    open_set[n_id] = node
                else:
                    if open_set[n_id].cost > node.cost:
                        open_set[n_id] = node    # 搜索的节点代价更小，替代open表中的节点

        pathx, pathy = self.calc_final_path(ngoal, closed_set)
        return pathx, pathy

    def calc_final_path(self, ngoal, closedset):    # 传入目标点和close表，经过函数处理得到最终所有的xy列表
        pathx, pathy = [self.calc_grid_position(ngoal.x, self.minx)], [
                        self.calc_grid_position(ngoal.y, self.miny)]
        parent_index = ngoal.parent_index
        while parent_index != -1:
            n = closedset[parent_index]
            pathx.append(self.calc_grid_position(n.x, self.minx))
            pathy.append(self.calc_grid_position(n.y, self.miny))
            parent_index = n.parent_index

        return pathx, pathy

    @staticmethod  # 静态方法，calc_heuristic函数不用传入self，经常改进启发函数，目的是提高阅读性
    def calc_heuristic(n1, n2):  # n1传入ngoal，n2传入open表要计算的那个点
        """
        改进点1：启发函数距离公式 曼哈顿距离、欧式距离、对角线距离 默认使用对角线距离
        """
        # d = np.abs(n1.x - n2.x) + np.abs(n1.y - n2.y)     #  Manhattan distance

        # dx = np.abs(n1.x - n2.x)                          #  Diagnol distance
        # dy = np.abs(n1.y - n2.y)
        # min_xy = min(dx,dy)
        # d = dx + dy + (math.sqrt(2) - 2) * min_xy

        d = math.hypot(n1.x - n2.x, n1.y - n2.y)            #  Euclidean distance
        print(d)

        """
        改进点2：f(n)=g(n)+h(n)*w(n)
        动态加权：在放弃搜索最优路径的情况下，使用动态加权来缩短A*搜索的时间
        其原则为，在搜索开始时，快速到达目的地所在区域更重要；在搜索结束时，得到到达目标的最佳路径更重要
        当h较大时，权重系数w也应该较大，此时A*算法会尽快向终点扩展，搜索速度很快但会错过最优路径；当h较小时，w也应该较小，此时A*算法会倾向于搜索最优路径而减慢搜索速度。
        如何找到最优选择，需要根据地图情况，多次调节参数
        """
        if d > 18:
            w = 3.0
        else:
            w = 1.0
        h = w * d

        #return d
        return h    # 传入2个点，返回h值

    # 函数功能：传入地图中最小处障碍物的坐标和index，得到全局范围下某个坐标
    def calc_grid_position(self, index, minpos):
        pos = index * self.reso + minpos
        return pos

    # 函数功能：计算xy坐标函数，传入position,min_pos，返回x/y坐标
    def calc_xyindex(self, position, min_pos):
        return round((position - min_pos) / self.reso)  # (当前节点-最小处的坐标)/分辨率=pos_index

    # 函数功能：计算栅格地图index，传入某个节点，返回当前节点的栅格index
    def calc_grid_index(self, node):
        return (node.y - self.miny) * self.xwidth + (node.x - self.minx)

    # 函数功能：验证是否为安全节点函数
    def verify_node(self, node):
        posx = self.calc_grid_position(node.x, self.minx)
        posy = self.calc_grid_position(node.y, self.miny)
        if posx < self.minx:
            return False
        elif posy < self.miny:
            return False
        elif posx >= self.maxx:
            return False
        elif posy >= self.maxy:
            return False

        if self.obmap[int(node.x)][int(node.y)]:
            return False
        return True

    # 函数功能：计算障碍物地图
    def calc_obstacle_map(self, ox, oy):
        self.minx = round(min(ox))    # 地图中的临界值
        self.miny = round(min(oy))
        self.maxx = round(max(ox))
        self.maxy = round(max(oy))
        print("minx:", self.minx)
        print("miny:", self.miny)
        print("maxx:", self.maxx)
        print("maxy:", self.maxy)

        self.xwidth = round((self.maxx - self.minx) / self.reso)
        self.ywidth = round((self.maxy - self.miny) / self.reso)
        print("xwidth:", self.xwidth)
        print("ywidth:", self.ywidth)

        self.obmap = [[False for i in range(int(self.ywidth))]
                       for i in range(int(self.xwidth))]
        for ix in range(int(self.xwidth)):
            x = self.calc_grid_position(ix, self.minx)
            for iy in range(int(self.ywidth)):
                y = self.calc_grid_position(iy, self.miny)
                for iox, ioy in zip(ox, oy):  #将ox,oy打包成元组，返回列表，并遍历
                    d = math.hypot(iox - x, ioy - y)
                    if d <= self.rr:          #代价小于车辆半径，可正常通过，不会穿越障碍物
                        self.obmap[ix][iy] = True
                        break

    @staticmethod
    def get_motion_model():
        # dx, dy, cost
        """
        改进点3：算法搜索的8个邻域，可改进为：5个、16个、32个、48个等(参考论文)
        """
        motion = [
                    [1, 0, 1],
                    [0, 1, 1],
                    [-1, 0, 1],
                    [0, -1, 1],
                    [1, 1, math.sqrt(2)],
                    [1, -1, math.sqrt(2)],
                    [-1, 1, math.sqrt(2)],
                    [-1, -1, math.sqrt(2)]

                    # [2,1,math.sqrt(5)],
                    # [1,2,math.sqrt(5)],
                    # [-2,1,math.sqrt(5)],
                    # [-1,2,math.sqrt(5)],
                    # [-2,-1,math.sqrt(5)],
                    # [-1,-2,math.sqrt(5)],
                    # [1,-2,math.sqrt(5)],
                    # [2,-1,math.sqrt(5)]

                    # [3,1,math.sqrt(10)],
                    # [1,3,math.sqrt(10)],
                    # [-3,1,math.sqrt(10)],
                    # [-1,3,math.sqrt(10)],
                    # [-3,-1,math.sqrt(10)],
                    # [-1,-3,math.sqrt(10)],
                    # [1,-3,math.sqrt(10)],
                    # [3,-1,math.sqrt(10)]

                    # [3,2,math.sqrt(13)],
                    # [2,3,math.sqrt(13)],
                    # [-3,2,math.sqrt(13)],
                    # [-2,3,math.sqrt(13)],
                    # [-3,-2,math.sqrt(13)],
                    # [-2,-3,math.sqrt(13)],
                    # [2,-3,math.sqrt(13)],
                    # [3,-2,math.sqrt(13)]
                  ]
        return motion
"""
改进点4：贝塞尔曲线平滑处理，对planning函数返回的path容器进行处理，可替换使用其他曲线方法
"""
#  贝塞尔曲线部分的三个函数
def comb(n, k):
    return factorial(n) // (factorial(k) * factorial(n-k))

def get_bezier_curve(points):
    n = len(points) - 1
    return lambda t: sum(comb(n, i)*t**i * (1-t)**(n-i)*points[i] for i in range(n+1))

def evaluate_bezier(points, total):
    bezier = get_bezier_curve(points)
    new_points = np.array([bezier(t) for t in np.linspace(0, 1, total)])
    return new_points[:, 0], new_points[:, 1]

# 主函数
def main():
    print(__file__ + '  start!')
    plt.title("improved astar by xiaoju")

    # start and goal position  [m]
    sx = -5.0
    sy = -5.0
    gx = 50
    gy = 50
    grid_size = 2.0
    robot_radius = 1.0

    # obstacle positions   在此更改地图
    ox, oy = [],[]
    for i in range(-10, 60):
        ox.append(i)
        oy.append(-10)      # y坐标-10的一行-10~60的坐标添加到列表并显示为黑色障碍物
    for i in range(-10, 60):
        ox.append(i)
        oy.append(60)       # y坐标60的一行-10~60的坐标添加到列表并显示为黑色障碍物
    for i in range(-10, 61):
        ox.append(-10)
        oy.append(i)        # x坐标-10的一列-10~61的坐标添加到列表并显示为黑色障碍物
    for i in range(-10, 61):
        ox.append(60)
        oy.append(i)        # x坐标60的一列-10~61的坐标添加到列表并显示为黑色障碍物
    for i in range(-10, 40):
        ox.append(20)
        oy.append(i)        # x坐标20的一列-10~40的坐标添加到列表并显示为黑色障碍物
    for i in range(0, 40):
        ox.append(40)
        oy.append(60 - i)   # x坐标40的一列20~60的坐标添加到列表并显示为黑色障碍物

    if show_animation:
        plt.plot(ox,oy,".k")  # 黑色.       障碍物
        plt.plot(sx,sy,"og")  # 绿色o       开始坐标
        plt.plot(gx,gy,"xb")  # 蓝色x       目标点
        plt.grid(True)
        plt.axis('equal')  # 保持栅格的横纵坐标刻度一致

    a_star = AStarPlanner(ox, oy, grid_size ,robot_radius)   # grid_size=reso
    pathx, pathy = a_star.planning(sx, sy, gx, gy)           # 开始与结束的坐标传入函数进行处理后，得到pathx,pathy：最终规划出的路径坐标

    # 贝塞尔曲线的控制点，为了方便更改，可根据出图效果调整
    points = np.array([[pathx[0], pathy[0]], [pathx[1], pathy[1]], [pathx[2], pathy[2]],
                        [pathx[3], pathy[3]],[pathx[4], pathy[4]],[pathx[5], pathy[5]],
                        [pathx[6], pathy[6]],[pathx[7], pathy[7]],[pathx[8], pathy[8]],
                        [pathx[9], pathy[9]],[pathx[10], pathy[10]],[pathx[11], pathy[11]],
                        [pathx[12], pathy[12]],[pathx[13], pathy[13]],[pathx[14], pathy[14]],
                        [pathx[15], pathy[15]]])
    points1 = np.array([[pathx[15], pathy[15]], [pathx[16], pathy[16]],[pathx[17], pathy[17]]])
    points2 = np.array([[pathx[17], pathy[17]],[pathx[18], pathy[18]], [pathx[19], pathy[19]], [pathx[20], pathy[20]],
                        [pathx[21], pathy[21]],[pathx[22], pathy[22]],[pathx[23], pathy[23]],
                        [pathx[24], pathy[24]],[pathx[25], pathy[25]],[pathx[26], pathy[26]],
                        [pathx[27], pathy[27]]])
    points3 = np.array([[pathx[27], pathy[27]],[pathx[28], pathy[28]],[pathx[29], pathy[29]]])
    points4 = np.array([[pathx[29], pathy[29]],[pathx[30], pathy[30]], [pathx[31], pathy[31]], [pathx[32], pathy[32]],
                        [pathx[33], pathy[33]],[pathx[34], pathy[34]],[pathx[35], pathy[35]],
                        [pathx[36], pathy[36]],[pathx[37], pathy[37]],[pathx[38], pathy[38]],
                        [pathx[39], pathy[39]],[pathx[40], pathy[40]],[pathx[41], pathy[41]],
                        [pathx[42], pathy[42]],[pathx[43], pathy[43]],[pathx[44], pathy[44]],
                        [pathx[45], pathy[45]],[pathx[46], pathy[46]],[pathx[47], pathy[47]],
                        [pathx[48], pathy[48]],[pathx[49], pathy[49]],[pathx[50], pathy[50]],
                        [pathx[51], pathy[51]],[pathx[52], pathy[52]]])

    bx, by = evaluate_bezier(points, 50)
    bx1, by1 = evaluate_bezier(points1, 50)
    bx2, by2 = evaluate_bezier(points2, 50)
    bx3, by3 = evaluate_bezier(points3, 50)
    bx4, by4 = evaluate_bezier(points4, 50)

    if show_animation:
        plt.plot(pathx, pathy, "-r")  # 红色线 最终路径
        plt.plot(bx, by, 'b-')        # 蓝色线 贝塞尔曲线
        plt.plot(bx1, by1, 'b-')
        plt.plot(bx2, by2, 'b-')
        plt.plot(bx3, by3, 'b-')
        plt.plot(bx4, by4, 'b-')

        plt.show()
        plt.pause(0.001)   # 动态显示

if __name__ == '__main__':
    main()


import argparse
import concurrent.futures
import logging
import subprocess
import sys
from pathlib import Path
from sys import argv

# from geoalchemy2 import shape
import geoalchemy2
import geojson
from codetiming import Timer
from cpuinfo import get_cpu_info
from pandas import DataFrame
from shapely import wkb
from shapely.geometry import shape
from sqlalchemy import MetaData, cast, column, create_engine, select, table, text
from sqlalchemy.dialects.postgresql import JSONB, insert
from sqlalchemy.engine.base import Connection
from sqlalchemy.orm import sessionmaker
from sqlalchemy_utils import create_database, database_exists

# Find the other files for this project
import osm_rawdata as rw
import osm_rawdata.db_models
from osm_rawdata.db_models import Base
from osm_rawdata.overture import Overture
from osm_rawdata.postgres import uriParser

rootdir = rw.__path__[0]

# Instantiate logger
log = logging.getLogger("osm-rawdata")

# The number of threads is based on the CPU cores
info = get_cpu_info()
cores = info["count"]

def importThread(
    data: list,
    db: Connection,
):
    """Thread to handle importing

    Args:
        data (list): The list of tiles to download
        db (Connection): A database connection
    """
    # log.debug(f"In importThread()")
    # timer = Timer(text="importThread() took {seconds:.0f}s")
    # timer.start()
    ways = table(
        "ways_poly",
        column("id"),
        column("user"),
        column("geom"),
        column("tags"),
    )

    nodes = table(
        "nodes",
        column("id"),
        column("user"),
        column("geom"),
        column("tags"),
    )

    nodes = table(
        "ways_line",
        column("id"),
        column("user"),
        column("geom"),
        column("tags"),
    )

    index = 0

    for feature in data:
        # log.debug(feature)
        index -= 1
        entry = dict()
        tags = feature["properties"]
        tags["building"] = "yes"
        entry["id"] = index
        ewkt = shape(feature["geometry"])
        geom = wkb.dumps(ewkt)
        type = ewkt.geom_type
        scalar = select(cast(tags, JSONB)).scalar_subquery()

        if type == "Polygon":
            sql = insert(ways).values(
                # id = entry['id'],
                geom=geom,
                tags=scalar,
            )
        elif type == "Point":
            sql = insert(nodes).values(
                # id = entry['id'],
                geom=geom,
                tags=scalar,
            )

        db.execute(sql)
        # db.commit()

def parquetThread(
    data: DataFrame,
    db: Connection,
):
    """Thread to handle importing

    Args:
        data (list): The list of tiles to download
        db (Connection): A database connection
    """
    timer = Timer(text="parquetThread() took {seconds:.0f}s")
    timer.start()
    ways = table(
        "ways_poly",
        column("id"),
        column("user"),
        column("geom"),
        column("tags"),
    )

    nodes = table(
        "nodes",
        column("id"),
        column("user"),
        column("geom"),
        column("tags"),
    )

    lines = table(
        "ways_line",
        column("id"),
        column("user"),
        column("geom"),
        column("tags"),
    )

    index = -1
    log.debug(f"There are {len(data)} entries in the data")
    if len(data) == 0:
        return

    overture = Overture()
    for index in data.index:
        feature = data.loc[index]
        dataset = feature["sources"][0]["dataset"]
        if dataset == "OpenStreetMap" or dataset == "Microsoft ML Buildings":
            continue
        tags = overture.parse(feature)
        geom = feature["geometry"]
        hex = wkb.loads(geom, hex=True)
        gdata = geoalchemy2.shape.from_shape(hex, srid=4326, extended=True)
        # geom_type = wkb.loads(geom).geom_type
        scalar = select(cast(tags["properties"], JSONB)).scalar_subquery()
        sql = None
        if hex.geom_type == "Polygon":
            sql = insert(ways).values(
                # osm_id = entry['osm_id'],
                geom=bytes(gdata.data),
                tags=scalar,
            )
        elif hex.geom_type == "MultiPolygon":
            gdata = geoalchemy2.shape.from_shape(hex.convex_hull, srid=4326, extended=True)
            sql = insert(ways).values(
                geom=bytes(gdata.data),
                tags=scalar,
            )
        elif hex.geom_type == "Point":
            sql = insert(nodes).values(
                # osm_id = entry['osm_id'],
                geom=bytes(gdata.data),
                tags=scalar,
            )
        elif hex.geom_type == "LineString":
            sql = insert(lines).values(
                # osm_id = entry['osm_id'],
                geom=bytes(gdata.data),
                tags=scalar,
            )
        else:
            log.error(f"geometry type {geom_type} is unsupported!")
            continue

        index -= 1
        db.execute(sql)
        # db.commit()
        # print(f"FIXME2: {entry}")
    timer.stop()

class MapImporter(object):
    def __init__(
        self,
        dburi: str,
    ):
        """This is a class to setup a local database for OSM data.

        Args:
            dburi (str): The URI string for the database connection

        Returns:
            (OsmImporter): An instance of this class
        """
        self.dburi = dburi
        self.db = None
        self.connections = list()
        for thread in range(0, cores + 1):
            engine = create_engine(f"postgresql://{self.dburi}", echo=False)
            if not database_exists(engine.url):
                create_database(engine.url)
            self.connections.append(engine.connect())
            sessionmaker(autocommit=False, autoflush=False, bind=engine)

            if thread == 0:
                meta = MetaData()
                meta.create_all(engine)

                # if dburi:
                # self.uri = uriParser(dburi)
                # engine = create_engine(f"postgresql://{self.dburi}", echo=True)
                # if not database_exists(engine.url):
                #     create_database(engine.url)
                # self.db = engine.connect()

                # Add the extension we need to process the data
                sql = text(
                    "CREATE EXTENSION IF NOT EXISTS postgis; CREATE EXTENSION IF NOT EXISTS hstore;CREATE EXTENSION IF NOT EXISTS dblink;"
                )
                self.connections[0].execute(sql)

                Base.metadata.create_all(bind=engine)

                sessionmaker(autocommit=False, autoflush=False, bind=engine)

            # Create indexes to improve peformance
            # sql = text("cluster ways_poly using ways_poly_geom_idx;")
            # self.db.execute(sql)
            # sql("create index on ways_poly using gin(tags)")
            # self.db.execute(sql)
            # self.db.commit()

    def importOSM(
        self,
        infile: str,
    ):
        """Import an OSM data file into a postgres database.

        Args:
            infile (str): The file to import
        Returns:
            (bool): Whether the import finished sucessfully
        """
        # osm2pgsql --create -d nigeria --extra-attributes --output=flex --style raw.lua nigeria-latest-internal.osm.pbf
        uri = uriParser(self.dburi)
        result = subprocess.run(
            [
                "osm2pgsql",
                "--create",
                "-d",
                f"{uri['dbname']}",
                "--extra-attributes",
                "--output=flex",
                "--style",
                f"{rootdir}/raw_with_ref.lua",
                f"{infile}",
            ]
        )
        result.check_returncode()

    def importParquet(
        self,
        infile: str,
    ):
        """Import an Overture parquet data file into a postgres database.

        Args:
            infile (str): The file to import

        Returns:
            (bool): Whether the import finished sucessfully
        """
        # spin = PixelSpinner(f"Processing {infile}...")
        timer = Timer(text="importParquet() took {seconds:.0f}s")
        timer.start()
        overture = Overture(infile)

        connections = list()
        for thread in range(0, cores + 1):
            engine = create_engine(f"postgresql://{self.dburi}", echo=False)
            if not database_exists(engine.url):
                create_database(engine.url)
            connections.append(engine.connect())
            sessionmaker(autocommit=False, autoflush=False, bind=engine)

            if thread == 0:
                meta = MetaData()
                meta.create_all(engine)

        # A chunk is a group of threads
        entries = len(overture.data)
        log.debug(f"There are {entries} entries in {infile}")
        chunk = round(entries / cores)

        if entries <= chunk:
            result = parquetThread(overture.data, connections[0])
            timer.stop()
            return True

        index = 0
        with concurrent.futures.ProcessPoolExecutor(max_workers=cores) as executor:
            block = 0
            while block <= entries:
                if len(overture.data[block : block + chunk]) == 0:
                    continue
                log.debug("Dispatching Block %d:%d" % (block, block + chunk))
                result = executor.submit(parquetThread, overture.data[block : block + chunk], connections[index])
                block += chunk
                index += 1
            executor.shutdown()
        timer.stop()

    def importGeoJson(
        self,
        infile: str,
    ):
        """Import a GeoJson data file into a postgres database.

        Args:
            infile (str): The file to import

        Returns:
            (bool): Whether the import finished sucessfully
        """
        # load the GeoJson file
        file = open(infile, "r")
        # size = os.path.getsize(infile)
        # for line in file.readlines():
        #    print(line)
        data = geojson.load(file)

        future = None
        result = None
        index = 0
        connections = list()

        timer = Timer(text="importGeoJson() took {seconds:.0f}s")
        timer.start()

        # A chunk is a group of threads
        entries = len(data["features"])
        chunk = round(entries / cores)

        # For small files we only need one thread
        if entries <= chunk:
            result = importThread(data["features"], self.connections[0])
            timer.stop()
            return True

        with concurrent.futures.ThreadPoolExecutor(max_workers=cores) as executor:
            block = 0
            while block <= entries:
                log.debug("Dispatching Block %d:%d" % (block, block + chunk))
                result = executor.submit(importThread, data["features"][block : block + chunk], self.connections[index])
                block += chunk
                index += 1
            executor.shutdown()
        timer.stop()

        return True

def main():
    """This main function lets this class be run standalone by a bash script."""
    parser = argparse.ArgumentParser(
        prog="config",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        description="Import data into a postgres database",
        epilog="""
        This should only be run standalone for debugging purposes.
        """,
    )
    parser.add_argument("-v", "--verbose", nargs="?", const="0", help="verbose output")
    parser.add_argument("-i", "--infile", required=True, help="Input data file")
    parser.add_argument("-u", "--uri", required=True, help="Database URI")
    args = parser.parse_args()

    if len(argv) <= 1:
        parser.print_help()
        quit()

    # if verbose, dump to the terminal.
    if args.verbose is not None:
        log.setLevel(logging.DEBUG)
        ch = logging.StreamHandler(sys.stdout)
        ch.setLevel(logging.DEBUG)
        formatter = logging.Formatter("%(threadName)10s - %(name)s - %(levelname)s - %(message)s")
        ch.setFormatter(formatter)
        log.addHandler(ch)

    # Create the database
    mi = MapImporter(args.uri)

    path = Path(args.infile)

    # And populate it with data
    if path.suffix == ".osm" or path.suffix == ".pbf":
        mi.importOSM(args.infile)
    elif path.suffix == ".geojson":
        mi.importGeoJson(args.infile)
    elif path.suffix == ".parquet":
        # Newer data from Overture has a suffix
        mi.importParquet(args.infile)
    else:
        # Older data from Overture lacked the suffix
        mi.importParquet(args.infile)
    log.info(f"Imported {args.infile} into {args.uri}")

if __name__ == "__main__":
    """This is just a hook so this file can be run standalone during development."""
    main()


# coding: utf-8
# some shit I had to do in order to change a 2 to a 1 in my hand-pruned network :P
# (saving this just in case I have to do something similar again)
from asnets import interactive_network as inet
ni = inet.NetworkInstantiator('./sparse/ttw-weights-hand-pruned.pkl', use_lm_cuts=False)
ni.weight_manager
import tensorflow as tf; import numpy as np
sess = tf.Session()
sess.run(tf.global_variables_initializer())
with sess.as_default():
    w_state = ni.weight_manager.__getstate__()
second_act_layer = w_state['act_weights_np'][1]
second_act_layer = {k.schema_name: v for k, v in second_act_layer.items()}
second_act_layer['move_car'][0][0,3,1] = 1
tf.reset_default_graph()
sess.close()
sess = tf.Session()
weights.__setstate__(w_state)
ni.weight_manager.__setstate__(w_state)
sess.run(tf.global_variables_initializer())
with sess.as_default():
    ni.weight_manager.save('./sparse/ttw-weights-hand-pruned-simpler.pkl')


from ..questions.models import Category

def get_results(response):
    results = []

    for category in Category.objects.all():
        result = {}
        total = 0
        questions = category.questions.values_list('pk', flat=True)
        answers = response.answers.filter(question_id__in=questions)
        for answer in answers:
            total = total + int(answer.body)

        total = round(total/questions.count(), 2)

        result["total"] = total
        result["name"] = category.name
        result["description"] = category.description

        print(total)

        if total >= 5:
            result["text"] = category.text_1

        if total > 2.5 and total < 5:
            result["text"] = category.text_2

        if total <= 2.5:
            result["text"] = category.text_3

        results.append(result)

    return results


import os
import pickle
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# load MCMC output and thin
species_codes = {1: 'Pst', 2: 'Pst', 3: 'Pgr', 4: 'Pgr', 6: 'Pst',
                 7: 'Aru', 9: 'Aru', 11: 'Aru', 12: 'Pst', 14: 'Pst',
                 17: 'Pst', 19: 'Pst', 21: 'Aru', 22: 'Pgr', 24: 'Aru',
                 26: 'Aru', 27: 'Pgr', 28: 'Aru', 29: 'Aru', 31: 'Bpa',
                 32: 'Bpa', 34: 'Pgr', 35: 'Bpa', 38: 'Bpa', 41: 'Bpa'}

# helper functions
def hide_current_axis(*args, **kwds):
    plt.gca().set_visible(False)

def f(species_code, plot=False, save=False):
    ts = pickle.load(open('../../Data/UMB_trace/Gil_v2/{}.pickle'\
                          .format(species_code), 'rb'))
    ts['kxmax/g1'] = 10**ts['kxmax_log10']/10**ts['g1_log10']
    ts['kxmax/alpha'] = 10**ts['kxmax_log10']/10**ts['alpha_log10']
    latex = [r'$c$', '$\\psi_{x50}$', '$k_{xmax}/L/g_1$', r'$k_{xmax}/\alpha$']
    df_thinned = {}
    for key in ts:
        #print(np.median(ts[key]))
        df_thinned[key] = [item for index, item in enumerate(ts[key])\
                           if index % 10 == 0]
    df_thinned = pd.DataFrame.from_dict(data=df_thinned, orient='columns')
    df_thinned = df_thinned.drop(['g1_log10', 'kxmax_log10', 'alpha_log10'],\
                                 axis=1)
    df_thinned.rename(columns=dict(zip(df_thinned.columns, latex)),\
                      inplace=True)
    #print(df_thinned[latex[-1]].describe(percentiles=[0.01]))
    # figure
    if plot:
        #sns.set(font_scale=2)
        sns.set_context('paper', rc={'axes.labelsize': 24})
        plt.ioff()
        g = sns.PairGrid(data=df_thinned, vars=latex, diag_sharey=False)
        g.fig.set_size_inches(12, 12)
        g = g.map_lower(plt.scatter, s=1)
        g = g.map_diag(plt.hist)
        #g = g.map_diag(sns.kdeplot, lw=3, legend=False)
        #g = g.map_upper(plt.scatter, s=1)
        g.map_upper(hide_current_axis)
        if save:
            g.savefig('../../Figures/Figure_correlation_Gil_v2_{}.png'\
                      .format(species_code), bbox_inches="tight")

# figures
#species_codes = [y+'_'+str(x) for x, y in species_codes.items()]
species_codes = ['Aru_24']
for species_code in species_codes:
    if not os.path.exists('../../Data/UMB_trace/Gil_v2/{}.pickle'\
                          .format(species_code)):
        continue
    f(species_code, plot=True, save=True)
    print(species_code)


import math

def solution(n):
  sum = 0
  if n < 10:
    return n
  hours = math.floor(n / 60)
  mins = n - hours * 60

  for digit in str(hours):
    sum += int(digit)

  for digit in str(mins):
    sum += int(digit)
  return sum

if __name__ == '__main__':
  sum = solution(240)
  print(sum)


# 2869 달팽이는 올라가고 싶다
"""
높이가 v인 나무 막대를 달팽이가 올라간다.
낮에는 a미터 올라가지만, 밤에는 b미터 내려간다.
정상에 오른 후에는 미끄러지지 않는다.
정상에 오르는데 며칠이 걸리는지 구하시오.

첫째 줄에 세 정수가 a,b,v가 공백으로 구분되어 주어진다.
며칠이 걸리는지 출력한다.

접근법
1. 하루에 올라가는 높이는 a-b이다.
2. 단, 아침에 올라가는 데 성공하는 경우 v-b만큼을 오른 것이다.
3. 즉, v-b % a-b 가 0이면, 아침에 올라가는 데 성공한 것이다.
- if
    4. v-b % a-b != 0 일때, days는 ((v-b)//(a-b)) + 1이다.
- else
    5. v-b % a-b == 0 일때, days는 (v-b)//(a-b)이다.
6. days를 출력한다.

숙지가 필요한 항목
1. 경우의 수를 철저하게 나누자.

"""
a,b,v = map(int, input().split())
days = 0
if (v-b) % (a-b) != 0:
    days = ((v-b) // (a-b)) + 1
else:
    days = (v-b) // (a-b)
print(days)

python/baekjoon/8. 기본 수학 1/2869 달팽이는 올라가고 싶다.py

2869 달팽이는 올라가고 싶다.py


from dataclasses import dataclass

import dataclasses
from typing import Iterable, Self

import json
import logging
import pickle

from utils import verify, sign

@dataclass
class TransInput:
    public_key: str  # PEM
    amount: int

@dataclass
class TransOutput:
    public_key: str  # PEM
    amount: int

@dataclass(frozen=True, slots=True)
class Transaction:
    input: TransInput | None
    output: TransOutput
    number_in_chain: int

    def serialized_input_output(self) -> str:
        inp = self.input
        ou = self.output
        separators = (",", ":")
        output_json_dump = json.dumps(
            obj=dataclasses.asdict(ou), sort_keys=True, separators=separators
        )

        if inp:
            inp_json_dump = json.dumps(
                obj=dataclasses.asdict(inp), sort_keys=True, separators=separators
            )
            return inp_json_dump + "|" + output_json_dump
        else:
            return "|" + output_json_dump

@dataclass(frozen=True, slots=True)
class TransactionSigned(Transaction):
    signature: str

    @classmethod
    def from_transaction(cls, t: Transaction, private_key):
        serialized = t.serialized_input_output().encode()
        signature = sign(serialized, private_key).hex()
        return cls(t.input, t.output, t.number_in_chain, signature)

    def is_valid(self) -> bool:
        serialized = self.serialized_input_output()
        key = self.input.public_key if self.input else self.output.public_key
        if self.output.amount < 0:
            return False
        if self.input and self.input.amount != self.output.amount:
            return False
        try:
            verify(serialized, self.signature.encode(), key)
            return True
        except Exception:
            return False

    # SERIALIZATION
    def pack_transaction(self) -> str:
        return pickle.dumps(self).decode("latin-1")

    # DESERIALIZATION
    @classmethod
    def unpack_transaction(cls, packed_transaction: str):
        new_obj = pickle.loads(packed_transaction.encode("latin-1"))
        if isinstance(new_obj, Self):
            return new_obj
        else:
            raise Exception("Invalid object instance unpickled")

def eval_balance(
    transactions: Iterable[TransactionSigned], accounts: dict[str, int], miner_fee: int
):
    for trans in transactions:
        input = trans.input
        output = trans.output
        # check signaged
        # check if amount is the same as fee
        if not trans.is_valid():
            raise Exception("Transaction not valid")

        if not input:
            # mined
            if output.amount == miner_fee:
                if not accounts.get(output.public_key):
                    accounts[output.public_key] = miner_fee
                else:
                    accounts[output.public_key] += miner_fee
            else:
                raise Exception("Fee different than miner fee")
        else:
            payer_address = input.public_key
            payee_address = output.public_key
            expense = input.amount
            if expense < 0:
                raise Exception("Input amount cant be a negative number")
            payer_account_balance = accounts.get(payer_address)
            if not payer_account_balance:
                raise Exception("Non existing payer attempting to transfer")
            else:
                if payer_account_balance < expense:
                    raise Exception("Spending above amount")
                else:
                    if not accounts.get(output.public_key):
                        # logging.warning("New or dead wallet")
                        accounts[payee_address] = 0
                    accounts[payee_address] += expense
                    accounts[payer_address] -= expense
    return accounts


# 状态：以arr[x]结尾的最大等差序列为dp  (x, y 是 index, arr[x], arr[y] 是 value，dp[x], dp[y] 是 欲求值)
# 转移: if arr[x] - arr[y] == diff(y < x): dp[x] = max(dp[y] + 1, dp[x])

def func():
    arr = [int(x) for x in input().split(",")]
    diff = int(input())

    dp = [1] * len(arr)

    x = 0
    while x < len(arr):
        y = 0
        while y < x:
            if arr[x] - arr[y] == diff:
                dp[x] = max(dp[x], dp[y] + 1)
            y += 1
        x += 1

    print(max(dp))

func()


import numpy as np

import torch
import torch.nn.functional as F
from torch.autograd import Variable, grad

from foolbox.adversarial import Adversarial

def cw_loss(logits, y):
    one_hot = torch.zeros_like(logits)
    one_hot.scatter_(1, y.view(-1, 1), 1)
    correct_logit = (logits * one_hot).sum(1)
    worst_wrong_logit = logits[one_hot == 0].view(one_hot.size(0), -1).max(1)[0]

    adv_margin = correct_logit - worst_wrong_logit
    return -F.relu(adv_margin + 50).mean()

def tensor_clamp(x, min_x, max_x):
    x[x < min_x] = min_x[x < min_x]
    x[x > max_x] = max_x[x > max_x]
    return x

def manual_fgs(model, x, y, eps=0.1, clamp=True):
    model.zero_grad()
    x.requires_grad = True
    pred = model(x)
    loss = cw_loss(pred, y)

    g = torch.sign(grad(loss, x)[0])
    adv_x = x + g * eps
    if clamp:
        adv_x.clamp_(0, 1)
    return adv_x, model(adv_x).argmax(1), pred.argmax(1)

def manual_pgd(model, x, y, stepsize=0.01, eps=0.1, iters=100, rand_start=True, clamp=True):
    model.zero_grad()
    x_adv = torch.zeros_like(x)
    x_adv.copy_(x)

    x_min = (x.detach() - eps)
    x_max = (x.detach() + eps)
    if clamp:
        x_min.clamp_(0, 1)
        x_max.clamp_(0, 1)

    if rand_start:
        rand = torch.zeros_like(x)
        rand.uniform_(-eps, eps)
        x_adv = x_adv + rand
    x_adv.requires_grad = True
    for i in range(iters):
        model.zero_grad()
        if x_adv.grad:
            x_adv.grad.zero_()
        pred = model(x_adv)
        # loss = F.cross_entropy(pred, y)
        loss = cw_loss(pred, y)
        g = torch.sign(grad(loss, x_adv)[0])
        x_adv = x_adv + g * stepsize
        x_adv = tensor_clamp(x_adv, x_min, x_max)
    return x_adv, model(x_adv).argmax(1), model(x).argmax(1)

def perform_attack(attack, model, input_adv, cuda=True, **attack_kwargs):
    adversarial_np = attack(input_adv, **attack_kwargs)
    image = torch.Tensor(input_adv.original_image)
    label = input_adv.original_class

    if adversarial_np is None:
        # Attack failed.
        return adversarial_np, 0.0, 0.0, 0.0
    else:
        # Check if attack was successful.
        adversarial = Variable(torch.Tensor(adversarial_np))
        if cuda:
            adversarial = adversarial.cuda()
            image = image.cuda()

        pred = lambda x: F.softmax(model.forward(x.unsqueeze(0)), dim=1).max(1)[1].data[0]

        # Compute adversarial MSE.
        adv_mse = torch.pow(adversarial - Variable(image), 2).mean().item()
        adv_inf = torch.max(torch.abs(adversarial - image))
        adv_inf = adv_inf.item()

        if pred(adversarial).item() != label and adv_inf > 0.0:
            success = 1.0
        else:
            success = 0.0

        return adversarial_np, success, adv_mse, adv_inf

def batch_attack(attack, model, criterion, x, y, attack_config={}, distance=None):
    adv_ex = []
    adv_targets = []
    ret_success = []
    ret_adv_mse = []
    ret_adv_inf = []

    for i in range(x.shape[0]):
        is_cuda = x.is_cuda
        input_adv = Adversarial(model, criterion, x[i].cpu().numpy(), y[i], distance=distance)
        adv, success, adv_mse, adv_inf = perform_attack(attack, model._model, input_adv, cuda=is_cuda, **attack_config)
        if adv is not None:
            adv_targets.append(y[i])
            adv_ex.append(adv)
        ret_success.append(success)
        ret_adv_mse.append(adv_mse)
        ret_adv_inf.append(adv_inf)
    return torch.Tensor(np.array(adv_ex)), torch.LongTensor(np.array(adv_targets)), torch.Tensor(
        ret_success), torch.Tensor(ret_adv_mse), torch.Tensor(ret_adv_inf)


# Corporation: HKCLR
# Project: AutoStore picking robots
# Author: Chang Liu
# Some codes are refered from https://github.com/facebookresearch/pycls

"""MMDet library's model training, testing, etc. functions.
"""

import cv2
import numpy as np
import mmcv
import os
import PIL.Image as pil_image
import torch
import time
from mmcv import Config
from mmcv.runner import load_checkpoint
from mmcv.parallel import MMDataParallel
from mmdet.apis import set_random_seed, init_detector, inference_detector
from mmdet.core import encode_mask_results
from mmdet.datasets import (
    build_dataset,
    build_dataloader,
    replace_ImageToTensor
)
from mmdet.models import build_detector
from mmdet.apis import train_detector, single_gpu_test
from typing import Optional, Tuple, List, NewType, Dict, Any, Callable
from pathlib import Path
from PIL.Image import Image
from autostore.core.logging import get_logger, setup_logging
from autostore.core.io import load_img_paths
from autostore.datasets.pre_process import (
    rsz_imgs_from_csv_info,
    rsz_paste_imgs_from_csv_info
)
from autostore.datasets.post_process import (
    restore_bboxes,
    restore_seg_mask,
    remove_irregular_bboxes,
    remove_irregular_seg_masks
)

EvaluateResultType = NewType(
    "EvaluateResultType",
    List[Tuple[List[np.ndarray], List[List[Dict[str, Any]]]]]
)

def train_model(
        mmdet_cfg: str,
        weight_path: str,
        output_dir: str
    ) -> None:
    """Train a mmdet model with provided config file and pretrained weight,
    and output the trained weight to output_dir.

    Args:
        mmdet_cfg (str):
            MMDet config file path.
        weight_path (str):
            Pretrained weight path.
        output_dir (str):
            The path where trained weight will be save at.

    Returns:
        None
    """
    os.makedirs(output_dir, exist_ok=True)
    setup_logging(os.path.join(output_dir, "train.log"))
    _logger = get_logger(__name__)
    cfg = Config.fromfile(mmdet_cfg)
    cfg.load_from = weight_path
    _logger.info(f"Loaded config file from {mmdet_cfg}.")
    try:
        # This del operation is to avoid exception that exclusively happened
        # on loading mask2former_r50 models
        del cfg.data.val.ins_ann_file
        del cfg.data.test.ins_ann_file
    except:
        pass
    cfg.device = "cuda"
    cfg.work_dir = output_dir
    cfg.seed = 0
    set_random_seed(0, deterministic=False)
    cfg.gpu_ids = [0]

    datasets = [build_dataset(cfg.data.train)]
    model = build_detector(cfg.model)
    model.CLASSES = datasets[0].CLASSES
    mmcv.mkdir_or_exist(os.path.abspath(cfg.work_dir))
    train_detector(model, datasets, cfg, distributed=False, validate=True)

    try:
        checkpoint_name = 'epoch_'+str(cfg.runner.max_epochs)
    except:
        checkpoint_name = 'iter_'+str(cfg.runner.max_iters)
    checkpoint_path = os.path.join(cfg.work_dir, f"{checkpoint_name}.pth")
    checkpoint = torch.load(checkpoint_path)
    os.remove(checkpoint_path)
    meta = checkpoint['meta']
    checkpoint['optimizer'] = None
    weights = checkpoint['state_dict']
    state_dict = {"state_dict": weights, "meta": meta}
    new_checkpoint_path = os.path.join(cfg.work_dir, f"{checkpoint_name}_small.pth")
    torch.save(state_dict, new_checkpoint_path)

def test_imgs(
        mmdet_cfg: str,
        weight_path: str,
        show_score_thr: float,
        output_dir: Optional[str] = None,
        font_size:int = 10,
    ) -> None:
    os.makedirs(output_dir, exist_ok=True)
    setup_logging(os.path.join(output_dir, "test.log"))
    _logger = get_logger(__name__)
    cfg = Config.fromfile(mmdet_cfg)
    try:
        # This del operation is to avoid exception that exclusively happened
        # on loading mask2former_r50 models
        del cfg.data.val.ins_ann_file
        del cfg.data.test.ins_ann_file
    except:
        pass

    if 'pretrained' in cfg.model:
        cfg.model.pretrained = None
    elif 'init_cfg' in cfg.model.backbone:
        cfg.model.backbone.init_cfg = None

    if cfg.model.get('neck'):
        if isinstance(cfg.model.neck, list):
            for neck_cfg in cfg.model.neck:
                if neck_cfg.get('rfp_backbone'):
                    if neck_cfg.rfp_backbone.get('pretrained'):
                        neck_cfg.rfp_backbone.pretrained = None
        elif cfg.model.neck.get('rfp_backbone'):
            if cfg.model.neck.rfp_backbone.get('pretrained'):
                cfg.model.neck.rfp_backbone.pretrained = None

    # Set seed thus the results are more reproducible
    cfg.seed = 0
    set_random_seed(0, deterministic=False)
    cfg.gpu_ids = [0]

    # in case the test dataset is concatenated
    if isinstance(cfg.data.test, dict):
        cfg.data.test.test_mode = True
        samples_per_gpu = cfg.data.test.pop('samples_per_gpu', 1)
        if samples_per_gpu > 1:
            # Replace 'ImageToTensor' to 'DefaultFormatBundle'
            cfg.data.test.pipeline = replace_ImageToTensor(
                cfg.data.test.pipeline)
    elif isinstance(cfg.data.test, list):
        for ds_cfg in cfg.data.test:
            ds_cfg.test_mode = True
        samples_per_gpu = max(
            [ds_cfg.pop('samples_per_gpu', 1) for ds_cfg in cfg.data.test])
        if samples_per_gpu > 1:
            for ds_cfg in cfg.data.test:
                ds_cfg.pipeline = replace_ImageToTensor(ds_cfg.pipeline)

    # Build dataset
    dataset = build_dataset(cfg.data.test)
    data_loader = build_dataloader(
            dataset,
            samples_per_gpu=samples_per_gpu,
            workers_per_gpu=cfg.data.workers_per_gpu,
            dist=False, #distributed
            shuffle=False)

    # Build the detector
    cfg.model.train_cfg = None
    model = build_detector(cfg.model, test_cfg=cfg.get('test_cfg'))
    checkpoint = load_checkpoint(model, weight_path, map_location='cpu')

    if 'CLASSES' in checkpoint.get('meta', {}):
        model.CLASSES = checkpoint['meta']['CLASSES']
    else:
        model.CLASSES = dataset.CLASSES

    model = MMDataParallel(model, device_ids=cfg.gpu_ids)
    outputs = single_gpu_test(
        model,
        data_loader,
        False,
        None,
        show_score_thr,
        font_size
    )
    kwargs = {}
    eval_kwargs = cfg.get('evaluation', {}).copy()
    # hard-code way to remove EvalHook args
    for key in ['interval', 'tmpdir', 'start',
        'gpu_collect', 'save_best', 'rule', 'dynamic_intervals']:
        eval_kwargs.pop(key, None)
    eval_kwargs.update(dict(metric = ["bbox", "segm"], **kwargs))
    metric = dataset.evaluate(outputs, **eval_kwargs)
    _logger.info(metric)
    return model, outputs

def rsz_and_test_imgs(
        mmdet_cfg: str,
        weight_path: str,
        show_score_thr: float,
        mode: str,
        input_size: Optional[Tuple[int, int]] = None,
        output_dir: Optional[str] = None,
        background_img_path: str = None,
    ) -> None:
    cfg = Config.fromfile(mmdet_cfg)
    test_img_dir = cfg.data.test.img_prefix
    test_ann_file = cfg.data.test.ann_file
    if mode == "rsz_inference_imgs":
        model, results = rsz_inference_imgs(
            test_img_dir,
            mmdet_cfg,
            weight_path,
            input_size,
            show_score_thr,
            output_dir
        )
    elif mode == "rsz_paste_inference_imgs":
        model, results = rsz_paste_inference_imgs(
            test_img_dir,
            mmdet_cfg,
            weight_path,
            background_img_path,
            show_score_thr,
            output_dir
        )
    test_dataset = build_dataset(cfg.data.test)
    kwargs = {}
    eval_kwargs = cfg.get('evaluation', {}).copy()
    # hard-code way to remove EvalHook args
    for key in ['interval', 'tmpdir', 'start',
        'gpu_collect', 'save_best', 'rule',
        'dynamic_intervals']:
        eval_kwargs.pop(key, None)
    eval_kwargs.update(dict(metric = ["bbox", "segm"], **kwargs))
    metric = test_dataset.evaluate(results, **eval_kwargs)
    print(metric)
    return model, results

def inference_imgs(
        img_dir: str,
        mmdet_cfg: str,
        weight_path: str,
        show_score_thr: float,
        output_dir: Optional[str] = None,
        show_font_size: Optional[int] = None,
        thickness: Optional[int] = None
    ) -> None:
    """Perform inference on images with a mmdet model.

    Args:
        img_dir (str):
            Image folder paths.
        mmdet_cfg (cfg):
            MMDet config file path.
        weight_path:
            Pretrained weight path.
        show_score_thr (float):
            BBox with score lower than this value will not show
            on inference result visualization.
        output_dir (Optional[str]):
            The path to save visualization results. if None, visualization
            results will not be saved.

    Returns:
        None
    """
    model = init_detector(mmdet_cfg, weight_path, device='cuda:0')
    time_deltas = []
    results = []
    for img_path, img_name, img_ext in load_img_paths(img_dir):
        img = cv2.imread(img_path)
        t1 = time.time()
        result = inference_detector(model, img)
        t2 = time.time()
        time_deltas.append(t2 - t1)
        results.append(result)
        if output_dir:
            os.makedirs(Path(output_dir), exist_ok=True)
            visual_save_path = os.path.join(output_dir, f"{img_name}_inf.{img_ext}")
            show_font_size = show_font_size if show_font_size else 10
            thickness = thickness if thickness else 2
            if show_font_size:
                model.show_result(
                    img_path,
                    result,
                    score_thr=show_score_thr,
                    out_file=visual_save_path,
                    font_size=show_font_size,
                    thickness = thickness
                )
    time_deltas = np.array(time_deltas)
    print(f"avg time consumed for inferencing {len(time_deltas)} images is {time_deltas.mean()}")
    return model, results

def rsz_inference_imgs(
        img_dir: str,
        mmdet_cfg: str,
        weight_path: str,
        input_size: Tuple[int, int],
        show_score_thr: float,
        output_dir: Optional[str] = None,
    ) -> EvaluateResultType:
    model = init_detector(mmdet_cfg, weight_path, device='cuda:0')
    time_deltas = []
    results = []
    i = 0
    for img_path, img, rsz_size in rsz_imgs_from_csv_info(img_dir, input_size):
        img = np.asarray(img).astype(np.uint8)
        t1 = time.time()
        result = inference_detector(model, img)
        t2 = time.time()
        time_deltas.append(t2 - t1)
        bboxes, seg_masks = result[0][0], result[1][0]
        org_bboxes = restore_bboxes(
            bboxes,
            rsz_size,
            input_size
        )
        valid_bbox_idx = remove_irregular_bboxes(
            org_bboxes,
            input_size,
            0.8
        )
        org_seg_masks = restore_seg_mask(
            seg_masks,
            rsz_size,
            input_size
        )
        valid_seg_mask_idx = remove_irregular_seg_masks(
            org_seg_masks,
            input_size,
            0.8
        )
        valid_idx = set(valid_bbox_idx).intersection(set(valid_seg_mask_idx))
        valid_org_bboxes = [org_bboxes[i] for i in valid_idx]
        valid_org_bboxes = np.concatenate(valid_org_bboxes, axis=0)
        valid_org_seg_masks = [org_seg_masks[i] for i in valid_idx]
        result[0][0] = valid_org_bboxes
        result[1][0] = valid_org_seg_masks
        if output_dir:
            try:
                os.makedirs(Path(output_dir), exist_ok=True)
                img_name, img_ext = Path(img_path).name.split(".")
                visual_save_path = os.path.join(output_dir, f"{img_name}_pred.{img_ext}")
                model.show_result(
                    img_path,
                    result,
                    score_thr=show_score_thr,
                    out_file=visual_save_path,
                    font_size=9
                )
            except Exception as e:
                print(e)
                print(img_path)
                print(valid_bbox_idx)
                print(valid_seg_mask_idx)

        result_ = [([valid_org_bboxes], [valid_org_seg_masks])]
        encoded_result = [(bbox_result, encode_mask_results(mask_result))
            for bbox_result, mask_result in result_]
        results.extend(encoded_result)
        i += 1

    time_deltas = np.array(time_deltas)
    _logger.info(f"avg time consumed for inferencing \
                {len(time_deltas)} images is {time_deltas.mean()}")
    return model, results

def rsz_paste_inference_imgs(
        img_dir: str,
        mmdet_cfg: str,
        weight_path: str,
        background_img_path: str,
        show_score_thr: float,
        output_dir: Optional[str] = None,
    ) -> EvaluateResultType:
    back_img = pil_image.open(background_img_path).convert("RGB")
    input_size = (back_img.height, back_img.width)
    model = init_detector(mmdet_cfg, weight_path, device='cuda:0')
    time_deltas = []
    results = []
    i = 0
    for img_path, img, rsz_size in rsz_paste_imgs_from_csv_info(img_dir, back_img):
        img = np.asarray(img).astype(np.uint8)
        t1 = time.time()
        result = inference_detector(model, img)
        t2 = time.time()
        time_deltas.append(t2 - t1)
        bboxes, seg_masks = result[0][0], result[1][0]
        org_bboxes = restore_bboxes(
            bboxes,
            rsz_size,
            input_size
        )
        valid_bbox_idx = remove_irregular_bboxes(
            org_bboxes,
            input_size,
            0.8
        )
        org_seg_masks = restore_seg_mask(
            seg_masks,
            rsz_size,
            input_size
        )
        valid_seg_mask_idx = remove_irregular_seg_masks(
            org_seg_masks,
            input_size,
            0.8
        )
        valid_idx = set(valid_bbox_idx).intersection(set(valid_seg_mask_idx))
        valid_org_bboxes = [org_bboxes[i] for i in valid_idx]
        valid_org_bboxes = np.concatenate(valid_org_bboxes, axis=0)
        valid_org_seg_masks = [org_seg_masks[i] for i in valid_idx]
        result[0][0] = valid_org_bboxes
        result[1][0] = valid_org_seg_masks
        if output_dir:
            try:
                os.makedirs(Path(output_dir), exist_ok=True)
                img_name, img_ext = Path(img_path).name.split(".")
                visual_save_path = os.path.join(output_dir, f"{img_name}_pred.{img_ext}")
                model.show_result(
                    img_path,
                    result,
                    score_thr=show_score_thr,
                    out_file=visual_save_path,
                    font_size=9
                )
            except Exception as e:
                print(e)
                print(img_path)
                print(valid_bbox_idx)
                print(valid_seg_mask_idx)

        result_ = [([valid_org_bboxes], [valid_org_seg_masks])]
        encoded_result = [(bbox_result, encode_mask_results(mask_result))
            for bbox_result, mask_result in result_]
        results.extend(encoded_result)
        i += 1

    time_deltas = np.array(time_deltas)
    _logger.info(f"avg time consumed for inferencing \
                {len(time_deltas)} images is {time_deltas.mean()}")
    return model, results


# n개의 숫자를 2진수로 변환하여, 1이 많은 갯수를 내림차순으로 정렬할 때, k 번째 위치한 수는!?

# 입력
n, k = map(int, input().split())
num_list = map(int, input().split())

# 본래의 수, 1의 갯수를 가지는 리스트 생성
bin_num_list = []
for x in num_list:
    bin_num_list.append([x, int(str(format(x, 'b')).count('1'))])

# 1의 갯수가 많은 순(index1번째), 동일하면 본래 수가큰수 (index0번째) 내림차순 정렬
bin_num_list.sort(key=lambda x: (x[1], x[0]), reverse=True)

# k번째 (k-1 index) 의 본래의 수 (index 0번째) 출력
print([bin_num_list[i][0] for i in range(n)][k-1])


from tkinter import *
from tkinter import messagebox
import serial
from threading import Thread
import time
import queue
import sys
from socket import *

# -----------------------------------------------------------------------
# The function is read the date and time from the label,
# check the errors and send it to the TTL port

def change_time_date():
    time_date = entry_ch_time_data.get()

    matchObj = re.match(  # regular expression, two digits number for every part
        r"^(\d\d?):(\d\d?):(\d\d?):(\d\d?):(\d\d?):(\d\d?):(\d\d?)$", time_date)
    ok = 1

    if matchObj:
        if not (0 <= int(matchObj.group(1)) <= 99):
            ok = 0
            messagebox.showinfo(
                'Wrong value', 'Wrong number of year.\n0 <= year <= 99')
        if not (1 <= int(matchObj.group(2)) <= 12):
            messagebox.showinfo(
                'Wrong value', 'Wrong number of month.\n1 <= month <= 12')
            ok = 0
        if not (1 <= int(matchObj.group(3)) <= 31):
            messagebox.showinfo(
                'Wrong value', 'Wrong number of day.\n1 <= day <= 31')
            ok = 0
        if not (1 <= int(matchObj.group(4)) <= 7):
            messagebox.showinfo(
                'Wrong value', 'Wrong number of week_day.\n1 <= week_day <= 7')
            ok = 0
        if not (0 <= int(matchObj.group(5)) <= 23):
            messagebox.showinfo(
                'Wrong value', 'Wrong number of hours.\n0 <= hours <= 23')
            ok = 0
        if not (0 <= int(matchObj.group(6)) <= 59):
            messagebox.showinfo(
                'Wrong value', 'Wrong number of minutes.\n0 <= minutes <= 59')
            ok = 0
        if not (0 <= int(matchObj.group(7)) <= 59):
            messagebox.showinfo(
                'Wrong value', 'Wrong number of seconds.\n0 <= seconds <= 59')
            ok = 0

        if (ok == 1):  # if data ok
            time_date = time_date + "\0"  # '\0' for C-string
            serialPort.write(time_date.encode('Ascii'))
    else:
        messagebox.showinfo(
            'Wrong value', 'Please type two-digit number for every segment.\nyear:month:day:week_day:hours:minutes:seconds\nFor example 20:12:31:1:12:30:30')

# -----------------------------------------------------------------------
# The function is read the seconds and average from the label,
# check the errors and send it to the TTL port
def change_time_upload():
    time_upload = entry_ch_up.get()

    matchObj = re.match(  # regular expression, positive number for every part
        r"^(\d+):(\d+)$", time_upload)
    ok = 1

    if matchObj:
        if not (1 <= int(matchObj.group(1)) <= 1200):
            ok = 0
            messagebox.showinfo(
                'Wrong value', 'Must be a positive integer.\n1 <= seconds <= 1200')
        if not (3 <= int(matchObj.group(2)) <= 1000):
            ok = 0
            messagebox.showinfo(
                'Wrong value', 'Must be a positive integer.\n1 <= average <= 1000')

        if (ok == 1):  # if data ok
            # 'a' for designation the time and average upload, '\0' for C-string
            time_upload = "a" + time_upload + "\0"
            serialPort.write(time_upload.encode('Ascii'))

    else:
        messagebox.showinfo(
            'Wrong value', 'Please type positive number for every segment.\nseconds:average\nFor example 3:10')

# -----------------------------------------------------------------------
# The function is read the data from the TTL port,
# check the errors and update the labels
def last_update():
    try:
        global flag_ch_port
        global flag_com
        global serialPort
        global flag_delete_thread
        serialString = ""

        serialPort.flushInput()
        serialPort.flushOutput()  # flush the TTL port

        while (1):
            if (flag_delete_thread == 1):
                serialPort.close()
                break

            if (flag_ch_port == 1):
                flag_ch_port = 0
                serialPort.close()

                if (flag_com == 1):
                    flag_com = 0
                    lbl_ch_com.configure(text="{0}".format("UART"))

                    while(1):
                        try:
                            serialPort = serial.Serial(port=UART_COM, baudrate=115200,
                                                       bytesize=8, timeout=0.5, stopbits=serial.STOPBITS_ONE)
                            # 'u' for main port, '\0' for C-string
                            serialPort.write("u\0".encode('Ascii'))
                            break

                        except serial.serialutil.SerialException:
                            print("Could not open port {0}".format(UART_COM))
                            time.sleep(2)
                else:
                    flag_com = 1
                    lbl_ch_com.configure(text="{0}".format("NRF24"))

                    while(1):
                        try:
                            serialPort = serial.Serial(port=NRF24_COM, baudrate=115200,
                                                       bytesize=8, timeout=0.5, stopbits=serial.STOPBITS_ONE)
                            # 'n' for slave port, '\0' for C-string
                            serialPort.write("n\0".encode('Ascii'))
                            break

                        except serial.serialutil.SerialException:
                            print("Could not open port {0}".format(NRF24_COM))
                            time.sleep(2)

            if not q_receive.empty():
                item = q_receive.get()
                item = item + b'\0'
                serialPort.write(item)

            if(serialPort.in_waiting > 0):
                serialString = serialPort.readline()
                serialString = serialString.decode('Ascii')

                matchObj = re.match(  # regular expression, three floating point number and two digits numbers for every part
                    r"^;([+-]?([0-9]*[.])?[0-9]+):([+-]?([0-9]*[.])?[0-9]+):([+-]?([0-9]*[.])?[0-9]+):(\d+):(\d+):(\d+):(\d+):(\d+):(\d+):(\d+):(\d+):(\d+);$", serialString)

                if matchObj:

                    if (flag_queue == 1):
                        q_send.put(matchObj.group(0))

                    lbl_date.configure(
                        text="Year: {0}    Month: {1}    Day: {2}    WeekDay: {3}".format(matchObj.group(7),
                                                                                matchObj.group(8), matchObj.group(9), matchObj.group(10)))
                    lbl_time.configure(
                        text="Hours: {0}    Minutes: {1}    Seconds: {2}".format(matchObj.group(11),
                                                                                matchObj.group(12), matchObj.group(13)))

                    lbl_humi.configure(
                        text="{0} %".format(matchObj.group(1)))
                    lbl_tem.configure(text="{0} C".format(matchObj.group(3)))
                    lbl_adc.configure(text="{0} V".format(matchObj.group(5)))
                    lbl_probe.configure(
                        text="{0} sec".format(matchObj.group(14)))
                    lbl_average.configure(text="{0} units".format(
                        matchObj.group(15)))  # update labels
                else:
                    print("not mach")
                    print(serialString)  # print the data that not match

    except Exception as e:
        print(e)

# -----------------------------------------------------------------------
# The function change the flag, which defines the ports
def change_com():
    global flag_ch_port

    flag_ch_port = 1

# -----------------------------------------------------------------------
# The function delete the window and thread after 0.5 seconds
def on_delete_window():
    global flag_delete_thread

    flag_delete_thread = 1
    window.after(700, window.destroy)

def onServer():
    global flag_queue
    global flag_delete_thread
    setdefaulttimeout(0.5)

    try:
        s = socket()
        s.bind(('', 12345))
        s.listen(5)
    except Exception as e:
        print(e)
        sys.exit(0)

    print("Waiting on {}:{}".format(*s.getsockname()))

    while True:
        try:
            client, address = s.accept()
            flag_queue = 1
            break
        except timeout:
            if (flag_delete_thread == 1):
                sys.exit(0)
            else:
                continue

    print("ip: {}   port: {} connected".format(*address))

    while True:
        try:
            if not q_send.empty():
                item = q_send.get()
                client.send(item.encode())
                q_send.task_done()

            msg = client.recv(1000)

            if msg == b'':
                flag_queue = 0
                client.close()

                while True:
                    try:
                        client, address = s.accept()
                        flag_queue = 1
                        break
                    except timeout:
                        if (flag_delete_thread == 1):
                            sys.exit(0)
                        else:
                            continue

            else:
                q_receive.put(msg)
                q_receive.task_done()

        except timeout:
            if (flag_delete_thread == 1):
                flag_queue = 0
                sys.exit(0)
            else:
                continue
        except (BlockingIOError, ConnectionResetError) as e:
            print(e)
            flag_queue = 0
            sys.exit(0)

    #
    # ===================================================================================
    #
    # ====================================================
NRF24_COM = "COM3"
UART_COM = "COM8"
flag_com = 1
flag_ch_port = 0
flag_delete_thread = 0
flag_queue = 0

q_send = queue.Queue()
q_receive = queue.Queue()
# ====================================================

while (1):
    try:
        serialPort = serial.Serial(port=NRF24_COM, baudrate=115200,
                                   bytesize=8, timeout=0.5, stopbits=serial.STOPBITS_ONE)
        break
    except serial.serialutil.SerialException:
        print("Could not open port {0}".format(NRF24_COM))
        time.sleep(2)

while (1):
    try:
        thread_last_up = Thread(target=last_update)
        thread_last_up.start()

        thread_tcp = Thread(target=onServer)
        thread_tcp.start()
        break

    except Exception as e:
        print("Thread error: ", e)

window = Tk()
window.title("Weather Analyzer")
window.geometry("490x250")

lbl_last = Label(window, text="Last update")
lbl_last.grid(column=1, row=0)

lbl_date = Label(window, text="Year: 10    Month: 5    Day: 1    WeekDay: 1")
lbl_date.grid(column=1, row=1)

lbl_time = Label(window, text="Hours: 12    Minutes: 12    Seconds: 30")
lbl_time.grid(column=1, row=2)

lbl_probe_txt = Label(window, text="Probe time: ")
lbl_probe_txt.grid(column=0, row=3)

lbl_probe = Label(window, text="3 sec")
lbl_probe.grid(column=1, row=3)

lbl_average_txt = Label(window, text="Average: ")
lbl_average_txt.grid(column=0, row=4)

lbl_average = Label(window, text="10 units")
lbl_average.grid(column=1, row=4)

lbl_humi_txt = Label(window, text="Humidity: ")
lbl_humi_txt.grid(column=0, row=5)

lbl_humi = Label(window, text="10.99999 %")
lbl_humi.grid(column=1, row=5)

lbl_tem_txt = Label(window, text="Temperature: ")
lbl_tem_txt.grid(column=0, row=6)

lbl_tem = Label(window, text="20.99999 C")
lbl_tem.grid(column=1, row=6)

lbl_adc_txt = Label(window, text="ADC Voltage: ")
lbl_adc_txt.grid(column=0, row=7)

lbl_adc = Label(window, text="1.99999 V")
lbl_adc.grid(column=1, row=7)

lbl_ch_time_data = Label(window, text="Change time and date")
lbl_ch_time_data.grid(column=0, row=8)

entry_ch_time_data = Entry(window, width=40)
entry_ch_time_data.grid(column=1, row=8)

btn_ch_time_data = Button(window, text="OK", command=change_time_date)
btn_ch_time_data.grid(column=2, row=8)

lbl_ch_up = Label(window, text="Change time and average")
lbl_ch_up.grid(column=0, row=9)

entry_ch_up = Entry(window, width=40)
entry_ch_up.grid(column=1, row=9)

btn_ch_up = Button(window, text="OK", command=change_time_upload)
btn_ch_up.grid(column=2, row=9)

lbl_ch_com = Label(window, text="NRF24")
lbl_ch_com.grid(column=1, row=10)

btn_ch_com = Button(window, text="OK", command=change_com)
btn_ch_com.grid(column=2, row=10)

# change function of delete
window.protocol('WM_DELETE_WINDOW', on_delete_window)

window.mainloop()


#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.

from rally_openstack.common import consts
from rally_openstack.task.scenarios.nova import utils as nova_utils
from rally_openstack.task.scenarios.neutron import utils as neutron_utils
from rally.task import scenario
from rally.task import types
from rally.task import validation

import sys
import os

sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../reports')))
from generate_scenario_duration_charts import ScenarioDurationChartsGenerator  # noqa: E402

@types.convert(image={"type": "glance_image"}, flavor={"type": "nova_flavor"})
@validation.add("image_valid_on_flavor", flavor_param="flavor", image_param="image")
@validation.add("required_services",services=[consts.Service.NEUTRON, consts.Service.NOVA])
@validation.add("required_platform", platform="openstack", users=True)
@scenario.configure(context={"cleanup@openstack": ["neutron", "nova"]},
                    name="BrowbeatPlugin.create_vms_on_network", platform="openstack")
class CreateVMsOnSingleNetwork(neutron_utils.NeutronScenario,
                               nova_utils.NovaScenario):

    def run(self, image, flavor, num_vms=1, network_create_args=None,
            subnet_create_args=None, port_create_args=None, **kwargs):

        network = self._create_network(network_create_args or {})
        self._create_subnet(network, subnet_create_args or {})

        for i in range(num_vms):
            kwargs["nics"] = []
            port = self._create_port(network, port_create_args or {})
            kwargs["nics"].append({'port-id': port['port']['id']})
            self._boot_server(image, flavor, **kwargs)

        self.duration_charts_generator = ScenarioDurationChartsGenerator()
        self.duration_charts_generator.add_per_iteration_complete_data(self)
        self.duration_charts_generator.add_duplicate_atomic_actions_iteration_additive_data(self)
        self.duration_charts_generator.add_all_resources_additive_data(self)


#Escribir un programa que vaya solicitando al usuario que ingrese nombres.
#a) Si el nombre se encuentra en la agenda (implementada con un diccionario), debe mostrar
#el teléfono y, opcionalmente, permitir modificarlo si no es correcto.
#b) Si el nombre no se encuentra, debe permitir ingresar el teléfono correspondiente.
#El usuario puede utilizar la cadena ”*”, para salir del programa.

def agenda():
    """
    usuario escribe un nombre, si no esta le pide que ingrese un numero
    si esta, le da el numero, si esta mal, lo puede cambiar
    """
    diccionario = {}
    nombre = ""
    while True:
        nombre = str(input('Ingrese un nombre, o "*" para salir: '))
        if nombre == '*':
            return False
        elif nombre in diccionario:
            print(f'telefono de {nombre} es {diccionario[nombre]}')
            nuevo_numero = int(input(f'ingrese nuevo numero para {nombre}: '))
            if nuevo_numero == " ":
                continue
            diccionario[nombre] = nuevo_numero
            print(f'Telefono actulizado para {nombre}, {diccionario[nombre]}')
            continue
        elif nombre not in diccionario:
            print('Persona no agendada')
            numero = int(input(f'ingrese el telefono para {nombre}: '))
            if numero == " ":
                continue
            diccionario.setdefault(nombre, numero)
            print(f'Nuevo telefono registrado para {nombre}, {numero}')
            continue
    return

agenda()


import sys
import os
import numpy as np
import matplotlib.pyplot as plt
import cv2
from copy import deepcopy as DC
import torch

path=""
clear=None
if os.name == 'nt':
    path="C:/Users/dexte/github/RoboSkin/Assets/images/"
    clear = lambda: os.system('cls')
else:
    path="/its/home/drs25/Documents/GitHub/RoboSkin/Assets/images/"
    clear = lambda: os.system('clear')

# caution: path[0] is reserved for script path (or '' in REPL)
sys.path.insert(1, 'C:/Users/dexte/github/RoboSkin/Code/')
sys.path.insert(1, '/its/home/drs25/Documents/GitHub/RoboSkin/Code')
out=None
import RoboSkin as sk
import Models.agent as agent

def genEnv(w):
    env=np.zeros((w*10,w*10)) #create environment
    grad=np.random.randint(-2,5)
    c=0
    if grad<=0: c=1000
    for i in range(w*10):
        for j in range(w*10):
            y=grad*j +c
            if y>i:
                env[i][j]=22
    #env+=np.random.normal(0,5,env.shape) #add bit of noise to simulate vibration
    env[env<0]=0
    return env,grad,c

def clearNoise(tip,skin,env,image,past_Frame,SPLIT,SIZE):
    for i in range(100):
        im,image,g=GetIm(tip,skin,env,image,past_Frame,SPLIT,SIZE)
        past_Frame=im.copy()
    return image
def GetIm(tip,skin,env,image,past_Frame,SPLIT,SIZE):
    im=tip.getImage(env)
    im=tip.maskPush(im)
    skin.imF=im.copy() #set it in skin
    im_g=skin.getBinary(min_size = SIZE) #get image from skin
    image,grid=skin.getForceGrid(im_g,SPLIT,image=image,threshold=20,degrade=20) #get the force push
    return im_g,image,grid
def tap(tip,skin,env,image,past_Frame,SPLIT,SIZE):
    tip.h=30
    img_g,image,g = GetIm(tip,skin,env,image,past_Frame,SPLIT,SIZE)
    tip.h=20
    img_g,image,g = GetIm(tip,skin,env,image,past_Frame,SPLIT,SIZE)
    return img_g,image,g

def runTrial(agent,img,skin,T):
    SPLIT=5
    past_Frame=skin.getBinary()
    image=np.zeros_like(past_Frame)
    h,w=img.shape[0:2]
    env,gr,c=genEnv(w)
    startY=(w*5) + img.shape[0]//2#start in middle
    if gr==0: gr=0.1
    startX=(startY- c)//gr
    if gr>0:startX-=50
    else:startX+=50
    SIZE=250
    tip=sk.digiTip(img) #create tactip
    tip.setPos(startX,startY) #start somewhere on line

    image=clearNoise(tip,skin,env,image,past_Frame,SPLIT,SIZE)
    dt=0.02
    t=0
    im_g,image,grid=tap(tip,skin,env,image,past_Frame,SPLIT,SIZE) #get tap to know area
    trial_over=False
    while t<T and not trial_over:
        y=tip.pos[0]+tip.grid.shape[0]
        x=tip.pos[1]+tip.grid.shape[1]
        terrain=env[max(min(tip.pos[0],env.shape[0]),0):max(min(y,env.shape[0]),0),max(min(tip.pos[1],env.shape[1]),0):max(min(x,env.shape[1]),0)].copy()*5
        if terrain.shape!=image.shape: trial_over=True
        if im_g.shape==terrain.shape:
            f_=np.concatenate((im_g,image,terrain),axis=1).astype(np.uint8)
            f_=cv2.resize(f_,(1000,400),interpolation=cv2.INTER_AREA)
            f_=cv2.cvtColor(f_,cv2.COLOR_GRAY2RGB)
            out.write(f_)
        #cv2.imshow('data', f_)
        #if cv2.waitKey(1) & 0xFF == ord('q'):
        #    break
        #move
        move=np.argmax(agent.forward(grid))
        if move==0: tip.moveX(5)
        elif move==1: tip.moveX(-5)
        elif move==2: tip.moveY(5)
        elif move==3: tip.moveY(-5)
        #gather next image
        im_g,image,grid = GetIm(tip,skin,env,image,past_Frame,SPLIT,SIZE)
        past_Frame=im_g.copy() #get last frame
        t+=dt
    return np.sum(terrain)/(img.shape[0]*img.shape[1]*22)/5

def mutate(genotype):
    return genotype+np.random.normal(0,2,genotype.shape)

def gen_genotype(shape):
    return np.random.normal(0,3,(shape,))

def run(agent,population,generations=500,T=2):
    pop_size=len(population)
    shape=population.shape[1]
    fitness_matrix=np.zeros((pop_size))
    overTime=np.zeros((generations,))
    gen=0
    while gen < (generations): #overTime[max(gen-1,0)]<1
        clear()
        print("Generation:",gen,"Fitness",overTime[max(gen-1,0)])
        #get mask to select genotypes for battle
        mask=np.random.choice([0, 1], size=pop_size)
        inds=(mask==1).nonzero()[0]
        while len(inds)%2!=0:
            mask=np.random.choice([0, 1], size=pop_size)
            inds=(mask==1).nonzero()[0]
        #get indicies and tournament modes
        inds=inds.reshape(len(inds)//2,2).astype(int)
        fitnesses=np.zeros((len(inds)//2)).astype(int)
        new_inds=np.zeros((len(inds)//2,2)).astype(int)
        #run each trial
        for i in range(len(inds)//2):
            #select genotypes
            g1=population[inds[i][0]]
            g2=population[inds[i][1]]
            #tournament
            agent.set_genes(g1)
            f1=0
            for j in range(3):
                f1+=runTrial(agent,img,skin,T)
            f1/=3
            agent.set_genes(g1)
            f2=0
            for j in range(3):
                f2+=runTrial(agent,img,skin,T)
            f2/=3
            fitness_matrix[inds[i][0]]=f1
            fitness_matrix[inds[i][1]]=f2
            if f1>f2:
                fitnesses[i]=f1
                new_inds[i]=[0,i]
            elif f2>f1:
                fitnesses[i]=f2
                new_inds[i]=[1,i]
            else:
                fitnesses[i]=0
                new_inds[i]=[0,i]
        #get top values and redistribute into the array
        winners=int(len(inds)//2 *0.4)
        mutants=int(len(inds)//2 *0.4)
        other=len(inds)//2 -winners - mutants
        order=np.argsort(fitnesses)
        for i in reversed(range(len(inds)//2)): #loop through backwards leaving the winners in place
            genoWin=new_inds[i][0]
            old_index=new_inds[i][1]
            if i<(len(inds)//2)-winners and i>(len(inds)//2)-winners-mutants: #pick mutants
                population[inds[old_index][1-genoWin]]=mutate(DC(population[inds[old_index][genoWin]])) #mutate copy
            elif i<(len(inds)//2)-winners-mutants: #the other
                population[inds[old_index][1-genoWin]]=gen_genotype(shape=shape) #create new genotype
        overTime[gen]=np.max(fitness_matrix)
        gen+=1

    return overTime,np.argmax(fitness_matrix)

img = cv2.imread(path+'flat.png')
shrink=(np.array(img.shape[0:2])//3).astype(int)
img=cv2.resize(img,(shrink[1],shrink[0]),interpolation=cv2.INTER_AREA)[60:220,75:220]
#img=cv2.resize(img,(np.array(img.shape[0:2])).astype(int),interpolation=cv2.INTER_AREA)
skin=sk.Skin(imageFile=img) #create the image

f=np.concatenate((img,img,img),axis=1).astype(np.uint8)
f=cv2.resize(f,(1000,400),interpolation=cv2.INTER_AREA)
#f=cv2.cvtColor(f,cv2.COLOR_GRAY2RGB)
h, w = f.shape[:2]
out = cv2.VideoWriter('digiTip_evolve.avi',cv2.VideoWriter_fourcc(*'DIVX'), 15, (w,h))

#create an agent
sensor=agent.Agent(5*5,[30,30],4)
genes=np.random.normal(0,3,(sensor.num_genes,))
sensor.set_genes(genes)

dt=0.01
T=2
#genetic agorithm
SIZE=100
pop=np.random.normal(0,3,(SIZE,sensor.num_genes))

generations=500
try:
    fit,ind=run(sensor,pop,generations)
except KeyboardInterrupt:
    pass
out.release()

np.save("TacTipSim",pop[ind])
np.save("TacTipSim_fitnesses",fit)
cv2.destroyAllWindows()


import requests

from restapitest.Routes import Routes

path = "C:\\Users\\Darshan\\Desktop\\questionpapers\\DRDO\\TIER 1\\Arithmetic.pdf"

files = {'file': open(path, 'rb')}

resps=requests.post(Routes.url3, files=files)
print(resps.status_code)
print(resps.text)


# -*- coding: utf-8 -*-
import difflib

#Dictionary of Amino Acid Sequence
AA_Table = {
    'ATA':'I', 'ATC':'I', 'ATT':'I', 'ATG':'M',
    'ACA':'T', 'ACC':'T', 'ACG':'T', 'ACT':'T',
    'AAC':'N', 'AAT':'N', 'AAA':'K', 'AAG':'K',
    'AGC':'S', 'AGT':'S', 'AGA':'R', 'AGG':'R',
    'CTA':'L', 'CTC':'L', 'CTG':'L', 'CTT':'L',
    'CCA':'P', 'CCC':'P', 'CCG':'P', 'CCT':'P',
    'CAC':'H', 'CAT':'H', 'CAA':'Q', 'CAG':'Q',
    'CGA':'R', 'CGC':'R', 'CGG':'R', 'CGT':'R',
    'GTA':'V', 'GTC':'V', 'GTG':'V', 'GTT':'V',
    'GCA':'A', 'GCC':'A', 'GCG':'A', 'GCT':'A',
    'GAC':'D', 'GAT':'D', 'GAA':'E', 'GAG':'E',
    'GGA':'G', 'GGC':'G', 'GGG':'G', 'GGT':'G',
    'TCA':'S', 'TCC':'S', 'TCG':'S', 'TCT':'S',
    'TTC':'F', 'TTT':'F', 'TTA':'L', 'TTG':'L',
    'TAC':'Y', 'TAT':'Y', 'TAA':'_', 'TAG':'_',
    'TGC':'C', 'TGT':'C', 'TGA':'_', 'TGG':'W',
}

def readSequence(fileName):
    """
    Reads a text file and returns a string without
    \n and \r

    Parameters
    ----------
    fileName : TYPE
        DESCRIPTION.

    Returns
    -------
    seq : TYPE
        DESCRIPTION.

    """
    with open(fileName, "r") as f:
        seq = f.read()
    seq = seq.replace("\n", "")
    seq = seq.replace("\r","")
    return seq

def writeSequence(fileName, p_sequence):
    with open(fileName, "w+") as f:
        f.write(p_sequence)

def findStart (sequence):
    """
    Searches for the ATG codon to start the protein translation

    Parameters
    ----------
    sequence : TYPE
        DESCRIPTION.

    Returns
    -------
    TYPE
        DESCRIPTION.

    """
    start_pos = 0
    for a in sequence:
        if (sequence[start_pos:(start_pos + 3)] == "ATG"):
            return start_pos
        else:
            start_pos += 1
    return -1

def findEnd (sequence):
    """
    Returns a tuple including the starting point and ending point
    not including the last codon
    """
    start_pos = findStart(sequence)
    end_pos = start_pos + 3
    for a in range(start_pos, len(sequence), 3):
        if (sequence[a:(a+3)] == "TAA" or
            sequence[a:(a+3)] == "TAG" or
            sequence[a:(a+3)] == "TGA"):
            # end_pos - 3 because the end codon should not be included
            return (start_pos, (end_pos-3))
        else:
            end_pos += 3
    return (start_pos, -1)

def translate(sequence):

    """
    This function takes in a string and returns an amino acid seqence.
    The function will not run if the input string is not
    divisible by 3.

    Parameters
    ----------
    sequence : TYPE
        DESCRIPTION.

    Returns
    -------
    protein : TYPE
        DESCRIPTION.
    """
    start_pos, end_pos = findEnd(sequence)
    protein = ""
    if ((end_pos-start_pos) % 3 == 0):
        for i in range(start_pos, end_pos, 3):
            codon = sequence[i:(i+3)]
            protein += AA_Table[codon]
    return protein

def checkDiff(file1, file2):
    for line in difflib.unified_diff(file1, file2):
        print(line)

def main():
    input_file = input("Input File Name (including .txt):")

    DNA_Sequence = readSequence(input_file)
    protein_Sequence = translate(DNA_Sequence)

    output_file = input("Output File Name (including .txt):")
    writeSequence(output_file, protein_Sequence)

    check_file = input("Check File Name (including .txt):")
    checkDiff(open(check_file).readlines(), open(output_file).readlines())

main()


import logging
from functools import partial

import numpy as np

from ..core.client import Client
from ..core.data import Data
from ..core.subset import RoiSubsetState
from ..core.roi import PolygonalROI
from ..core.util import relim
from ..core.edit_subset_mode import EditSubsetMode
from .viz_client import init_mpl
from .layer_artist import ScatterLayerArtist, LayerArtistContainer
from .util import visible_limits
from ..core.callback_property import (CallbackProperty, add_callback,
                                      delay_callback)

class ScatterClient(Client):
    """
    A client class that uses matplotlib to visualize tables as scatter plots.
    """
    xmin = CallbackProperty(0)
    xmax = CallbackProperty(1)
    ymin = CallbackProperty(0)
    ymax = CallbackProperty(1)
    ylog = CallbackProperty(False)
    xlog = CallbackProperty(False)
    yflip = CallbackProperty(False)
    xflip = CallbackProperty(False)
    xatt = CallbackProperty()
    yatt = CallbackProperty()

    def __init__(self, data=None, figure=None, axes=None,
                 artist_container=None):
        """
        Create a new ScatterClient object

        :param data: :class:`~glue.core.DataCollection` to use

        :param figure:
           Which matplotlib figure instance to draw to. One will be created if
           not provided

        :param axes:
           Which matplotlib axes instance to use. Will be created if necessary
        """
        Client.__init__(self, data=data)
        figure, axes = init_mpl(figure, axes)
        self.artists = artist_container
        if self.artists is None:
            self.artists = LayerArtistContainer()

        self._layer_updated = False  # debugging
        self._xset = False
        self._yset = False
        self.axes = axes

        self._connect()
        self._set_limits()

    def is_layer_present(self, layer):
        """ True if layer is plotted """
        return layer in self.artists

    def get_layer_order(self, layer):
        """If layer exists as a single artist, return its zorder.
        Otherwise, return None"""
        artists = self.artists[layer]
        if len(artists) == 1:
            return artists[0].zorder
        else:
            return None

    @property
    def layer_count(self):
        return len(self.artists)

    def _connect(self):
        add_callback(self, 'xlog', self._set_xlog)
        add_callback(self, 'ylog', self._set_ylog)

        add_callback(self, 'xflip', self._set_limits)
        add_callback(self, 'yflip', self._set_limits)
        add_callback(self, 'xmin', self._set_limits)
        add_callback(self, 'xmax', self._set_limits)
        add_callback(self, 'ymin', self._set_limits)
        add_callback(self, 'ymax', self._set_limits)
        add_callback(self, 'xatt', partial(self._set_xydata, 'x'))
        add_callback(self, 'yatt', partial(self._set_xydata, 'y'))
        self.axes.figure.canvas.mpl_connect('draw_event',
                                            lambda x: self._pull_properties())

    def _set_limits(self, *args):
        xlim = min(self.xmin, self.xmax), max(self.xmin, self.xmax)
        if self.xflip:
            xlim = xlim[::-1]
        ylim = min(self.ymin, self.ymax), max(self.ymin, self.ymax)
        if self.yflip:
            ylim = ylim[::-1]

        xold = self.axes.get_xlim()
        yold = self.axes.get_ylim()
        self.axes.set_xlim(xlim)
        self.axes.set_ylim(ylim)
        if xlim != xold or ylim != yold:
            self._redraw()

    def plottable_attributes(self, layer, show_hidden=False):
        data = layer.data
        comp = data.components if show_hidden else data.visible_components
        return [c for c in comp if
                data.get_component(c).numeric]

    def add_layer(self, layer):
        """ Adds a new visual layer to a client, to display either a dataset
        or a subset. Updates both the client data structure and the
        plot.

        :param layer: the layer to add
        :type layer: :class:`~glue.core.Data` or :class:`~glue.core.Subset`
        """
        if layer.data not in self.data:
            raise TypeError("Layer not in data collection")
        if layer in self.artists:
            return
        self.artists.append(ScatterLayerArtist(layer, self.axes))
        self._update_layer(layer)
        self._ensure_subsets_added(layer)

    def _ensure_subsets_added(self, layer):
        if not isinstance(layer, Data):
            return
        for subset in layer.subsets:
            self.add_layer(subset)

    def _visible_limits(self, axis):
        """Return the min-max visible data boundaries for given axis"""
        return visible_limits(self.artists, axis)

    def _snap_xlim(self):
        """
        Reset the plotted x rng to show all the data
        """
        is_log = self.xlog
        rng = self._visible_limits(0)
        if rng is None:
            return
        rng = relim(rng[0], rng[1], is_log)
        if self.xflip:
            rng = rng[::-1]
        self.axes.set_xlim(rng)
        self._pull_properties()

    def _snap_ylim(self):
        """
        Reset the plotted y rng to show all the data
        """
        rng = [np.infty, -np.infty]
        is_log = self.ylog

        rng = self._visible_limits(1)
        if rng is None:
            return
        rng = relim(rng[0], rng[1], is_log)

        if self.yflip:
            rng = rng[::-1]
        self.axes.set_ylim(rng)
        self._pull_properties()

    def snap(self):
        """Rescale axes to fit the data"""
        self._snap_xlim()
        self._snap_ylim()
        self._redraw()

    def set_visible(self, layer, state):
        """ Toggle a layer's visibility

        :param layer: which layer to modify
        :type layer: class:`~glue.core.Data` or :class:`~glue.coret.Subset`

        :param state: True to show. false to hide
        :type state: boolean
        """
        if layer not in self.artists:
            return
        for a in self.artists[layer]:
            a.visible = state
        self._redraw()

    def is_visible(self, layer):
        if layer not in self.artists:
            return False
        return any(a.visible for a in self.artists[layer])

    def _set_xydata(self, coord, attribute, snap=True):
        """ Redefine which components get assigned to the x/y axes

        :param coord: 'x' or 'y'
           Which axis to reassign
        :param attribute:
           Which attribute of the data to use.
        :type attribute: str
        :param snap:
           If True, will rescale x/y axes to fit the data
        :type snap: bool
        """

        if coord not in ('x', 'y'):
            raise TypeError("coord must be one of x,y")

        #update coordinates of data and subsets
        if coord == 'x':
            new_add = not self._xset
            self.xatt = attribute
            self._xset = self.xatt is not None
        elif coord == 'y':
            new_add = not self._yset
            self._yset = self.yatt is not None

        #update plots
        map(self._update_layer, self.artists.layers)

        if coord == 'x' and snap:
            self._snap_xlim()
            if new_add:
                self._snap_ylim()
        elif coord == 'y' and snap:
            self._snap_ylim()
            if new_add:
                self._snap_xlim()

        self._update_axis_labels()
        self._pull_properties()
        self._redraw()

    def apply_roi(self, roi):
        # every editable subset is updated
        # using specified ROI
        subset_state = RoiSubsetState()
        subset_state.xatt = self.xatt
        subset_state.yatt = self.yatt
        x, y = roi.to_polygon()
        subset_state.roi = PolygonalROI(x, y)
        mode = EditSubsetMode()
        visible = [d for d in self._data if self.is_visible(d)]
        focus = visible[0] if len(visible) > 0 else None
        mode.update(self._data, subset_state, focus_data=focus)

    def _set_xlog(self, state):
        """ Set the x axis scaling

        :param state:
            The new scaling for the x axis
        :type state: string ('log' or 'linear')
        """
        mode = 'log' if state else 'linear'
        lim = self.axes.get_xlim()
        self.axes.set_xscale(mode)

        #Rescale if switching to log with negative bounds
        if state and min(lim) <= 0:
            self._snap_xlim()

        self._redraw()

    def _set_ylog(self, state):
        """ Set the y axis scaling

        :param state: The new scaling for the y axis
        :type state: string ('log' or 'linear')
        """
        mode = 'log' if state else 'linear'
        lim = self.axes.get_ylim()
        self.axes.set_yscale(mode)
        #Rescale if switching to log with negative bounds
        if state and min(lim) <= 0:
            self._snap_ylim()

        self._redraw()

    def _remove_data(self, message):
        """Process DataCollectionDeleteMessage"""
        for s in message.data.subsets:
            self.delete_layer(s)
        self.delete_layer(message.data)

    def _remove_subset(self, message):
        self.delete_layer(message.subset)

    def delete_layer(self, layer):
        if layer not in self.artists:
            return
        self.artists.pop(layer)
        self._redraw()
        assert not self.is_layer_present(layer)

    def _update_data(self, message):
        data = message.sender
        self._update_layer(data)

    def _redraw(self):
        self.axes.figure.canvas.draw()

    def _update_axis_labels(self):
        self.axes.set_xlabel(self.xatt)
        self.axes.set_ylabel(self.yatt)

    def _add_subset(self, message):
        subset = message.sender
        #only add subset if data layer present
        if subset.data not in self.artists:
            return
        subset.do_broadcast(False)
        self.add_layer(subset)
        subset.do_broadcast(True)

    def add_data(self, data):
        self.add_layer(data)
        for subset in data.subsets:
            self.add_layer(subset)

    @property
    def data(self):
        """The data objects in the scatter plot"""
        return list(self._data)

    def _update_subset(self, message):
        self._update_layer(message.sender)

    def _update_layer(self, layer):
        """ Update both the style and data for the requested layer"""
        if self.xatt is None or self.yatt is None:
            return

        if layer not in self.artists:
            return

        self._layer_updated = True
        for art in self.artists[layer]:
            art.xatt = self.xatt
            art.yatt = self.yatt
            art.update()
        self._redraw()

    def _pull_properties(self):
        xlim = self.axes.get_xlim()
        ylim = self.axes.get_ylim()
        xsc = self.axes.get_xscale()
        ysc = self.axes.get_yscale()

        xflip = (xlim[1] < xlim[0])
        yflip = (ylim[1] < ylim[0])

        with delay_callback(self, 'xmin', 'xmax', 'xflip', 'xlog'):
            self.xmin = min(xlim)
            self.xmax = max(xlim)
            self.xflip = xflip
            self.xlog = (xsc == 'log')

        with delay_callback(self, 'ymin', 'ymax', 'yflip', 'ylog'):
            self.ymin = min(ylim)
            self.ymax = max(ylim)
            self.yflip = yflip
            self.ylog = (ysc == 'log')


import json
import time

def text_processing(text):
    res = ['\ufeff', '\xa0', '\u3000']
    text = text.strip()
    for ch in res:
        text = text.replace(ch, '')
    return text

def read_txt(input_file):
    with open(input_file, encoding="utf-8") as f:
        reader = f.readlines()
        return [tuple(line.split('\t')) for line in reader]

def read_json(input_file):
    """Reads a json list file."""
    with open(input_file, "r") as f:
        reader = f.readlines()
    return [json.loads(line.strip()) for line in reader]

def save_json(input_json):
    VERSION = time.strftime("%Y%m%d-%H%M%S")
    with open(f'evaluate/results/result-{VERSION}.json', 'w', encoding='utf-8') as f:
        json.dump(input_json, f, ensure_ascii=False, indent=4)
    print(f'result-{VERSION}.json save completely..')


import math
import numpy
#import matplotlib.pyplot as plot

def mc_loren_summary(num, iterates):
    res = 0
    for i in range(1, iterates):
        pre_res = (math.factorial(2 * i) * (num ** i)) / ((1 - 2 * i) * (math.factorial(i) ** 2) * (4 ** i))
        if i % 2 == 0:
            res += pre_res
        else:
            res -= pre_res
    return res

class Complex:
    mc_loren_accuracy = 10
    number = 0
    savedOne = False
    lowerOne = False

    def __init__(self, number, mc_loren_accuracy=10):
        self.number = number
        if self.number < 0:
            self.number *= (-1)
            print("FU, number should be > 0. Negating...")
        if self.number < 1:
            self.lowerOne = True
            self.number = 2 - self.number

        self.mc_loren_accuracy = mc_loren_accuracy

    def sqr(self):
        if self.savedOne:
            module = self.number
            self.number = module * module + 2 * module
            if self.number > 1:
                self.savedOne = False
                self.number += 1
        else:
            self.number = self.number * self.number

    def sqr_n(self, n):
        for i in range(n):
            self.sqr()

    def sqrt(self):
        if numpy.abs(self.number - 1) < 1 and not self.savedOne or numpy.abs(self.number) < 1 and self.savedOne:
            if not self.savedOne:
                self.savedOne = True
                self.number -= 1
            module = self.number
            beta = mc_loren_summary(module, self.mc_loren_accuracy)
            self.number = beta
        else:
            self.number = math.sqrt(self.number)

    def sqrt_n(self, n):
        for i in range(n):
            self.sqrt()

    def magic_function(self, iterates, out):
        self.sqrt_n(iterates)
        if out:
            print("After sqr:")
            print(self)
        self.sqr_n(iterates)

    def __str__(self):
        if self.lowerOne:
            if self.savedOne:
                if self.number > 0.000000001:
                    return str(1 - self.number)
                else:
                    return "1 - " + str(self.number)
            else:
                return str(2 - self.number)
        else:
            if self.savedOne:
                if self.number > 0.000000001:
                    return str(1+self.number)
                else:
                    return "1 + " + str(self.number)
            else:
                return str(self.number)

""" num is number to work,
    iterates is number of repeatings for sqrt and sqr
    mc_loren_accuracy is amount of members in mcLoren summary
"""
def main(num, iterates=100, mc_loren_accuracy=10):

    x = Complex(num, mc_loren_accuracy)
    print("sqrt and sqr " + str(iterates) + " times:")
    print("Number before:")
    print(x)
    x.magic_function(iterates, True)
    print("Number after:")
    print(x)

    try:
        delta = num - float(x.__str__())
        eps = numpy.abs(delta) / num

        print("Relative error: ")
        print(eps)
    except ValueError:
        print("Deviation from 1 is lower than ", 0.000000001, "\nCant count epsilon well")