from keras import layers,models,optimizers,losses
from keras.datasets import cifar10

import tensorflow as tf

import pandas as pd
import matplotlib.pyplot as plt

(X_train,y_train),(X_test,y_test)=cifar10.load_data()

print(X_train.shape)
print(y_train.shape)
HIDDEN_SIZE=256#要有下划线
NUM_CLASSES=10#要有下划线避免语法重叠
LEARNING_RATE=1E-3
model=models.Sequential()

model.add(layers.Conv2D(32,(3,3),activation='relu',input_shape=(32,32,3)))
model.add(layers.MaxPool2D(2,2))
model.add(layers.Conv2D(64,(3,3),activation='relu'))
model.add(layers.MaxPool2D(2,2))
model.add(layers.Flatten())
model.add(layers.Dense(HIDDEN_SIZE,activation='relu'))
model.add(layers.Dense(NUM_CLASSES,activation='softmax'))

model.compile(
    optimizer=optimizers.Adam(learning_rate=LEARNING_RATE),
    loss=losses.SparseCategoricalCrossentropy(from_logits=True),
    metrics=['accuracy']
)

EPOCH=10
history=model.fit(X_train,y_train,epochs=EPOCH,validation_split=0.2)
#pd.DataFrame(history.history).plot(figsize=(8,5))
pd.DataFrame(history.history).plot(figsize=(8,5))
plt.grid(True)
plt.show()

result=model.evaluate(X_train,y_train,verbose=0)
print('卷积神经网络在cifar10数据集上的准确率为%.2f%%'%(result[1]*100))
print('卷积神经网络在cifar10数据集上的loss为%.2f'%(result[0]))

import numpy as np
pred=model.predict(X_test)
pred = np.argmax(pred, axis = 1)[:10]
label = np.argmax(y_test,axis = 1)[:10]

print(pred)
print(label)

model.save('model2.h5')

手写卷积神经网络_test.py

手写卷积神经网络_test.py


# -*- coding: utf-8 -*-
from odoo import api, models, fields, registry
import odoo
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
import json
import logging

_logger = logging.getLogger(__name__)

class pos_call_log(models.Model):
    _rec_name = "call_model"
    _name = "pos.call.log"
    _description = "Log datas of pos sessions"

    min_id = fields.Integer('Min Id', required=1, index=True, readonly=1)
    max_id = fields.Integer('Max Id', required=1, index=True, readonly=1)
    call_domain = fields.Char('Domain', required=1, index=True, readonly=1)
    call_results = fields.Char('Results', readonly=1)
    call_model = fields.Char('Model', required=1, index=True, readonly=1)
    call_fields = fields.Char('Fields', index=True, readonly=1)
    active = fields.Boolean('Active', default=True)
    write_date = fields.Datetime('Write date', readonly=1)

    @api.multi
    def compare_database_write_date(self, model, pos_write_date):
        last_logs = self.search([('call_model', '=', model), ('write_date', '<', pos_write_date)])
        if last_logs:
            _logger.info('POS write date is %s' % pos_write_date)
            _logger.info('Model %s write date is %s' % (model, last_logs[0].write_date))
            return True
        else:
            return False

    def covert_datetime(self, model, datas):
        all_fields = self.env[model].fields_get()
        version_info = odoo.release.version_info[0]
        if version_info == 12:
            if all_fields:
                for data in datas:
                    for field, value in data.items():
                        if field == 'model':
                            continue
                        if all_fields[field] and all_fields[field]['type'] in ['date', 'datetime'] and value:
                            data[field] = value.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
        return datas

    @api.multi
    def refresh_call_logs(self):
        _logger.info('========================= BEGIN refresh_call_logs ========================================')
        cache_database_object = self.env['pos.cache.database']
        logs = self.search([])
        for log in logs:
            call_fields = cache_database_object.get_fields_by_model(log.call_model)
            call_domain = cache_database_object.get_domain_by_model(log.call_model)
            call_domain.append(['id', '>=', log.min_id])
            call_domain.append(['id', '<=', log.max_id])
            _logger.info('Refresh log of model: %s' % log.call_model)
            _logger.info(call_domain)
            _logger.info('===============================')
            results = self.env[log.call_model].sudo().search_read(
                call_domain,
                call_fields)
            version_info = odoo.release.version_info[0]
            if version_info == 12:
                all_fields = self.env[log.call_model].fields_get()
                if all_fields:
                    for result in results:
                        for field, value in result.items():
                            if field == 'model':
                                continue
                            if all_fields[field] and all_fields[field]['type'] in ['date', 'datetime'] and value:
                                result[field] = value.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
            log.write({
                'call_results': json.dumps(results),
                'call_fields': json.dumps(call_fields),
                'call_domain': json.dumps(call_domain),
            })
        self.env['pos.cache.database'].search([]).unlink()
        _logger.info('========================= END refresh_call_logs ========================================')
        return True


from loguru import logger
import configparser as cfg
import os

def logger_handler(msg: str, mode=2) -> None:
    """
    Handles logging of messages
    mode: 0 = debug, 1 = info, 2 = error (default)
    """

    # construct logger
    _log_constructor(mode)

    # log message
    if mode == 0:
        logger.exception(msg)
    elif mode == 1:
        logger.info(msg)
    else:
        logger.error(msg)

def _log_constructor(mode: int) -> None:
    """
    internal function to construct the logger
    requires config file in the same directory!
    """

    # read config file
    config = cfg.ConfigParser()
    config.read('config.ini')

    _log_level_mapping = {0: 'DEBUG', 1: 'INFO', 2: 'ERROR'}

    # define log levels as defined in config file
    _config_level = {0: 'LOGGING_DEBUG', 1: 'LOGGING_INFO', 2: 'LOGGING_ERROR'}

    _mode = _log_level_mapping[mode]

    _cnf_lvl = _config_level[mode]

    _file_name = os.path.expanduser(
        config.get(_cnf_lvl, 'log_file', fallback=''))

    _serialize = config.get(_cnf_lvl, 'log_serialize')
    _diagnose = config.get(_cnf_lvl, 'log_diagnose')

    logger.add(_file_name,
               rotation=config.get(_cnf_lvl, 'log_rotate', fallback=''),
               level=_mode,
               format=config.get(_cnf_lvl, 'log_format', fallback=''),
               compression=config.get(
                   _cnf_lvl, 'log_compression', fallback=''),
               diagnose=eval(_diagnose),
               serialize=eval(_serialize))


"""
Usage: negotiator-cli [OPTIONS] GUEST_UNIX_SOCKET
Communicate from a KVM/QEMU host system with running guest systems using a
guest agent daemon running inside the guests.
Supported options:
  -c, --list-commands
    List the commands that the guest exposes to its host.
  -e, --execute=COMMAND
    Execute the given command inside GUEST_UNIX_SOCKET. The standard output stream of
    the command inside the guest is intercepted and copied to the standard
    output stream on the host. If the command exits with a nonzero status code
    the negotiator-host program will also exit with a nonzero status code.
  -t, --timeout=SECONDS
    Set the number of seconds before a remote call without a response times
    out. A value of zero disables the timeout (in this case the command can
    hang indefinitely). The default is 10 seconds.
  -h, --help
    Show this message and exit.
"""

from humanfriendly import Timer
from negotiator_common.config import DEFAULT_TIMEOUT
from negotiator_common import NegotiatorInterface
from negotiator_common.utils import TimeOut

import coloredlogs
import functools
import getopt
import logging
import os
import shlex
import socket
import sys

# Initialize a logger for this module.
logger = logging.getLogger(__name__)

class GuestChannel(NegotiatorInterface):

    """
    The host side of the channel connecting KVM/QEMU hosts and guests.
    This is a modificaiton of negotiator_host.GuestChannel
    """

    def __init__(self, unix_socket):
        if not unix_socket:
            raise GuestChannelInitializationError("No UNIX socket pathname provided!")

        # Connect to the UNIX socket.
        logger.debug("Opening UNIX socket: %s", unix_socket)
        self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        try:
            logger.debug("Connecting to UNIX socket: %s", unix_socket)
            self.socket.connect(unix_socket)
        except Exception:
            raise GuestChannelInitializationError("Guest refused connection attempt!")
        logger.debug("Successfully connected to UNIX socket!")
        # Initialize the super class, passing it a file like object connected
        # to the character device in read/write mode.
        super(GuestChannel, self).__init__(handle=self.socket.makefile(),
                                           label="UNIX socket %s" % unix_socket)

    def prepare_environment(self):
        """
        Prepare environment variables for command execution on KVM/QEMU hosts.
        The following environment variables are currently exposed to commands:
        ``$NEGOTIATOR_GUEST``
          The name of the KVM/QEMU guest that invoked the command.
        """
        os.environ['NEGOTIATOR_GUEST'] = self.guest_name

class GuestChannelInitializationError(Exception):

    """Exception raised by :py:class:`GuestChannel` when socket initialization fails."""

class Context(object):

    """Enables :py:func:`main()` to inject a custom timeout into partially applied actions."""

    def __init__(self):
        """Initialize a context for executing commands on the host."""
        self.timeout = DEFAULT_TIMEOUT

    def print_commands(self, guest_unix_socket):
        """Print the commands supported by the guest."""
        with TimeOut(self.timeout):
            channel = GuestChannel(unix_socket=guest_unix_socket)
            print('\n'.join(sorted(channel.call_remote_method('list_commands'))))

    def execute_command(self, guest_unix_socket, command_line):
        """Execute a command inside the named guest."""
        with TimeOut(self.timeout):
            timer = Timer()
            channel = GuestChannel(unix_socket=guest_unix_socket)
            output = channel.call_remote_method('execute', *shlex.split(command_line), capture=True)
            logger.debug("Took %s to execute remote command.", timer)
            print(output.rstrip())

def main():
    """Command line interface for the ``negotiator-cli`` program."""
     # Initialize logging to the terminal and system log.
    coloredlogs.install(syslog=True)
    # Parse the command line arguments.
    actions = []
    context = Context()
    try:
        options, arguments = getopt.getopt(sys.argv[1:], 'ce:t:h', [
            'list-commands', 'execute=', 'timeout=', 'help'
        ])
        for option, value in options:
            if option in ('-c', '--list-commands'):
                assert len(arguments) == 1, \
                    "Please provide the unix socket of a guest as the 1st and only positional argument!"
                actions.append(functools.partial(context.print_commands, arguments[0]))
            elif option in ('-e', '--execute'):
                assert len(arguments) == 1, \
                    "Please provide the unix socket of a guest as the 1st and only positional argument!"
                actions.append(functools.partial(context.execute_command, arguments[0], value))
            elif option in ('-t', '--timeout'):
                context.timeout = int(value)
            elif option in ('-h', '--help'):
                usage()
                sys.exit(0)
        if not actions:
            usage()
            sys.exit(0)
    except Exception:
        logger.exception("Failed to parse command line arguments!")
        sys.exit(1)
    # Execute the requested action(s).
    try:
        for action in actions:
            action()
    except Exception:
        logger.exception("Caught a fatal exception! Terminating ..")
        sys.exit(1)

def usage():
    """Print a user friendly usage message to the terminal."""
    print(__doc__.strip())

if __name__ == "__main__":
    main()


import agentpy as ap
import numpy as np

import matplotlib.pyplot as plt
import matplotlib.colors as colors
import matplotlib.patches as mpatches
import seaborn as sns

def status_stackplot(data, ax):
    """Stackplot of people's condition over time."""
    x = data.index.get_level_values("t")
    y = [data[var] for var in ["store", "buy", "sell"]]

    color_map = {"labels": ["store", "buy", "sell"], "colors": ["blue", "orange", "green"]}
    ax.stackplot(x, y, **color_map)

    ax.legend()
    ax.set_xlim(0, max(1, len(x) - 1))
    ax.set_ylim(0, 1)
    ax.set_xlabel("Time steps")
    ax.set_ylabel("Percentage of population")
    ax.set_title("Proportion of agents taking each action")

def cost_lineplot(data, ax):
    x = data.index.get_level_values("t")[1:]
    y = -data["daily_cost"][1:]

    ax.plot(x, y)
    # Fit a linear regression model
    coeffs = np.polyfit(x, y, 1)
    m = coeffs[0]
    b = coeffs[1]

    # Plot the regression line
    ax.plot(x, m * x + b, color="black", linestyle="--")

    ax.legend()
    ax.set_xlim(0, max(1, len(x) - 1))
    ax.set_xlabel("Time steps")
    ax.set_ylabel("Daily cost (arbitrary units)")

def transfer_lineplot(data, ax):
    x = data.index.get_level_values("t")[1:]
    local = data["local_transfer"][1:]
    grid = data["grid_transfer"][1:]

    sns.set()
    ax.plot(x, local, label="Local transfer")
    ax.plot(x, grid, label="Grid transfer")

    ax.legend()
    ax.set_xlabel("Time steps")
    ax.set_ylabel("Daily energy sources (arbitrary units)")

def reward_lineplot(data, ax):
    x = data.index.get_level_values("t")[1:]
    y = data["reward"][1:]

    ax.plot(x, y)
    # Fit a linear regression model
    coeffs = np.polyfit(x, y, 1)
    m = coeffs[0]
    b = coeffs[1]

    # Plot the regression line
    ax.plot(x, m * x + b, color="black", linestyle="--")

    ax.legend()
    ax.set_xlim(0, max(1, len(x) - 1))
    ax.set_xlabel("Time steps")
    ax.set_ylabel("Reward (arbitrary units)")

def animation_plot(model, ax):
    group_grid = model.network.attr_grid("status")
    color_dict = {-1: "orange", 0: "blue", 1: "green"}
    action_dict = {"buy": "orange", "sell": "green", "store": "blue"}
    cmap = colors.ListedColormap([color_dict[key] for key in color_dict])
    ap.gridplot(group_grid, cmap=cmap, ax=ax)

    # Create legend
    legend_handles = [
        mpatches.Patch(color=color, label=label) for label, color in action_dict.items()
    ]
    ax.legend(handles=legend_handles)

    ax.set_title(f"Energyshed model \n Time-step: {model.t} Weather: {model.weather}")

def q_values_plot(i, q_values):
    # Extract the state and action spaces from the q-values
    state_space = sorted(set([key[0] for q_values in q_values for key in q_values.keys()]))
    action_space = sorted(set([key[1] for q_values in q_values for key in q_values.keys()]))
    q_values = q_values[i]
    # Create an empty matrix to hold the q-values
    q_values_matrix = np.zeros((len(state_space), len(action_space)))
    for j, state in enumerate(state_space):
        for k, action in enumerate(action_space):
            q_values_matrix[j, k] = q_values.get((state, action), 0)

    value_map = {-1: "Neg. energy bal.", 0: "Zero energy bal.", 1: "Pos. energy bal."}
    state_space_labels = [
        (value_map[energy], weather, store) for energy, weather, store in state_space
    ]
    # Clear the previous plot and plot the new heat map
    plt.clf()
    sns.heatmap(
        q_values_matrix,
        annot=True,
        fmt=".3g",
        xticklabels=action_space,
        yticklabels=state_space_labels,
        norm=colors.Normalize(vmin=-50, vmax=10),
    )


import ast
from django.db.models import Q
from django.db import transaction
from django.core.exceptions import ValidationError as DjangoValidationError
from rest_framework.permissions import IsAuthenticated
from rest_framework.exceptions import ValidationError
from rest_framework.generics import ListAPIView

from common_config.api_code import HTTP_201_CREATED, HTTP_400_BAD_REQUEST, HTTP_OK, HTTP_500_INTERNAL_SERVER_ERROR
from common_config.api_message import ADD_SERVICE, UPDATE_SERVICE, INVALID_PAGE_SIZE, \
    DELETE_SERVICE, EXTRA_QUERY_PARAMS, INVALID_PAGE_NUMBER, INVALID_BOOLEAN_FLAG, BLANK_PARAM, INVALID_SORT_BY, \
    INVALID_SORT_BY_FIELD_PARAM, REQUIRED_PARAMS, INVALID_STATUS_FILTER, INVALID_SERVICE_IMAGE_ID
from common_config.constant import SERVICE_CATEGORY
from common_config.logger.logging_handler import logger
from common_config.generics import get_object_or_404
from utils.api_response import APIResponse
from utils.permissions import IsAuthorized
from utils.pagination import Pagination
from utils.views.service import ServiceListCreateMixin, ServiceRetrieveUpdateDeleteMixin

from services.models.service import Service
from services.serializers.service import ServiceCreateSerializer, ServiceViewSerializer, ServiceListSerializer, \
    ServiceUpdateSerializer
from price_groups.tasks.store_service import linked_services_to_store_task, linked_service_and_options_to_store_task

class ServiceListCreateView(ServiceListCreateMixin):
    """
    An Api View which provides a method to add new service or view list services.
    Accepts the following GET/POST header parameters: access token
    Returns the success/fail message.
    """
    queryset = Service.objects.all()
    serializer_class = ServiceCreateSerializer
    pagination_class = Pagination
    permission_classes = (IsAuthenticated, IsAuthorized,)
    permission_required = ('add_service', 'list_service',)
    query_filter_params = ["is_active", "include_deleted", "page", "page_size", "status", "sort_by", "search",
                           "sort_by_field"]

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.errors = dict()
        self.params = dict()

    def validate_query_param(self, page_size, page):
        # check pre define query parameter if contain extra query param then raise error message
        if len(self.params) > 0 and not all(key in self.query_filter_params for key in self.params.keys()):
            extra_param = [key for key in self.params if key not in self.query_filter_params]
            self.errors.setdefault("message", []).append(EXTRA_QUERY_PARAMS.format(extra_param))

        # check page size must  number
        if "page_size" in self.params and not page_size.isnumeric():
            self.errors.setdefault("page_size", []).append(INVALID_PAGE_SIZE)

        if "page" in self.params and not page.isnumeric():
            self.errors.setdefault("page", []).append(INVALID_PAGE_NUMBER)

        if "status" in self.params:
            try:
                self.params['status'] = ast.literal_eval(self.params['status'])
            except Exception as err:
                self.errors.setdefault("status", []).append(INVALID_STATUS_FILTER.format(
                    type(self.params['status']).__name__))

            if not isinstance(self.params['status'], list):
                self.errors.setdefault("status", []).append(INVALID_STATUS_FILTER.format(
                    type(self.params['status']).__name__))

        if "is_active" in self.params:
            try:
                eval(self.params['is_active'])
            except Exception as err:
                self.errors.setdefault("is_active", []).append(
                    INVALID_BOOLEAN_FLAG.format("is_active", self.params['is_active']))

        if "sort_by" in self.params:
            if self.params['sort_by'] == "":
                self.errors.setdefault("sort_by", []).append(BLANK_PARAM)
            elif self.params['sort_by'].lower() not in ["asc", "desc"]:
                self.errors.setdefault("sort_by", []).append(INVALID_SORT_BY.format(self.params['sort_by']))

        if "search" in self.params and self.params['search'] == "":
            self.errors.setdefault("search", []).append(BLANK_PARAM)

        if "sort_by_field" in self.params and self.params['sort_by_field'] not in ["name", "description", "status",
                                                                                "price"]:
            self.errors.setdefault("sort_by_field", []).append(INVALID_SORT_BY_FIELD_PARAM)

        if "sort_by_field" in self.params and "sort_by" not in self.params:
            self.errors.setdefault("sort_by", []).append(REQUIRED_PARAMS)

        if "include_deleted" in self.params:
            try:
                eval(self.params['include_deleted'])
            except Exception as err:
                self.errors.setdefault("include_deleted", []).append(
                    INVALID_BOOLEAN_FLAG.format("include_deleted", self.params['include_deleted']))
            else:
                if not self.errors:
                    # validate view soft deleted object view permission
                    IsAuthorized.has_include_deleted_permission(self.request, "list_service")

    def filter_queryset(self, params):
        filter_kwargs = {'is_active': True}
        if "is_active" in params and params['is_active'] in ['False']:
            filter_kwargs['is_active'] = False

        if "status" in params:
            filter_kwargs['status__in'] = params.get('status')

        if "sort_by_field" in params:
            if params['sort_by_field'] == "name":
                sort_by_field = "name"

            elif params['sort_by_field'] == "status":
                STATUS_CHOICE = Service.STATUS_CHOICES

                # sort service status
                service_status = sorted(STATUS_CHOICE, key=lambda tup: tup[1], reverse=True)

                # get sorted status
                sorted_list = [x[0] for x in service_status]

                from django.db.models import Case, When

                # sort by field
                sort_by_field = Case(
                    *[When(status=status, then=pos) for pos, status in enumerate(sorted_list)])

            elif params['sort_by_field'] == "description":
                sort_by_field = "description"

            else:
                sort_by_field = "price"
        else:
            sort_by_field = "created_on"

        query = Q()

        if "search" in params:
            query = Q(name__icontains=params['search']) | Q(description__icontains=params['search']) | \
                    Q(Q(category_tags__name__icontains=params['search']) &
                      Q(category_tags__entity_type=SERVICE_CATEGORY))

        for item in filter_kwargs:
            query = query & Q(**{item: filter_kwargs[item]})

        if "sort_by" in params and params['sort_by'] == "asc":
            return self.queryset.filter(query).order_by(sort_by_field)

        return self.queryset.filter(query).order_by(sort_by_field).reverse()

    def get(self, request, *args, **kwargs):
        """
        In this method validate request query parameters and filter and return service list.
        return success/error message.
        """
        self.params = request.query_params.copy()
        page_size = self.params.get('page_size', None)
        page = self.params.get('page', None)

        # validate sales order params
        self.validate_query_param(page_size, page)

        if self.errors:
            return APIResponse(self.errors, HTTP_400_BAD_REQUEST)

        error_msg, status_code = None, None

        try:
            # filter and get all service based on query params
            queryset = self.filter_queryset(self.params)
        except DjangoValidationError as err:
            error_msg, status_code = err.args[0], HTTP_400_BAD_REQUEST
        except Exception as err:
            logger.error("Unexpected error occurred :  %s.", err.args[0])
            error_msg, status_code = err.args[0], HTTP_500_INTERNAL_SERVER_ERROR

        if error_msg is not None:
            return APIResponse({"message": error_msg}, status_code)

        is_pagination = False

        # set api request page number
        if page is not None:
            self.paginator.page = page
            is_pagination = True

            # set request api page size number
            if page_size is None:
                page_size = 10

            self.paginator.page_size = page_size

        return self.paginator.generate_response(queryset, ServiceListSerializer, request, is_pagination)

    @transaction.atomic
    def post(self, request, *args, **kwargs):
        """
        In this method validate service from data and created new service.
        return success/error message.
        """
        request_data = request.data.copy()

        try:
            # validate service and service option fields value
            serializer, validate_data = self.validate(request_data)
        except ValidationError as err:
            return APIResponse(err.args[0], HTTP_400_BAD_REQUEST)
        except Exception as err:
            logger.error("Unexpected error occurred :  %s.", err)
            return APIResponse({"message": err.args[0]}, HTTP_400_BAD_REQUEST)

        # get last transaction save point id
        sid = transaction.savepoint()

        try:
            # add new service
            instance, priceGroupServiceIdList = serializer.create(validate_data)
        except ValidationError as err:
            # roll back transaction if any exception occur while adding service and service option
            transaction.savepoint_rollback(sid)
            return APIResponse(err.args[0], HTTP_400_BAD_REQUEST)
        except Exception as err:
            # roll back transaction if any exception occur while adding service and service option
            transaction.savepoint_rollback(sid)
            logger.error("Unexpected error occurred :  %s.", err.args[0])
            return APIResponse({"message": err.args[0]}, HTTP_400_BAD_REQUEST)

        # convert model object into json
        data = ServiceViewSerializer(instance).data
        data['message'] = ADD_SERVICE

        if priceGroupServiceIdList:
            # system user assign services to store
            linked_services_to_store_task.delay({'priceGroupServiceIdList': priceGroupServiceIdList})

        return APIResponse(data, HTTP_201_CREATED)

class ServiceRetrieveUpdateDeleteView(ServiceRetrieveUpdateDeleteMixin):
    """
    An Api View which provides a method to get, update and delete service.
    Accepts the following GET/PUT/DELETE header parameters: access token
    Returns the success/fail message.
    """

    queryset = Service.objects.all()
    serializer_class = ServiceUpdateSerializer
    permission_classes = (IsAuthenticated, IsAuthorized,)
    permission_required = ('change_service', 'view_service', 'delete_service',)
    lookup_field = 'pk'

    def get_object(self):
        queryset = self.filter_queryset(self.get_queryset())

        # Perform the lookup filtering.
        lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
        filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}

        # get object
        obj = get_object_or_404(queryset, "service_id", **filter_kwargs)
        return obj

    def get(self, request, *args, **kwargs):
        # get service object
        instance = self.get_object()

        # serialize service objects
        serializer = ServiceViewSerializer(instance)
        return APIResponse(serializer.data, HTTP_OK)

    @transaction.atomic
    def put(self, request, *args, **kwargs):
        # get service object
        instance = self.get_object()

        # get request form data
        request_data = request.data

        try:
            # validate service and service option fields value
            serializer, validated_data = self.validate(request_data)
        except ValidationError as err:
            return APIResponse(err.args[0], HTTP_400_BAD_REQUEST)
        except Exception as err:
            logger.error("Unexpected error occurred :  %s.", err)
            return APIResponse({"message": err.args[0]}, HTTP_400_BAD_REQUEST)

        if "del_images" in validated_data and len(validated_data['del_images']) > 0:
            del_images = validated_data.get("del_images")
            errors = {}
            images = [x.id for x in instance.images.all()]

            for x in del_images:
                if x.id not in images:
                    errors.setdefault("del_images", []).append(INVALID_SERVICE_IMAGE_ID.format(x.id))

            if len(errors) > 0:
                return APIResponse(errors, HTTP_400_BAD_REQUEST)

        # get last transaction save point id
        sid = transaction.savepoint()

        try:
            # update service
            instance, priceGroupServiceIdList = serializer.update(instance, validated_data)
        except ValidationError as err:
            logger.error("validation error occurred 1 :  %s.", err.args[0])
            # roll back transaction if any exception occur while adding service and service option
            transaction.savepoint_rollback(sid)
            return APIResponse(err.args[0], HTTP_400_BAD_REQUEST)
        except Exception as err:
            logger.error("Unexpected error occurred 2 :  %s.", err.args[0])
            # roll back transaction if any exception occur while update service and service option
            transaction.savepoint_rollback(sid)
            return APIResponse({"message": err.args[0]}, HTTP_400_BAD_REQUEST)

        # convert model object into json
        data = ServiceViewSerializer(instance).data
        data['message'] = UPDATE_SERVICE

        task_payload = {}
        if priceGroupServiceIdList:
            task_payload['priceGroupServiceIdList'] = priceGroupServiceIdList

        if "createOptionIds" in request.session:
            task_payload['createOptionIds'] = request.session['createOptionIds']
            del request.session['createOptionIds']

        if task_payload:
            # system user assign services to store
            linked_service_and_options_to_store_task.delay(task_payload)

        return APIResponse(data, HTTP_OK)

    @transaction.atomic
    def delete(self, request, *args, **kwargs):
        # validate and get service object
        instance = self.get_object()

        # get last transaction save point id
        sid = transaction.savepoint()

        try:
            # soft delete service
            instance.delete()
        except Exception as err:
            # roll back transaction if any exception occur while delete service
            transaction.savepoint_rollback(sid)
            logger.error("Unexpected error occurred :  %s.", err.args[0])
            return APIResponse({"message": err.args[0]}, HTTP_400_BAD_REQUEST)

        return APIResponse({'message': DELETE_SERVICE}, HTTP_OK)

class UpdateServiceOptionSequenceNumber(ListAPIView):
    """
    An Api View which provides a method to update service option sequence number.
    Accepts the following GET header parameters: access token
    Returns the success/fail message.
    """

    queryset = Service.objects.all()
    permission_classes = (IsAuthenticated, IsAuthorized,)
    permission_required = ('change_service',)

    def get(self, request, *args, **kwargs):
        services = Service.objects.all()

        for service_obj in services:

            options = service_obj.options.all().order_by("id")
            sequence = 1

            for option_obj in options:
                option_obj.sequence = sequence
                option_obj.save()

                # update price group service option
                for price_list_option_obj in option_obj.price_group_options.all():
                    price_list_option_obj.sequence = sequence
                    price_list_option_obj.save()

                sequence += 1

        return APIResponse({'message': "Service option sequence updated successfully."}, HTTP_OK)


from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium import webdriver
import time

'''
제가 실행하면 보이나요
python3 test.py
쳐보실래요??
저만 실행 되나요?? 안되는데 그러면 ㅠㅠ

맥으로 하는거라 리팩토링하면서 하고있어요

지금 날짜 찾는거까진 했거든요 이제 몇일인지 찾아야해요
ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 함 봐볼까여
'''

'''
근데 그거 그냥 코드로 박으면 안되나여? 궁금하네여 예
'''

options = webdriver.ChromeOptions()
options.add_argument("window-size=800,600")

driver = webdriver.Chrome()
wait = WebDriverWait(driver, 10)
url = "https://ticket.interpark.com/Gate/TPLogin.asp"
driver.get(url)

def interpark_login():  # 인터파크 로그인
    driver.switch_to.frame(driver.find_element(By.TAG_NAME, "iframe"))

    driver.find_element(By.ID, "userId").send_keys("chlwldnjs0416")
    driver.find_element(By.ID, "userPwd").send_keys("#Chl4689056")
    driver.find_element(By.ID, "btn_login").click()

def booking_number_site():  # 예약번호 입력 후, 입장
    driver.get(
        "http://poticket.interpark.com/Book/BookSession.asp?GroupCode="
        # + showcode_entry.get()
        + "23002291"
    )

# def date_select():
#     # Select date
#     while True:
#         driver.switch_to.frame(driver.find_element(By.ID, "ifrmBookStep"))
#         # if int(calender_entry.get()) > 0:  # 날짜 설정
#         if int(1) > 0:  # 날짜 설정
#             # for i in range(int(calender_entry.get())): # 해당 월 아닐시 +1씩 증가하여 해당 월 찾기.
#             for i in range(int(1)):  # +1씩 증가하여 해당 월 찾기.:) 날짜 설정과 같은 넘버로 해야함.
#                 driver.find_element(
#                     By.XPATH, "/html/body/div/div[1]/div[1]/div/span[3]").click()
#                 try:
#                     '''
#                     회차 클릭 해야함.
#                     '''
#                     time.sleep(100)
#                     driver.find_element(
#                         # By.XPATH, '(//*[@id="CellPlayDate"])' + "[" + date_entry.get() + "]"  # 회차 설정
#                         # By.XPATH, '(//*[@id="CellPlayDate"])' + "[" + 21 + "]").click()  # 회차 설정
#                         By.XPATH, '(//*[@id="CellPlayDate"])' + "[" + 21 + "]").click()  # 회차 설정
#                     break
#                 except NoSuchElementException:
#                     print("NoSearch")
#                     #         # link_go()
#                     #         # go()

#                     # # Select round
#                     # # round_xpath = f"/html/body/div/div[3]/div[1]/div/span/ul/li[{round_entry.get()}]/a"
#                     # round_xpath = f"/html/body/div/div[3]/div[1]/div/span/ul/li['10']/a"
#                     # wait.until(EC.element_to_be_clickable((By.XPATH, round_xpath))).click()

#                     # # Click next button
#                     # driver.switch_to.default_content()
#                     # driver.find_element(By.ID, "LargeNextBtnImage").click()

def date_select():
    day_value = 23
    # 날짜
    while True:
        driver.switch_to.frame(driver.find_element(By.ID, "ifrmBookStep"))
        if int(1) == 0:
            pass
        elif int(1) >= 1:
            for i in range(1, int(1) + 1):
                driver.find_element(
                    By.XPATH, "/html/body/div/div[1]/div[1]/div/span[3]"
                ).click()
        try:
            driver.find_element(
                By.XPATH, '(//*[@id="CellPlayDate"])' +
                "[" + day_value + "]"
            ).click()
            break
        except NoSuchElementException:
            #     # link_go()
            #     # go()
            #     print("Element 못찾음.")
            time.sleep(1111)

    # 회차
    wait.until(
        EC.element_to_be_clickable(
            (
                By.XPATH,
                "/html/body/div/div[3]/div[1]/div/span/ul/li["
                + round_entry.get()
                + "]/a",
            )
        )
    ).click()
    driver.switch_to.default_content()
    driver.find_element(By.ID, "LargeNextBtnImage").click()

def find_random_seat():  # 좌석 무작위로 설정
    driver.switch_to.default_content()
    seat_frame = driver.find_element(By.NAME, "ifrmSeat")
    driver.switch_to.frame(seat_frame)

    # wait.until(EC.presence_of_element_located(
    # ))

interpark_login()  # 예약번호 입력 후, 입장
booking_number_site()  # 예약번호 입력 후, 입장
date_select()  # 상품 날짜 찾기.

# find_random_seat() # 좌석 무작위로 설정


import sys
from PyQt6 import QtCore, QtGui, QtWidgets
from CurConUi import Ui_MainWindow
from currency_converter import CurrencyConverter

class CurrencyConv(QtWidgets.QMainWindow):
    def __init__(self):
        super(CurrencyConv, self).__init__()

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.init_ui()

    def init_ui(self):
        self.ui.line_new_currency.setPlaceholderText("В какую валюту перевести")
        self.ui.line_old_currency.setPlaceholderText("Из какой валюты перевести")
        self.ui.line_old_amount.setPlaceholderText("У вас было")
        self.ui.button_convert.clicked.connect(self.convert)

    #        self.ui.button_convert.setObjectName()

    def convert(self):
        converter = CurrencyConverter()
        old_currency = self.ui.line_old_currency.text().upper()
        new_currency = self.ui.line_new_currency.text().upper()
        old_amount = self.ui.line_old_amount.text()
        if old_amount.isdigit() and old_currency and new_currency:
            new_amount = round(converter.convert(int(old_amount), f"{old_currency}", f"{new_currency}"), 2)
            self.ui.line_new_amount.setText(str(new_amount))
        else:
            self.ui.line_new_amount.setText("Ошибка ввода")

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    application = CurrencyConv()
    application.show()

    sys.exit(app.exec())


from __future__ import absolute_import

import logging
import numpy as np

from .import utils
from .import sampling

from sklearn.preprocessing import MultiLabelBinarizer, LabelBinarizer
from sklearn.model_selection import StratifiedShuffleSplit

logger = logging.getLogger(__name__)

class Dataset(object):

    def __init__(self, inputs, labels, test_indices=None, **kwargs):
        """Encapsulates all pieces of data to run an experiment. This is basically a bag of items that makes it
        easy to serialize and deserialize everything as a unit.

        Args:
            inputs: The raw model inputs. This can be set to None if you dont want
                to serialize this value when you save the dataset.
            labels: The raw output labels.
            test_indices: The optional test indices to use. Ideally, this should be generated one time and reused
                across experiments to make results comparable. `generate_test_indices` can be used generate first
                time indices.
            **kwargs: Additional key value items to store.
        """
        self.X = np.array(inputs)
        self.y = np.array(labels)
        for key, value in kwargs.items():
            setattr(self, key, value)

        self._test_indices = None
        self._train_indices = None
        self.test_indices = test_indices

        self.is_multi_label = isinstance(labels[0], (set, list, tuple))
        self.label_encoder = MultiLabelBinarizer() if self.is_multi_label else LabelBinarizer()
        self.y = self.label_encoder.fit_transform(self.y).flatten()

    def update_test_indices(self, test_size=0.1):
        """Updates `test_indices` property with indices of `test_size` proportion.

        Args:
            test_size: The test proportion in [0, 1] (Default value: 0.1)
        """
        if self.is_multi_label:
            self._train_indices, self._test_indices = sampling.multi_label_train_test_split(self.y, test_size)
        else:
            sss = StratifiedShuffleSplit(n_splits=1, test_size=test_size)
            self._train_indices, self._test_indices = next(sss.split(self.X, self.y))

    def save(self, file_path):
        """Serializes this dataset to a file.

        Args:
            file_path: The file path to use.
        """
        utils.dump(self, file_path)

    def train_val_split(self, split_ratio=0.1):
        """Generates train and validation sets from the training indices.

        Args:
            split_ratio: The split proportion in [0, 1] (Default value: 0.1)

        Returns:
            The stratified train and val subsets. Multi-label outputs are handled as well.
        """
        if self.is_multi_label:
            train_indices, val_indices = sampling.multi_label_train_test_split(self.y, split_ratio)
        else:
            sss = StratifiedShuffleSplit(n_splits=1, test_size=split_ratio)
            train_indices, val_indices = next(sss.split(self.X, self.y))
        return self.X[train_indices], self.X[val_indices], self.y[train_indices], self.y[val_indices]

    @staticmethod
    def load(file_path):
        """Loads the dataset from a file.

        Args:
            file_path: The file path to use.

        Returns:
            The `Dataset` instance.
        """
        return utils.load(file_path)

    @property
    def test_indices(self):
        return self._test_indices

    @test_indices.setter
    def test_indices(self, test_indices):
        if test_indices is None:
            self._train_indices = np.arange(0, len(self.y))
        else:
            self._test_indices = test_indices
            self._train_indices = np.setdiff1d(np.arange(0, len(self.y)), self.test_indices)

    @property
    def train_indices(self):
        return self._train_indices

    @property
    def labels(self):
        return self.label_encoder.classes_

    @property
    def num_classes(self):
        if len(self.y.shape) == 1:
            return 1
        else:
            return len(self.labels)


import scrapy

class CjSpider(scrapy.Spider):
    name = 'cj'
    # allowed_domains = ['caijing.com']
    start_urls = ['https://www.dyxhw.com/']

    def parse(self, response):
        typess = response.xpath('//div[@class="nav clearfix"]/a[@class="j_ch_nav _block_news_menu"]/@href').getall()
        for one_type in typess:
            # print(one_type)
            yield scrapy.Request(url=one_type, callback=self.parse_types)

    def parse_types(self, response):
        news_links = response.xpath('//ul[@class="list14 ml10"]/li/a/@href').getall()
        for news_link in news_links:
            # print(news_link)
            yield scrapy.Request(url=news_link, callback=self.parse_detial)

    def parse_detial(self, response):
        title = response.xpath('//h1[@class="title"]/text()').get()
        contents = response.xpath('//div[@class="clearfix"]/p/text()').getall()
        content = '\n'.join(x for x in contents)
        recurse = response.xpath('//div[@class="info fl"]//tr/td/text()').get().strip()
        pubtime = response.xpath('//div[@class="info fl"]//span[@class="pubTime"]/text()').get()

        item = dict()
        item['title'] = title
        item['content'] = content
        item['pubtime'] = pubtime
        yield item

        rela_article = response.xpath('//div[@class="pic-list clearfix"]//h3/a/@href').getall()
        if rela_article:
            for rela in rela_article:
                yield scrapy.Request(url=rela, callback=self.parse_detial)


# --------------------------------------------------------
# Licensed under The MIT License [see LICENSE for details]
# --------------------------------------------------------

import numpy as np
import os
import sys
from transforms3d.quaternions import *
from transforms3d.euler import *
from transforms3d.axangles import *
import random
from tensorboardX import SummaryWriter
from scipy.spatial import cKDTree

import scipy.io as sio
import IPython
import time
from torch import nn
from torch import optim
import torch
import torch.nn.functional as F
from torch.optim import Adam

from collections import deque
import tabulate
import cv2
import matplotlib.pyplot as plt
import yaml
import core
import copy
import math
from easydict import EasyDict as edict
from pointnet2_ops.pointnet2_utils import furthest_point_sample, gather_operation

import colorsys
import psutil
import GPUtil
from core.common_utils import *
import pybullet as p

HAS_PLANNER_INSTALLED = True
try:
    from OMG.ycb_render.robotPose import robot_pykdl
except:
    HAS_PLANNER_INSTALLED = False

# global variables
V = cam_V =  [[-0.9351, 0.3518, 0.0428, 0.3037],
              [0.2065, 0.639, -0.741, 0.132],
              [-0.2881, -0.684, -0.6702, 1.8803],
              [0.0, 0.0, 0.0, 1.0]]

hand_finger_point = np.array([ [ 0.,  0.,  0.   , -0.   ,  0.   , -0.   ],
                               [ 0.,  0.,  0.053, -0.053,  0.053, -0.053],
                               [ 0.,  0.,  0.075,  0.075,  0.105,  0.105]])
anchor_seeds = np.array([
                        [0.0, -1.285, 0, -2.356, 0.0, 1.571, 0.785],
                        [2.5, 0.23, -2.89, -1.69, 0.056, 1.46, -1.27],
                        [2.8, 0.23, -2.89, -1.69, 0.056, 1.46, -1.27],
                        [2, 0.23, -2.89, -1.69, 0.056, 1.46, -1.27],
                        [2.5, 0.83, -2.89, -1.69, 0.056, 1.46, -1.27],
                        [0.049, 1.22, -1.87, -0.67, 2.12, 0.99, -0.85],
                        [-2.28, -0.43, 2.47, -1.35, 0.62, 2.28, -0.27],
                        [-2.02, -1.29, 2.20, -0.83, 0.22, 1.18, 0.74],
                        [-2.2, 0.03, -2.89, -1.69, 0.056, 1.46, -1.27],
                        [-2.5, -0.71, -2.73, -0.82, -0.7, 0.62, -0.56],
                        [-2, -0.71, -2.73, -0.82, -0.7, 0.62, -0.56],
                        [-2.66, -0.55, 2.06, -1.77, 0.96, 1.77, -1.35],
                        [1.51, -1.48, -1.12, -1.55, -1.57, 1.15, 0.24],
                        [-2.61, -0.98, 2.26, -0.85, 0.61, 1.64, 0.23]
                        ])
renderer = None
robot = None
robot_points = None

panda = None
panda_clients = []

def require_panda(num=1):
    global panda, panda_clients
    if panda is None:
        from env.panda_gripper_hand_camera import Panda
        import pybullet_utils.bullet_client as bc
        panda_clients = [bc.BulletClient(connection_mode=p.DIRECT) for i in range(num)]
        panda = [Panda(stepsize=1./ 1000., base_shift=[-0.05, 0.0, 10.], bullet_client=panda_clients[i]) for i in range(num)] # -0.65
    return panda, panda_clients

def require_robot(new=False):
    if new: return robot_pykdl.robot_kinematics(None, data_path='../../../')
    global robot
    if robot is None:
        robot = robot_pykdl.robot_kinematics(None, data_path='../../../')
    return robot

def require_renderer(large_fov=False, offset=False ):
    global renderer, robot
    if  renderer is None :
        from OMG.ycb_render.ycb_renderer import YCBRenderer

        width, height = 640, 480
        renderer = YCBRenderer(width=width, height=height, offset=offset, gpu_id=0)
        if not large_fov:
            renderer.set_projection_matrix(width, height, width * 0.8, width * 0.8, width / 2, height / 2, 0.1, 6)
            renderer.set_camera_default()
        else:
            renderer.set_fov(90)
        models = ["link1", "link2", "link3", "link4", "link5", "link6", "link7", "hand", "finger", "finger"]
        obj_paths = ["data/robots/{}.DAE".format(item) for item in models]
        renderer.load_objects(obj_paths)
        robot = require_robot()
    return renderer, robot

def truncated_normal(tensor, mean=0, std=1, trunc_std=2):
    size = tensor.shape
    tmp = tensor.new_empty(size + (8,)).normal_() # 4
    valid = (tmp < trunc_std) & (tmp > -trunc_std)
    ind = valid.max(-1, keepdim=True)[1]
    tensor.data.copy_(tmp.gather(-1, ind).squeeze(-1))
    tensor.data.mul_(std).add_(mean)
    return tensor

def sample_gaussian(size, truncate_std=None, device=None):
    y = torch.randn(*size).float()
    y = y if device is None else y.to(device)
    if truncate_std is not None:
        truncated_normal(y, mean=0, std=1, trunc_std=truncate_std)
    return y

def vis_network_input(xyz, xyz_features):
    for i in range(len(xyzs)):
        renderer, _ = require_renderer()
        vis_point(renderer, xyz_features[i], interact=2)

def get_usage():
    GPUs = GPUtil.getGPUs()
    memory_usage = psutil.virtual_memory().percent
    gpu_usage = max([GPU.memoryUsed for GPU in GPUs])
    return gpu_usage, memory_usage

def solve_ik(joints, pose):
    """
    For simulating trajectory
    """
    ik = robot.inverse_kinematics_trac_ik(pose[:3], ros_quat(pose[3:]), seed=joints[:7])
    if ik is not None:
        joints = np.append(np.array(ik), [0, 0.04, 0.04])
    return joints

def bullet_ik(pandas, joints, poses, panda_clients): # simulate
    target_joints = []
    for panda, joint, p_client, pose in zip(pandas, joints, panda_clients, poses):
        panda.reset(np.array(joint).flatten())
        pos, orn = pose[:3], ros_quat(pose[3:])

        target_joints.append(np.array(p_client.calculateInverseKinematics(panda.pandaUid,
                                      panda.pandaEndEffectorIndex, pos, orn)))

    return np.stack(target_joints, axis=0)

def generate_simulated_learner_trajectory(point_state, joints, agent, remain_timestep, max_traj_num=1, vis=False, gaddpg=False):
    """
    use the current point cloud and bullet kinemetics to simulate observation and action for a trajectory
    extract the stored plan in the dataset for plan encoding
    param: 4 x N, 9
    """
    MAX_CLIENT_NUM = max(agent.test_traj_num, 8)
    pandas, panda_clients = require_panda(MAX_CLIENT_NUM)
    num = len(point_state)

    if  num > 1:
        init_joints = joints[0].flatten()
        total_step = int(remain_timestep[0])
    else:
        init_joints = joints.flatten()
        total_step  = remain_timestep

    pandas = pandas[:num]
    panda_clients = panda_clients[:num]
    ef_pose = []
    for panda, p_client in zip(pandas, panda_clients):
        panda.reset(joints=init_joints.flatten())
        pos, orn = p_client.getLinkState(panda.pandaUid, panda.pandaEndEffectorIndex)[:2]
        ef_pose.append(unpack_pose(list(pos) + [orn[3], orn[0], orn[1], orn[2]]))
    ef_pose = np.stack(ef_pose, axis=0)
    sim_point_state = point_state[0]  if len(point_state.shape) == 3  and point_state.shape[0] == 1 else point_state
    sim_pose   = np.stack([np.eye(4)] * num, axis=0)

    plan, sim_states, sim_joints, sim_actions, sim_poses = [], [], [], [], [sim_pose]
    agent.train_traj_feature = False # avoid regenerating traj latent

    # rollout
    step_func = agent.batch_select_action if num  > 1 else agent.select_action

    if  has_check(agent, 'vis_traj') and hasattr(agent, 'gaddpg') and gaddpg: step_func = agent.gaddpg_step #
    for episode_steps in range(total_step):
        state = [[sim_point_state, np.zeros(1)], None, None, None]
        action, _, _, aux_pred = step_func(state, remain_timestep=remain_timestep - episode_steps, curr_joint=joints )
        if len(action.shape) == 1:
            action = action[None]

        action_pose = unpack_action_batch(action)
        ef_pose = np.matmul(ef_pose, action_pose) # joints
        joints = bullet_ik(pandas, joints, pack_pose_batch(ef_pose), panda_clients)
        sim_point_state = se3_transform_pc(se3_inverse_batch(action_pose), sim_point_state)
        plan.append(joints)
        sim_actions.append(action)
        sim_states.append(sim_point_state)
        sim_poses.append(np.matmul(sim_poses[-1], action_pose))
        sim_joints.append(joints)

    sim_poses = list(pack_pose_rot_first_batch(np.concatenate(sim_poses, axis=0)).reshape(-1, num, 7).transpose((1,0,2)))
    agent.train_traj_feature = True

    sim_integer_time = np.arange(total_step, 0, -1)
    traj_time_batch  = sim_integer_time[::-1] / float(total_step)
    return sim_poses, traj_time_batch, sim_joints, sim_states, sim_integer_time

def generate_simulated_expert_trajectory(state, plan, curr_joint, curr_traj_time=0, idx=0, vis=False,robot=None):
    """
    use the current point cloud to simulate observation and action for a trajectory
    extract the stored plan in the dataset for plan encoding
    param: 4 x N, T x 9, 9
    """
    arm_collision_point = get_collision_points()
    if robot is None: robot = require_robot()
    curr_ef_pose  = (robot.forward_kinematics_parallel(wrap_value(curr_joint)[None], offset=False)[0][7])
    global_pc =  np.matmul(curr_ef_pose[:3, :3], state[:3, :-500]) + curr_ef_pose[:3, [3]]
    pc_mask  = state[[3]]
    max_len  = len(plan)
    traj_len = plan_length(plan)
    plan     = plan[:traj_len]

    if traj_len == 0:
        return (state[None], plan, np.zeros(6)[None], pack_pose_rot_first(np.eye(4))[None],
                pack_pose_rot_first(np.eye(4))[None], [1.],
                [[idx, 0, curr_traj_time]])

    plan_link_poses  = robot.forward_kinematics_parallel(wrap_values(plan), offset=False)
    sim_poses   = pack_pose_rot_first_batch(np.matmul(se3_inverse(curr_ef_pose)[None], plan_link_poses[:, 7]))
    sim_goals   = pack_pose_rot_first_batch(np.matmul(se3_inverse_batch(\
                    np.concatenate((curr_ef_pose[None], plan_link_poses[:, 7]), axis=0)), plan_link_poses[-1, 7][None]))

    # not used
    inv_ef_pose = se3_inverse_batch(plan_link_poses[:, 7])
    sim_states = np.matmul(inv_ef_pose[:, :3, :3], global_pc[None]) + inv_ef_pose[:, :3, [3]]
    plan_link_poses = np.matmul(inv_ef_pose[:, None], plan_link_poses)
    collision_point = np.matmul(plan_link_poses[...,:3,:3], arm_collision_point.swapaxes(-1, -2)[:,:3]).swapaxes(-1, -2) + \
                                plan_link_poses[...,:3,[3]].swapaxes(-1, -2)
    collision_point = collision_point.reshape([len(plan_link_poses), -1, 3]).swapaxes(-1, -2)

    sim_states  = np.concatenate((sim_states, collision_point), axis=-1) # robot points
    sim_states  = np.concatenate((sim_states, np.tile(pc_mask[None], (len(sim_states), 1, 1))), axis=1)  # mask
    sim_joints  = np.concatenate((curr_joint[None], plan), axis=0)

    sim_actions = np.zeros([len(sim_joints) - 1, 6]) # not used
    sim_traj_idx = [[idx, j / float(traj_len), curr_traj_time + (j + 1) / max_len] for j in range(traj_len + 1)]
    sim_states = np.concatenate((state[None], sim_states),axis=0) #
    plan       = np.concatenate((curr_joint[None], plan),axis=0) #
    sim_poses  = np.concatenate((pack_pose_rot_first(np.eye(4))[None], sim_poses),axis=0)
    sim_actions  = np.concatenate((sim_actions, np.zeros(6)[None]),axis=0)
    sim_integer_time = np.arange(traj_len + 1, 0, -1)
    return (sim_states, plan, sim_actions, sim_poses, sim_goals, sim_integer_time, sim_traj_idx)

def vis_learner_traj(state, joints, agent, remain_timestep):
    """
    visualize rollout using the current traj_feat
    """
    remain_timestep = min(remain_timestep, 45)
    point_state = state[0][0][None]
    poses = robot.forward_kinematics_parallel(wrap_value(joints)[None], offset=False)[0]
    ef_pose = poses[7]
    packed_poses = [pack_pose(pose) for pose in poses]
    sampler_multi_traj = len(agent.traj_feat_target_test) > 1

    # make copy
    traj_feat_copy = agent.traj_feat.clone()
    agent.traj_feat = agent.traj_feat_target_test # restore sampler latent
    max_traj_num = 1

    if sampler_multi_traj:
        max_traj_num = agent.test_traj_num
        joints = np.tile(joints, (max_traj_num, 1))
        point_state = np.tile(point_state, (max_traj_num, 1, 1))
        remain_timestep = torch.ones(max_traj_num).cuda() * remain_timestep
        vis_traj = generate_simulated_learner_trajectory(point_state, joints, agent, remain_timestep, max_traj_num)[0]
        traj_lines = []
        hues = np.linspace(0., 5./6, max_traj_num )
        colors = np.stack([colorsys.hsv_to_rgb(hue, 1.0, 1.0) for hue in hues]) * 255
        lines_color =  (np.repeat(colors, 2, axis=0).astype(np.int)).tolist()
        for i in range(max_traj_num):
            traj_lines.extend(gripper_traj_lines(ef_pose, vis_traj[i]))
        lines = traj_lines
    else:
        vis_traj = generate_simulated_learner_trajectory(point_state, joints, agent, remain_timestep, max_traj_num)[0]
        traj_line, grasp_line = gripper_traj_lines(ef_pose, vis_traj[0])
        lines = [(traj_line[0], traj_line[1]), (grasp_line[0], grasp_line[1])]
        lines_color = [[0, 0, 255], [0, 0, 255]]

    vis_point_state = state[0][0]
    vis_point_state = vis_point_state[:, 6:] # avoid hand point collision
    target_mask = get_target_mask(vis_point_state)
    point_color = get_point_color(vis_point_state)
    vis_point_state = se3_transform_pc(ef_pose, vis_point_state) # base coordinate
    renderer = require_renderer()[0]
    renderer.vis(packed_poses, range(len(poses)),
        shifted_pose=np.eye(4),
        interact=2,
        V=np.array(V),
        visualize_context={
            "white_bg": True,
            "project_point": [vis_point_state[:3]],
            "project_color": [point_color],
            "point_size": [3],
            "reset_line_point": True,
            "static_buffer": True,
            "line": lines,
            "line_color": lines_color,
        }
    )
    agent.traj_feat = traj_feat_copy

def joint_to_cartesian(new_joints, curr_joint):
    """
    Convert joint space action to task space action by fk
    """
    r = require_robot()
    ef_pose = r.forward_kinematics_parallel(wrap_value(curr_joint)[None], offset=False)[0][-3]
    ef_pose_ = r.forward_kinematics_parallel(wrap_value(new_joints)[None], offset=False)[0][-3]
    rel_pose = se3_inverse(ef_pose).dot(ef_pose_)
    action = np.hstack([rel_pose[:3,3], mat2euler(rel_pose[:3,:3])])
    return action

def check_ngc():
    """
    check for using cluster in training
    """
    GPUs = GPUtil.getGPUs()
    gpu_limit = max([GPU.memoryTotal for GPU in GPUs])
    return (gpu_limit > 14000)

def plan_length(plan):
    if len(plan) == 0: return plan
    if type(plan) is np.ndarray:
        return np.sum(np.abs(plan).sum(-1) > 0)
    else:
        return torch.sum(torch.abs(plan).sum(-1) > 0)

def pad_traj_plan(plan, max_len=50):
    padded_plan = np.zeros((max_len, 9))
    if len(plan) == 0: return padded_plan
    padded_plan[:len(plan)] = plan
    return padded_plan

def update_net_args(config, spec, net_args):
    net_args["model_scale"] = config.feature_input_dim / 512.
    net_args["group_norm"] = True

    if has_check(config, 'sa_channel_concat'):
        spec["net_kwargs"]["action_concat"] = True

    if has_check(config, 'joint_point_state_input'):
        net_args["extra_latent"] += 7

    if  has_check(config, 'feature_option'):
        net_args["feature_option"] = config.feature_option

    if  has_check(config, 'value_overwrite_lr') and config.value_overwrite_lr > 0:
        spec["opt_kwargs"]["lr"] = config.value_overwrite_lr

def update_traj_net_args(config, spec, net_args):
    net_args["feature_extractor_class"] = config.traj_feature_extractor_class
    net_args["num_inputs"]     = config.traj_latent_size
    net_args["hidden_dim"]     = config.feature_input_dim
    net_args["feat_head_dim"]  = config.traj_latent_size
    net_args["config"]         = config
    net_args["model_scale"]    = config.traj_latent_size / 512.
    net_args["feature_option"] = config.st_feature_option
    net_args["group_norm"] = True
    spec["opt_kwargs"]["lr"] = config.traj_net_lr
    net_args["extra_latent"] += 7

def update_traj_sampler_net_args(config, spec, net_args):
    net_args["num_inputs"]     = config.traj_latent_size
    net_args["hidden_dim"]     = config.feature_input_dim
    net_args["feat_head_dim"]  = config.traj_latent_size
    net_args["config"]         = config
    net_args["output_model_scale"] = config.traj_latent_size / 512.
    net_args["model_scale"]    = config.traj_sampler_latent_size / 512.
    net_args["feature_option"] = config.traj_feature_option
    net_args["group_norm"] = True
    net_args["extra_latent"] += 7 # joint
    spec["opt_kwargs"]["lr"] = config.traj_sampler_net_lr

    if config.sampler_extra_abs_time:
        net_args["extra_latent"] += 1 # time

def make_nets_opts_schedulers(model_spec, config, cuda_device="cuda"):
    specs = yaml.load(open(model_spec).read(), Loader=yaml.SafeLoader)  #
    ret = {}
    if torch.cuda.device_count() > 1:
        print("Let's use", torch.cuda.device_count(), "GPUs!")

    for net_name, spec in specs.items():
        net_args = spec.get("net_kwargs", {})

        if net_name == "state_feature_extractor":
            if has_check(config, 'state_feature_extractor'):
                spec["class"] = config.state_feature_extractor
            net_args["input_dim"] = config.channel_num
            update_net_args(config, spec, net_args)

        if net_name == 'traj_feature_extractor':
            if has_check(config, 'train_traj_feature'):
                net_args["input_dim"] = config.channel_num
                update_traj_net_args(config, spec, net_args)
            else:
                continue
        if net_name == 'traj_feature_sampler':
            if has_check(config, 'train_traj_sampler')  :
                net_args["input_dim"] = config.channel_num
                update_traj_sampler_net_args(config, spec, net_args)
            else:
                continue

        print('net_name:', net_name)
        net_class = getattr(core.networks, spec["class"])
        net = net_class(**net_args)

        net = torch.nn.DataParallel(net).to("cuda")
        d = {
            "net": net,
        }

        if "opt" in spec:
            d["opt"] = getattr(optim, spec["opt"])(
            net.parameters(), **spec["opt_kwargs"]
            )
            if len(config.overwrite_feat_milestone) > 0:
                spec["scheduler_kwargs"]["milestones"] = config.overwrite_feat_milestone
            print("schedule:", spec["scheduler_kwargs"]["milestones"])

            d["scheduler"] = getattr(optim.lr_scheduler, spec["scheduler"])(
                d["opt"], **spec["scheduler_kwargs"]
            )
            if hasattr(net.module, "encoder"):
                d["encoder_opt"] = getattr(optim, spec["opt"])(
                    net.module.encoder.parameters(), **spec["opt_kwargs"]
                )
                d["encoder_scheduler"] = getattr(optim.lr_scheduler, spec["scheduler"])(
                    d["encoder_opt"], **spec["scheduler_kwargs"]
                )
            if hasattr(net.module, "value_encoder"):
                d["val_encoder_opt"] = getattr(optim, spec["opt"])(
                    net.module.value_encoder.parameters(), **spec["opt_kwargs"]
                )
                d["val_encoder_scheduler"] = getattr(
                    optim.lr_scheduler, spec["scheduler"]
                )(d["val_encoder_opt"], **spec["scheduler_kwargs"])
        ret[net_name] = d
    return ret

def get_fc_feat_head(input_dim, dim_list, output_dim, acti_func='nn.ReLU', end_with_act=False):
    model_list = [nn.Linear(input_dim, dim_list[0]), nn.ReLU(True)]
    for i in range(1, len(dim_list)):
        model_list.extend([nn.Linear(dim_list[i-1], dim_list[i]), eval(acti_func)(True)])

    model_list.append(nn.Linear(dim_list[-1], output_dim))
    if end_with_act: model_list.append(eval(acti_func)(True))
    return nn.Sequential(*model_list)

def get_info(state, opt="img", IMG_SIZE=(112, 112)):
    if opt == "img":
        return (state[0][1][:3].T * 255).astype(np.uint8)
    if opt == "intr":
        cam_proj = np.array(state[-2][48:]).reshape([4, 4])
        return projection_to_intrinsics(cam_proj, IMG_SIZE[0], IMG_SIZE[1])[:3, :3]
    if opt == "point":
        return state[0][0]

def get_collision_points():
    """
    load collision points with the order of the link list and end effector
    """
    global robot_points
    if robot_points is None:
        collision_file = 'data/robots/all_collision_pts.npy'
        if not os.path.exists(collision_file):
            collision_pts = []
            links = [
                "link1",
                "link2",
                "link3",
                "link4",
                "link5",
                "link6",
                "link7",
                "hand",
                "finger",
                "finger",
            ]
            for i in range(len(links)):
                file = "data/robots/{}.xyz".format(links[i])
                pts = np.loadtxt(file)
                sample_pts = pts[random.sample(range(pts.shape[0]), 50)]
                collision_pts.append(sample_pts)
            collision_pts  = np.array(collision_pts)
            np.save(collision_file, collision_pts)
        else:
            collision_pts = np.load(collision_file)
        robot_points = collision_pts
    return robot_points

def sample_latent(batch_size, latent_size):
    return torch.randn(batch_size, latent_size).cuda()

def add_extra_text(img, extra_text, text_size=0.3, corner='tl'):
    img = img.copy()
    img_ratio = img.shape[0] / 256
    gap = int(15 * img_ratio)
    width, height = img.shape[:2]
    offset_h = 0 if corner.startswith('t') else height - int(50 * img_ratio)
    offset_w = 0 if corner.endswith('l') else int(width - 30 * img_ratio)
    sign = 1 if corner.startswith('t') else -1

    text_size = 0.3 * img_ratio
    for i, t in enumerate(extra_text): #
        cv2.putText(
            img, t,
            (offset_w, offset_h + sign * (gap + i * gap)),
            cv2.FONT_HERSHEY_DUPLEX,
            text_size, [255,0,0] )  # 0.7

    return img

def write_video(
    traj,
    scene_file,
    overhead_traj=None,
    expert_traj=None,
    overhead_expert_traj=None,
    name=0,
    IMG_SIZE=(112, 112),
    output_dir="output_misc/",
    logdir="policy",
    target_name="",
    surfix="",
    use_pred_grasp=False,
    success=False,
    use_value=False,
    extra_text=None
):
    ratio = 1 if expert_traj is None else 2
    result = "success" if success else "failure"
    video_writer = make_video_writer(
        os.path.join(
            output_dir,
            "rl_output_video_{}/{}_rollout.avi".format(surfix, scene_file),
        ),
        int(ratio * IMG_SIZE[0]),
        int(IMG_SIZE[1]),
    )

    text_color = [255, 0, 0] if use_pred_grasp else [0, 255, 0]
    for i in range(len(traj)):
        img = traj[i][..., [2, 1, 0]]
        if expert_traj is not None:
            idx = min(len(expert_traj) - 1, i)
            img = np.concatenate((img, expert_traj[idx][..., [2, 1, 0]]), axis=1)

        img = img.astype(np.uint8)
        if extra_text is not None:
            img = add_extra_text(img, extra_text)
        video_writer.write(img)

    if overhead_traj is not None:
        width, height = overhead_traj[0].shape[1], overhead_traj[0].shape[0]
        overhead_video_writer = make_video_writer(
            os.path.join( output_dir,
                "rl_output_video_{}/{}_overhead_rollout.avi".format(surfix, scene_file)), int(ratio * width), height )

        for i in range(len(overhead_traj)):
            img = overhead_traj[i][..., [2, 1, 0]]
            if overhead_expert_traj is not None:
                idx = min(len(overhead_expert_traj) - 1, i)
                img = np.concatenate((img, overhead_expert_traj[idx][..., [2, 1, 0]]), axis=1)

            overhead_video_writer.write(img.astype(np.uint8))

def append_pointcloud_time(agent, point_state, time_batch=None, traj=True, train=True):
    if not train:
        if not hasattr(agent, 'timestep'):
            traj_integer_time_batch = torch.Tensor([0]).float().cuda()
        else:
            traj_integer_time_batch = agent.timestep
    else:
        traj_integer_time_batch = time_batch

    if agent.sampler_extra_abs_time:
        traj_time_batch = traj_integer_time_batch.view(-1,1,1).expand(-1, -1, point_state.shape[2])
        point_state  = torch.cat((point_state, traj_time_batch), dim=1)

    return point_state

def preprocess_points(config, state_input, curr_joint, time_batch=None, traj=False, append_pc_time=False):
    """
    process point cloud for network input
    """
    if type(curr_joint) is not torch.Tensor:
        curr_joint = torch.from_numpy(curr_joint).cuda().float()
    if type(state_input) is not torch.Tensor:
        state_input = torch.from_numpy(state_input).cuda().float()
    state_input_batch = state_input.clone()
    curr_joint = curr_joint[:, :7]
    if state_input_batch.shape[-1] > 4500: # robot point included
        state_input_batch = remove_robot_pt(state_input_batch)

    if (not traj and has_check(config, 'joint_point_state_input')) or \
                    (traj and has_check(config, 'traj_joint_point_state_input')):
        curr_joint_bc = curr_joint[...,None].expand(-1, -1, state_input_batch.shape[-1])
        state_input_batch = torch.cat((state_input_batch, curr_joint_bc), dim=1)

    if  append_pc_time and hasattr(config, 'test_mode'):
        state_input_batch  = append_pointcloud_time(config, state_input_batch, time_batch, False, not config.test_mode)

    return state_input_batch

def get_point_color(vis_points):
    tgt_mask = get_target_mask(vis_points)
    obs_mask = get_obs_mask(vis_points)
    near_obs_mask = get_near_obs_mask(vis_points)
    rob_mask = get_robot_mask(vis_points)

    target_color = [0, 255, 0]
    obs_color = [255, 0, 0]
    rob_color = [0, 0, 255]
    near_obs_color = [255, 0, 0]

    pt_color = np.zeros_like(vis_points[:3]).T
    pt_color[tgt_mask] = target_color
    pt_color[obs_mask] = obs_color
    pt_color[rob_mask] = rob_color
    pt_color[near_obs_mask] = near_obs_color
    return pt_color

def sample_ef(target, near=0.2, far=0.50):
    # sample a camera extrinsics
    count = 0
    ik = None
    outer_loop_num = 20
    inner_loop_num = 5
    robot = require_robot()
    for _ in range(outer_loop_num):
        theta = np.random.uniform(low=0, high=1*np.pi/2)
        phi = np.random.uniform(low=np.pi/2, high=3*np.pi/2) # half sphere
        r = np.random.uniform(low=near, high=far) # sphere radius
        pos = np.array([r*np.sin(theta)*np.cos(phi), r*np.sin(theta)*np.sin(phi), r*np.cos(theta)])

        trans = pos + target + np.random.uniform(-0.03, 0.03, 3)
        trans[2] = np.clip(trans[2], 0.2, 0.6)
        trans[1] = np.clip(trans[1], -0.3, 0.3)
        trans[0] = np.clip(trans[0], 0.0, 0.5)
        pos = trans - target

        for i in range(inner_loop_num):
            rand_up = np.array([0, 0, -1])
            rand_up = rand_up / np.linalg.norm(rand_up)
            R = inv_lookat(pos, 2 * pos, rand_up).dot(rotZ(-np.pi/2)[:3, :3])
            quat = ros_quat(mat2quat(R))
            ik = robot.inverse_kinematics(trans, quat, seed=anchor_seeds[np.random.randint(len(anchor_seeds))])
            if  ik is not None:
                break
    return ik

def gripper_traj_lines(start_pose, traj_state, joint_output=False, gripper_along=False ):
    ef_lines = []
    gripper_lines = [np.zeros([3, 0]), np.zeros([3, 0])]
    draw_gripper_traj_line = gripper_along

    if joint_output:
        r = require_robot()
        curr_joint = np.concatenate((traj_state, 0.04 * np.ones((len(traj_state), 2))), axis=-1)
        traj_state = r.forward_kinematics_parallel(wrap_values(curr_joint ), offset=False)[:, 7]

    for grasp_idx, grasp in enumerate(traj_state):
        if not joint_output:
            if grasp_idx == 0:
                grasp = np.eye(4)
            elif len(grasp) == 6:
                grasp = unpack_pose_euler(grasp)
            else:
                grasp = unpack_pose_rot_first(grasp)
        grasp_pose = start_pose.dot(grasp)
        line_starts, line_ends = grasp_gripper_lines(grasp_pose[None])
        gripper_lines[0] = np.concatenate((gripper_lines[0], line_starts[0]), axis=-1)
        gripper_lines[1] = np.concatenate((gripper_lines[1], line_ends[0]), axis=-1)
        ef_lines.append(grasp_pose[:3, 3])

    if not draw_gripper_traj_line:
        gripper_lines[0] = gripper_lines[0][:,-5:]
        gripper_lines[1] = gripper_lines[1][:,-5:]
    if len(ef_lines) > 1:
        ef_lines = [[ef_lines[idx], ef_lines[idx+1]] for idx in range(len(ef_lines) - 1)]
        ef_lines = np.array(ef_lines)
        ef_lines = [ef_lines.T[:, 0], ef_lines.T[:, 1]]
    else:
        ef_lines = []
    return [gripper_lines, ef_lines]

def vis_traj(point, curr_joint, traj_state=None, V=cam_V, interact=2, used_renderer=None, gripper_along=False):
    # visualize traj with renderer
    renderer, robot = require_renderer( )

    if type(point) is torch.Tensor:
        point = point.detach().cpu().numpy()

    point = point[0]
    if point.shape(1) != 4096:
        point = point[:,6:-500] #  remove gripper and robot point
    if type(curr_joint) is torch.Tensor:
        curr_joint = curr_joint.detach().cpu().numpy()
    if len(curr_joint) == 7:
        curr_joint = np.append(curr_joint, [0, 0])

    poses_ = robot.forward_kinematics_parallel(wrap_value(curr_joint), offset=False)[0]
    poses_2 = [pack_pose(pose) for pose in poses_]
    point_color = get_point_color(point)
    point = se3_transform_pc(poses_[7], point)

    if traj_state is not None:
        if type(traj_state) is torch.Tensor:
            traj_state = traj_state.detach().cpu().numpy()

        if type(traj_state) is list and len(traj_state) > 4:
            traj_lines = []
            line_colors = get_mask_colors(len(traj_state) * 2 + 5)[5:]

            for i in range(len(traj_state)):
                traj_lines.extend(gripper_traj_lines(poses_[7], traj_state[i]))

        else:
            gripper_lines, ef_lines = gripper_traj_lines(poses_[7], traj_state, gripper_along=gripper_along)
            line_colors = [[255, 255, 0], [0, 0, 255]]
            traj_lines = [gripper_lines, ef_lines]

        rgb = renderer.vis(poses_2, list(range(10)),
        shifted_pose=np.eye(4),
        interact=interact,
        V=np.array(V),
        visualize_context={
            "white_bg": True,
            "project_point": [point[:3]],
            "project_color": [point_color],
            "static_buffer": True,
            "reset_line_point": True,
            "line": traj_lines,
            "line_color": line_colors,
        }
        )

    else:
        rgb = renderer.vis(poses_2, list(range(10)),
        shifted_pose=np.eye(4),
        interact=interact,
        V=np.array(V),
        visualize_context={
            "white_bg": True,
            "project_point": [point[:3]],
            "project_color": [point_color],
            "static_buffer": True,
            "reset_line_point": True,
            "thickness": [2]
        } )

    return rgb

def vis_point(renderer, point_state, window_name='test', interact=1, curr_joint=None, grasp=None, V=None):
    """visualize single point state """
    if type(point_state) is torch.Tensor:
        point_state = point_state.detach().cpu().numpy()
    vis_points = point_state.copy()
    pt_color = get_point_color(vis_points)

    if V is None:
        V =  [[ 0.3021,  0.668,   0.6801,  0.    ],
             [-0.7739, -0.2447,  0.5841,  0.    ],
             [ 0.5566, -0.7028,  0.4431,  1.1434],
             [ 0.,      0.,      0.,      1.    ]]

    line, line_color = [], []
    cls_indexes, poses = [], []

    if grasp is not None:
        line_starts, line_ends = grasp_gripper_lines(unpack_pose_rot_first(grasp.detach().cpu().numpy())[None])
        line = [(line_starts[0], line_ends[0])]
        line_color = [[255, 255, 0]]

    return renderer.vis( poses, cls_indexes,
    shifted_pose=np.eye(4),
    interact=interact,
    V=np.array(V),
    visualize_context={
        "white_bg": True,
        "project_point": [vis_points[:3] ],
        "project_color": [pt_color],
        "point_size": [3],
        "reset_line_point": True,
        "static_buffer": True,
        "line": line,
        "line_color": line_color,
    }
    )

def compose_state_traj(data_list, CONFIG, step=0):
    """downsampling traj """
    downsample_length = (len(data_list[0]) - step) // int(CONFIG.sparsify_traj_ratio)
    idx = list(np.linspace(step, len(data_list[0]) - 1, downsample_length).astype(np.int))
    torch_data_list = []
    for data_idx, data in enumerate(data_list):
        torch_data_list.append(torch.from_numpy(np.stack([data[i] for i in idx], axis=0)).cuda().float())
    return torch_data_list

def update_expert_traj(agent, expert_data_list, cfg, step=0, remote=False):
    """ compute expert traj latent embedding """
    expert_exec_traj = compose_state_traj(expert_data_list, cfg.RL_TRAIN, step)
    if remote:
        recons_traj = agent.select_traj.remote(None,
                    expert_data_list[0][step][None],
                    None,
                    vis=False,
                    remain_timestep=cfg.RL_MAX_STEP,
                    curr_joint=expert_data_list[1][step][None],
                    gt_traj=expert_exec_traj)    # generate the traj latent
    else:
        recons_traj = agent.select_traj(None,
                    expert_data_list[0][step][None],
                    None,
                    vis=False,
                    remain_timestep=cfg.RL_MAX_STEP,
                    curr_joint=expert_data_list[1][step][None],
                    gt_traj=expert_exec_traj)    # generate the traj latent
    return expert_exec_traj, recons_traj, expert_exec_traj[3].detach().cpu().numpy()

def get_gaddpg(path=None, load_joint_trained_model=False):
    """ get pretrained GA-DDPG Models """
    from core.ddpg import DDPG
    gaddpg_dict = edict()
    gaddpg_dict = edict(yaml.load(open("output/demo_model/config.yaml", "r")))
    net_dict = make_nets_opts_schedulers(gaddpg_dict.RL_MODEL_SPEC, gaddpg_dict.RL_TRAIN)

    gaddpg = DDPG(512, PandaTaskSpace6D(), gaddpg_dict.RL_TRAIN)
    gaddpg.setup_feature_extractor(net_dict, True)
    gaddpg.load_model('output/demo_model')
    gaddpg.set_mode(True)
    return gaddpg

def proj_point_img(img, K, offset_pose, points=None, color=(255, 0, 0),
                   vis=False, neg_y=True, traj=None, joint_output=False, last_joint=None,
                   remain_timestep=-1,  gt_goal=None, traj_offset_pose=None, extra_text=None,
                   model_name=None, vis_traj_gradient_color=False):
    # draw traj lines, goal / actions predictions and texts in image plane
    target_mask = get_target_mask(points)
    obs_mask = get_obs_mask(points)
    robot_mask = get_robot_mask(points)
    colors = [[0, 255, 0], [255, 0, 0], [0, 0, 255]]
    img = img.copy()

    # point first
    for i, mask in enumerate([target_mask, obs_mask, robot_mask]):
        points_i = points[:, mask]
        points_xyz = points_i[:3]
        xyz_points = offset_pose[:3, :3].dot(points_xyz) + offset_pose[:3, [3]]
        if neg_y: xyz_points[:2] *= -1
        x, y, valid_idx_mask = valid_3d_to_2d(K, xyz_points, img)
        img[y[valid_idx_mask], x[valid_idx_mask]] = colors[i]

    if traj_offset_pose is None: traj_offset_pose = offset_pose
    if traj is not None and traj[0] is not None:
        if (remain_timestep == -1 or len(traj) == remain_timestep) and type(traj) is not list:
            line_colors = [[255, 255, 0], [0, 255, 255]]
            traj_lines = gripper_traj_lines(traj_offset_pose, traj, joint_output)
        else:
            if type(traj) is list:
                traj_num = len(traj)
                remain_timestep = len(traj[0])
                traj[0] = traj[0][:,:7]
                traj = np.concatenate(traj, axis=0)
            else:
                traj_num = int(len(traj) / remain_timestep)
                remain_timestep = int(remain_timestep)

            traj_lines = []
            hues = np.linspace(0., 5./6, traj_num )
            colors = np.stack([colorsys.hsv_to_rgb(hue, 1.0, 1.0) for hue in hues]) * 255
            line_colors = np.repeat(colors,  2, axis=0)

            for i in range(traj_num):
                traj_lines.extend(gripper_traj_lines(traj_offset_pose, traj[i*remain_timestep:(i+1)*remain_timestep ] ))

        for line_i, lines in enumerate(traj_lines):
            lines = np.array(lines)
            if len(lines) == 0: continue
            if neg_y: lines[:, :2] *= -1
            p_xyz = np.matmul(K, lines)
            x, y = (p_xyz[:,0] / p_xyz[:,2]).astype(np.int), (p_xyz[:,1] / p_xyz[:,2]).astype(np.int)
            x = np.clip(x, 0, img.shape[0] - 1)
            y = np.clip(y, 0, img.shape[1] - 1)

            for i in range(x.shape[1]):
                # avoid clipping issues
                color = line_colors[line_i]
                color = (int(color[0]), int(color[1]), int(color[2]))
                if np.abs(x[0, i] - x[1, i]) > 100 or np.abs(y[0, i] - y[1, i]) > 100:
                    continue
                if line_i == 1 and len(traj_lines) > 4 and not vis_traj_gradient_color:
                    cv2.line(img, (x[0, i], y[0, i]), (x[1, i], y[1, i]), color, 2)
                else:
                    cv2.line(img, (x[0, i], y[0, i]), (x[1, i], y[1, i]), color, 1)

    if extra_text is not None:
        img = add_extra_text(img, extra_text, 1.5) # 0.7
    return img

def draw_grasp_img(img, pose, K, offset_pose, color=(0, 0, 255), vis=False, neg=True ):
    img_cpy = img.copy()
    line_index = [[0, 1, 1, 2, 3], [1, 2, 3, 4, 5]]

    hand_anchor_points = grasp_points_from_pose(pose, offset_pose)
    if neg: hand_anchor_points[:2] *= -1
    p_xyz = K.dot(hand_anchor_points)
    x, y = (p_xyz[0] / p_xyz[2]).astype(np.int), (p_xyz[1] / p_xyz[2]).astype(np.int)
    x = np.clip(x, 0, img.shape[0] - 1)
    y = np.clip(y, 0, img.shape[1] - 1)
    for i in range(len(line_index[0])):
        pt1 = (x[line_index[0][i]], y[line_index[0][i]])
        pt2 = (x[line_index[1][i]], y[line_index[1][i]])
        cv2.line(img_cpy, pt1, pt2, color, 2)

    return img_cpy

def remove_robot_pt(points):
    return points[..., :-500]

def reparameterize(mu, logsigma, truncated=True, fix_eps=None):
    std = torch.exp(logsigma)
    if truncated:
        eps = sample_gaussian(std.shape, truncate_std=2.).cuda()
    else:
        eps = torch.randn_like(std)
    if fix_eps is not None:
        eps = fix_eps
    return mu + eps * std

def has_check(x, prop):
    return hasattr(x, prop) and getattr(x, prop)

def check_scene(env, state=None, start_rot=None, object_performance=None, planner=None,
                scene_name=None, run_iter=0, check_ik=False, CONFIG=None, load_test_scene=False):
    """
    check if a scene is valid by its distance, view, hand direction, target object state, and object counts
    """

    if  load_test_scene :  return name_check(env, object_performance, run_iter)
    MAX_TEST_PER_OBJ = CONFIG.max_test_per_obj
    pose_flag  = pose_check(env, state, start_rot, CONFIG)
    name_flag  = name_check(env, object_performance, run_iter, MAX_TEST_PER_OBJ)
    collision_flag = not env.collided
    check_flag = pose_flag and name_flag and collision_flag
    if check_flag and check_ik:
        goal_validity = planner.expert_plan(return_success=True, check_scene=True)
        if not goal_validity:
            return False
    return check_flag

def sample_scene(env, planner, object_performance=None, scene_file=None, run_iter=0, CONFIG=None, timeout=6.):
    """
    sample scenes with ik filtering
    """
    state = None
    MAX_TEST_PER_OBJ = CONFIG.max_test_per_obj
    start_time = time.time()
    outer_cnt, inner_cnt = CONFIG.scene_sample_check_ik_cnt, CONFIG.scene_sample_inner_cnt
    if CONFIG.index_file == 'filter_shapenet.json':
        inner_cnt *= 3

    for _ in range(outer_cnt):
        for _ in range(inner_cnt):
            if time.time() - start_time > timeout:
                return  state, False
            flag = not test_cnt_check(env, object_performance, run_iter, MAX_TEST_PER_OBJ)

            if flag: break

            state = env.reset(  scene_file=None, init_joints=rand_sample_joint(env, None, CONFIG.ENV_NEAR, CONFIG.ENV_FAR),
                                reset_free=True, enforce_face_target=True )
            cur_ef_pose = env._get_ef_pose(mat=True)
            flag = check_scene(env, state, cur_ef_pose[:3, :3], object_performance,
                               planner, scene_file, run_iter, False, CONFIG)

            if flag: break
        if flag and check_scene(env, state, cur_ef_pose[:3, :3], object_performance,
                                planner, scene_file, run_iter, True, CONFIG):
            break

    return  state, flag

def select_target_point(state, target_pt_num=1024):
    """get target point cloud from scene point cloud """
    point_state = state[0][0]
    target_mask = get_target_mask(point_state)
    point_state = point_state[:4, target_mask]
    gripper_pc  = point_state[:4, :6]
    point_num  = min(point_state.shape[1], target_pt_num)
    obj_pc = regularize_pc_point_count(point_state.T, point_num, False).T
    point_state = np.concatenate((gripper_pc, obj_pc), axis=1)
    return [(point_state, state[0][1])] + state[1:]

def gaddpg_action(gaddpg, state, action, episode_steps, max_steps, curr_joint, return_goal=False):
    """apply GA-DDPG action """
    state = select_target_point(state)

    if state[0][0].shape[1] > 0:
        gaddpg_remain_step = max(min(max_steps-episode_steps + 1, 30), 1)
        print('use gaddpg remaining step: {}...'.format(gaddpg_remain_step))
        action, _, _, aux_pred = gaddpg.select_action(state, remain_timestep=gaddpg_remain_step, curr_joint=curr_joint)
        if return_goal:
            return action, aux_pred
        return action
    return np.zeros(6), np.ones(7) * 0.01

class PandaTaskSpace6D():
    def __init__(self):
        self.high = np.array([0.1,   0.1,  0.1,  np.pi/6,  np.pi/6,  np.pi/6])
        self.low  = np.array([-0.1, -0.1, -0.1, -np.pi/6, -np.pi/6, -np.pi/6])
        self.shape = [6]
        self.bounds = np.vstack([self.low, self.high])

class RobotMLP(nn.Module):
    """ simple Pointnet-Like MLP """
    def __init__(self, in_channels, out_channels, dim=1, gn=False, gn_num=16):
        super(RobotMLP, self).__init__()
        if dim == 1:
            conv = nn.Conv1d
            if gn:
                bn = lambda k: nn.GroupNorm(gn_num, k)
            else:
                bn = nn.BatchNorm1d
        else:
            raise ValueError
        if not isinstance(out_channels, (list, tuple)):
            out_channels = [out_channels]
        layers = []
        for oc in out_channels:
            layers.extend([
                conv(in_channels, oc, 1),
                bn(oc),
                nn.ReLU(True),
            ])
            in_channels = oc
        self.layers = nn.Sequential(*layers)

    def forward(self, inputs, masks=None):
        inp_shape = inputs.shape
        inputs = inputs.view(-1, inputs.shape[-2], inputs.shape[-1])
        x = self.layers(inputs)

        x = torch.max(x, 2, keepdim=True)[0]
        x = x.view(len(x), -1)
        return x

def clean_dir(dst_dir):
    if os.path.exists(dst_dir):
        os.system('rm -rf {}/*'.format(dst_dir))

def get_usage_and_success():
    """Get gpu and memory usages as well as current performance """
    GPUs = GPUtil.getGPUs()
    memory_usage = psutil.virtual_memory().percent
    gpu_usage = max([GPU.memoryUsed for GPU in GPUs])
    return memory_usage, gpu_usage

def get_model_path(output_dir, name, env_name, surfix):
    actor_path = "{}/{}_actor_{}_{}".format(
        output_dir, name, env_name, surfix )
    critic_path = "{}/{}_critic_{}_{}".format(
        output_dir, name, env_name, surfix )
    traj_feat_path = "{}/{}_traj_feat_{}_{}".format(
        output_dir, name, env_name, surfix )
    traj_sampler_path = "{}/{}_traj_sampler_{}_{}".format(
        output_dir, name, env_name, surfix )
    state_feat_path = "{}/{}_state_feat_{}_{}".format(
        output_dir, name, env_name, surfix )
    return actor_path, critic_path, traj_feat_path, traj_sampler_path, state_feat_path

def count_parameters(model):
    return sum(p.numel() for p in model.parameters() if p.requires_grad)

def get_loss_info_dict():
   return {     'bc_loss': deque([0], maxlen=50),
                'policy_grasp_aux_loss': deque([0], maxlen=50),
                'critic_gaddpg_loss': deque([0], maxlen=100),
                'critic_loss': deque([0], maxlen=100),
                'kl_loss': deque([0], maxlen=50),
                'sampler_grasp_aux_loss': deque([0], maxlen=50),
                'sampler_bc_loss': deque([0], maxlen=50),
                'traj_latent_loss': deque([0], maxlen=50),
                'gaddpg_loss':  deque([0], maxlen=50),
                'reward_mask_num': deque([0], maxlen=5),
                'expert_reward_mask_num': deque([0], maxlen=5),
                'value_mean': deque([0], maxlen=5),
                'return_mean': deque([0], maxlen=5),
                'gaddpg_pred_mean': deque([0], maxlen=5),
                'traj_grad': deque([0], maxlen=5),
                'traj_param': deque([0], maxlen=5),
                'policy_param': deque([0], maxlen=5),
                'sampler_mean': deque([0], maxlen=5),
                'traj_num': deque([0], maxlen=5),
                'sampler_logsigma': deque([0], maxlen=5),
                'policy_grad': deque([0], maxlen=5),
                'feat_grad': deque([0], maxlen=5),
                'feat_param': deque([0], maxlen=5),
                'val_feat_grad': deque([0], maxlen=5),
                'val_feat_param': deque([0], maxlen=5),
                'critic_grad': deque([0], maxlen=5),
                'critic_param': deque([0], maxlen=5),
                'train_batch_size': deque([0], maxlen=5),
             }

def flip(x, dim):
    indices = [slice(None)] * x.dim()
    indices[dim] = torch.arange(x.size(dim) - 1, -1, -1, dtype=torch.long, device=x.device)
    return x[tuple(indices)]

def create_bottleneck(input_size, latent_size):
    logmu = nn.Linear(input_size, latent_size)
    logvar = nn.Linear(input_size, latent_size)
    return nn.ModuleList([logmu, logvar])

def get_policy_class(policy_net_name, args):
    policy = getattr(core.networks, policy_net_name)(
        args.num_inputs,
        args.action_dim,
        args.hidden_size,
        args.action_space,
        extra_pred_dim=args.extra_pred_dim,
        config=args,
    ).to('cuda')
    policy_optim = Adam(
       policy.parameters(), lr=args.lr, eps=1e-5, weight_decay=1e-5 )
    policy_scheduler = torch.optim.lr_scheduler.MultiStepLR(
        policy_optim, milestones=args.policy_milestones, gamma=args.lr_gamma)
    policy_target = getattr(core.networks, policy_net_name)(
        args.num_inputs,
        args.action_dim,
        args.hidden_size,
        args.action_space,
        extra_pred_dim=args.extra_pred_dim,
        config=args,
    ).to('cuda')
    return policy, policy_optim, policy_scheduler, policy_target

def get_critic(args):
    model = core.networks.ResidualQNetwork if has_check(args, 'dense_critic') else core.networks.QNetwork
    critic = model(
            args.critic_num_input,
            args.critic_value_dim,
            args.hidden_size,
            extra_pred_dim=args.critic_extra_pred_dim,
        ).cuda()

    critic_optim = Adam(
        critic.parameters(), lr=args.value_lr, eps=1e-5, weight_decay=1e-5 )
    critic_scheduler = torch.optim.lr_scheduler.MultiStepLR(
        critic_optim,
        milestones=args.value_milestones,
        gamma=args.value_lr_gamma,
    )
    critic_target = model(
        args.critic_num_input,
        args.critic_value_dim,
        args.hidden_size,
        extra_pred_dim=args.critic_extra_pred_dim,
    ).cuda()
    return critic, critic_optim, critic_scheduler, critic_target


from .dbtest import (
    DbTest,
    dbconnect
)

import os
from psycopg2.extras import (
    RealDictCursor,
    RealDictRow
)

PATH_TO_SQL_DIR = os.path.abspath(
    os.path.join(
        os.path.dirname(__file__),
        "..",
        "sql"
    )
)

class TestExample(DbTest):
    @dbconnect
    def test_select_organizations(self, conn):
        self.load_fixtures(
            conn,
            os.path.join(PATH_TO_SQL_DIR, "organizations.sql")
        )

        sql = """
        SELECT * FROM organizations;
        """
        with conn.cursor(cursor_factory=RealDictCursor) as cur:
            cur.execute(sql)
            organizations = cur.fetchall()

            assert len(organizations) == 7

    @dbconnect
    def test_count_the_number_of_subordinates(self, conn):
        self.load_fixtures(
            conn,
            os.path.join(PATH_TO_SQL_DIR, "organizations.sql")
        )

        sql = """
        SELECT COUNT(enterprise_sales_enterprise_customers.sales_organization_id) as subordinates_count, organizations."id" from organizations
        LEFT JOIN enterprise_sales_enterprise_customers ON organizations.id=enterprise_sales_enterprise_customers.sales_organization_id
        GROUP BY enterprise_sales_enterprise_customers.sales_organization_id, organizations."id" ORDER BY organizations."id";
        """
        with conn.cursor(cursor_factory=RealDictCursor) as cur:
            cur.execute(sql)
            actual = cur.fetchall()
            assert len(actual) == 7
            assert actual == [
                RealDictRow(**{
                    "subordinates_count": 0,
                    "id": 1,
                })
                , RealDictRow(**{
                    "subordinates_count": 4,
                    "id": 2,
                })
                , RealDictRow(**{
                    "subordinates_count": 0,
                    "id": 3,
                })
                , RealDictRow(**{
                    "subordinates_count": 0,
                    "id": 4,
                })
                , RealDictRow(**{
                    "subordinates_count": 0,
                    "id": 5,
                })
                , RealDictRow(**{
                    "subordinates_count": 1,
                    "id": 6,
                })
                , RealDictRow(**{
                    "subordinates_count": 0,
                    "id": 7,
                })
            ]

    @dbconnect
    def test_calculate_center_of_each_segment(self, conn):
        self.load_fixtures(
            conn,
            os.path.join(PATH_TO_SQL_DIR, "japan_segments.sql")
        )

        sql = """
        SELECT sub_query.id, ST_X(sub_query.bounds_center) as longitude, ST_Y(sub_query.bounds_center) as latitude
        FROM (SELECT japan_segments.id as id, st_centroid(bounds) as bounds_center FROM japan_segments) as sub_query;
        """
        with conn.cursor(cursor_factory=RealDictCursor) as cur:
            cur.execute(sql)
            actual = cur.fetchall()
            assert len(actual) == 10
            assert actual == [
                RealDictRow(**{
                    "id": "KAGOSHIMA_1",
                    "longitude": 130.642228315775,
                    "latitude": 30.7045454545455,
                })
                , RealDictRow(**{
                    "id": "KAGOSHIMA_2",
                    "longitude": 130.694183864916,
                    "latitude": 30.7045454545455,
                })
                , RealDictRow(**{
                    "id": "KAGOSHIMA_3",
                    "longitude": 130.746139414057,
                    "latitude": 30.7045454545455,
                })
                , RealDictRow(**{
                    "id": "KAGOSHIMA_4",
                    "longitude": 129.707028431231,
                    "latitude": 30.75,
                })
                , RealDictRow(**{
                    "id": "KAGOSHIMA_5",
                    "longitude": 129.758983980373,
                    "latitude": 30.75,
                })
                , RealDictRow(**{
                    "id": "KAGOSHIMA_6",
                    "longitude": 129.810939529514,
                    "latitude": 30.75,
                })
                , RealDictRow(**{
                    "id": "KAGOSHIMA_7",
                    "longitude": 129.862895078655,
                    "latitude": 30.75,
                })
                , RealDictRow(**{
                    "id": "KAGOSHIMA_8",
                    "longitude": 129.914850627797,
                    "latitude": 30.75,
                })
                , RealDictRow(**{
                    "id": "KAGOSHIMA_9",
                    "longitude": 129.966806176937,
                    "latitude": 30.75,
                })
                , RealDictRow(**{
                    "id": "KAGOSHIMA_10",
                    "longitude": 130.018761726079,
                    "latitude": 30.75,
                })
            ]

    @dbconnect
    def test_segments_using_geojson_boundary(self, conn):
        self.load_fixtures(
            conn,
            os.path.join(PATH_TO_SQL_DIR, "japan_segments.sql")
        )

        sql = """
        SELECT sub.id from (SELECT * from japan_segments, (SELECT ST_GeomFromEWKT('SRID=4326;POLYGON((130.27313232421875 30.519681272749402,131.02020263671875 30.519681272749402,
        131.02020263671875 30.80909017893796,130.27313232421875 30.80909017893796,130.27313232421875 30.519681272749402))') as boundary) as sub_query) as sub where ST_Contains(sub.boundary, sub.bounds)
        """
        with conn.cursor(cursor_factory=RealDictCursor) as cur:
            cur.execute(sql)
            actual = cur.fetchall()
            print(actual)
            assert len(actual) == 3
            assert actual == [
                RealDictRow(**{
                    "id": "KAGOSHIMA_1",
                })
                , RealDictRow(**{
                    "id": "KAGOSHIMA_2",
                })
                , RealDictRow(**{
                    "id": "KAGOSHIMA_3",
                })
            ]