import os

from todoist.api import TodoistAPI
import click
import yaml
from dateutil import parser
import datetime

def get_param(d, key, label="specification"):
    """Retrieve a value from a dictionary, exit if not present"""
    if key not in d:
        click.echo(f"\tCould not find field {key} in {label}")
        exit(1)
    return d[key]

def parse_steps(steps, target_time):
    """Recursive parsing of process steps, returns list of steps"""
    out = []
    for step in steps:
        name = get_param(step, "name", label="step")
        duration = float(get_param(step, "duration", label=f"step"))
        start_time = target_time - datetime.timedelta(minutes=duration)

        out.append(dict(name=name, start_time=start_time))

        if "steps" in step:
            out += parse_steps(step["steps"], start_time)

    return out

@click.command()
@click.option(
    "--run/--dry-run",
    default=False,
    help="Dry-run only (default) or actually create the tasks in todoist",
)
@click.argument("yml_file", type=click.File("r"))
def plan(yml_file, run):
    click.echo(f"Parsing {yml_file.name}...")
    process = yaml.safe_load(yml_file.read())

    # get required parameters
    todoist_project = get_param(process, "todoist_project")
    process_name = get_param(process, "process_name")

    # get and parse target time
    target_time_str = get_param(process, "target_time")
    target_time = parser.parse(target_time_str)
    click.echo(f"\nPlanning to finish on {str(target_time)}")

    # parse steps
    steps = get_param(process, "steps")
    parsed_steps = parse_steps(steps, target_time)
    print("\nParsed steps:")
    for step in sorted(parsed_steps, key=lambda s: s["start_time"]):
        print(f"\t{str(step['start_time'])}: {step['name']}")

    if run:
        click.echo("\nCreating the tasks...")

        # get API token from environment variables
        token = os.environ["TODOIST_API_TOKEN"]

        # create and sync API instance
        api = TodoistAPI(token=token)
        api.sync()

        # find containing project
        project = [p for p in api.state["projects"] if p["name"] == todoist_project]
        if len(project) != 1:
            click.echo(f"Could not identify todoist project {todoist_project}")
            exit(1)
        project = project[0]

        # add a new section for that project
        section = api.sections.add(process_name, project_id=project["id"])
        api.commit()

        # add tasks and reminders
        for i, step in enumerate(sorted(parsed_steps, key=lambda s: s["start_time"])):
            item = api.items.add(
                step["name"],
                project_id=project["id"],
                section_id=section["id"],
                due=dict(date=step["start_time"].strftime("%Y-%m-%dT%H:%M:%S")),
                day_order=1000 + i,
            )
            print("\n\t", str(item))
            api.commit()

            # comment out the following block in order not to create reminders
            reminder = api.reminders.add(
                item_id=item["id"],
                service="push",
                due=dict(
                    date=(step["start_time"] - datetime.timedelta(minutes=5)).strftime(
                        "%Y-%m-%dT%H:%M:%S"
                    )
                ),
            )
            print("\n\t", str(reminder))
            api.commit()

    else:
        click.echo("\nJust planning, not creating the tasks...")

if __name__ == "__main__":
    plan()


import StaticAnalysis, ModalAnalysis
import numpy as np
import matplotlib.pyplot as plt

if __name__ == "__main__":

    mesh_static = StaticAnalysis.StaticAnalysis()
    mesh_static.read_mesh_from_file('lattice_2.txt')

    mesh_static.boundary_conditions = [1, 4, 11]
    force = np.array([[0],[0],[0],[0],[0],[0],[0],[-2e5],[0],[0],[0],[0]])
    static_displacement = mesh_static.solve(force)

    mesh_modal = ModalAnalysis.ModalAnalysis()
    mesh_modal.read_mesh_from_mesh(mesh_static)

    mesh_modal.boundary_conditions = [1, 4, 11]
    frequencies, modal_displacement = mesh_modal.solve()

    plt.figure()
    mesh_static.plot_lattice()
    mesh_static.plot_solved(static_displacement, factor=500)

    mesh_modal.plot_frequencies(modal_displacement, factor=10)


import collections
import datetime

# this is a toy example and clearly not robust at all
Composer = collections.namedtuple("Composer", "name era id timestamp")
counter = 1
dict = {}

def get_timestamp():
    now = datetime.datetime.now()
    return now.strftime("%d/%m/%Y %H:%M:%S")

def get_composers():
    global dict
    return list(dict.values())

def get_composer_by_id(id):
    global dict
    return dict[id]

def new_composer(name, era):
    global counter
    global dict
    this_id = counter
    counter += 1
    composer = Composer(name=name, era=era, id=this_id, timestamp=get_timestamp())
    dict[this_id] = composer
    return composer

def update_composer(id, name, era):
    global dict
    composer = Composer(name=name, era=era, id=id, timestamp=get_timestamp())
    dict[id] = composer
    return composer

def delete_composer(id):
    global dict
    del dict[id]


#!/usr/bin/env python3

import sys
import argparse
import socket

from sncserver import SncServer
from sncclient import SncClient

class Snc():

    def start(self):
        parser = argparse.ArgumentParser()

        parser.add_argument("connection", nargs='*', help="Connection in the format of [server] [port]")
        parser.add_argument("--key", type = str, help="Enter the encxryption key", required=True)
        parser.add_argument("-l", help="use the option for Server(listen) mode", action="store_true", default=False)

        args = parser.parse_args()

        connection_list=args.connection

        key = args.key.encode('utf8')
        if len(key) < 16 :
            sys.stderr.write('Key should be at least %s characters long\n' % str(16))
            sys.exit(1)
        listen=args.l

        if listen == True :
            try :
                port = int(connection_list[0])

            except IndexError:
                sys.stderr.write('Please specify a port\n')
                sys.exit(1)

            SncServer(port, args.key).start()
        else :
            try :
                host = connection_list[0]
                port = int(connection_list[1])

            except IndexError:
                sys.stderr.write('Please specify connection string in [server] [port] format\n')
                sys.exit(1)

            except ValueError:
                sys.stderr.write('Incorrect host or port\n')
                sys.exit(1)

            SncClient(host, port, args.key).start()


"""Mosh effect. Uses OpticalFlow to reproduce a datamoshing effect.

We first calculate the dense optical flow between each frame of the input video
and its preceding frame. We then convert the obtained flow in remap vectors
and apply these vectors to an image buffer so as to apply to it the motion
approximated by the dense optical flow.

This file can be used as a library and a script.
"""
import itertools
import sys

import numpy
import cv2

from ..utils.frame import Frame
from ..utils.optical_flow import OpticalFlow, OpticalFlowGenerator
from ..utils.video import VideoReader, VideoWriter

def GenerateFrames(
        input_video,
        start_frame, end_frame,
        effect_start_frame, effect_end_frame,
        motion_multiplier_x, motion_multiplier_y,
        motion_threshold_x, motion_threshold_y,
        motion_trail_lenght,
        frame_blend_weight=0.0):
    """Applies the effect and returns a generator over the resulting frames.

    Args:
        input_video: string. The path to the input video file.
        start_frame: int. The frame number of the first frame to include in the
            output video.
        end_frame: int. The frame number of the last frame to include in the
            output video.
        effect_start_frame: int. The frame number of the first frame to apply
            the effect to.
        effect_end_frame: int. The frame number of the last frame to apply
            the effect to.
        motion_multiplier_x: float. A scalar to multiply the estimated motion
            by on the x axis.
        motion_multiplier_y: float. A scalar to multiply the estimated motion
            by on the y axis.
        motion_threshold_x: float. Minimum value for an estimated motion vector
            to be taken into account on the x axis.
        motion_threshold_y: float. Minimum value for an estimated motion vector
            to be taken into account on the y axis.
        motion_trail_lenght: int. Motion trail lenght in number of frames.
        frame_blend_weight: float. How much the current transformed frame should
            be blended with the result frame.

    Returns:
        A generator over the resulting frames.
    """

    # Unaffected frames before effect.
    frames_before = input_video.GetStream().ReadFrames(
        start_frame=start_frame, end_frame=effect_start_frame)

    # Unaffected frames after effect.
    frames_after = input_video.GetStream().ReadFrames(
        start_frame=effect_end_frame, end_frame=end_frame)

    # Affected frames.
    frames = input_video.GetStream().ReadFrames(
        start_frame=effect_start_frame, end_frame=effect_end_frame)

    def GeneratedFrames():
        """A generator over the resulting frames."""
        # The image buffer will be initialized as the first affected frame.
        # It is the pixels of this buffer that will be transformed by applying
        # the calculated remap vectors.
        image_buffer = None

        history = []

        for frame, optical_flow in OpticalFlowGenerator(frames).GenerateFlow():
            if image_buffer is None:
                image_buffer = numpy.zeros_like(frame.pixels)

            if not len(history):
                history.append(
                    (numpy.zeros_like(frame.pixels),
                     OpticalFlow.Like(optical_flow)))

            history.append((frame.pixels, optical_flow))
            history = history[-motion_trail_lenght:]

            for history_frame_pixels, history_optical_flow in history:
                remap_vectors = OpticalFlow.GetRemapVectors(
                    history_optical_flow.flow)

                cv2.remap(
                    src=history_frame_pixels,
                    dst=history_frame_pixels,
                    map1=remap_vectors[0],
                    map2=remap_vectors[1],
                    interpolation=cv2.INTER_LINEAR,
                    borderMode=cv2.BORDER_DEFAULT)

            # sum_optical_flows = OpticalFlow.Add(*optical_flow_history)

            # remap_vectors = sum_optical_flows.GetRemapVectors(
            #     sum_optical_flows.flow)

            # cv2.remap(
            #     src=frame.pixels,
            #     dst=image_buffer,
            #     map1=remap_vectors[0],
            #     map2=remap_vectors[1],
            #     interpolation=cv2.INTER_LINEAR,
            #     borderMode=cv2.BORDER_DEFAULT)

            # # Blends in the current transformed frame if blend weight > 0.
            # if frame_blend_weight > 0:
            #     # We first transform the frame by applying the remap vectors.
            #     cv2.remap(
            #         src=frame.pixels,
            #         dst=frame.pixels,
            #         map1=optical_flow.remap_vectors_x,
            #         map2=optical_flow.remap_vectors_y,
            #         interpolation=cv2.INTER_LINEAR,
            #         borderMode=cv2.BORDER_DEFAULT)
            #     # We then blend in the resulting frame with the image buffer.
            #     cv2.addWeighted(
            #         src1=image_buffer,
            #         src2=frame.pixels,
            #         dst=image_buffer,
            #         alpha=1 - frame_blend_weight,
            #         beta=frame_blend_weight,
            #         gamma=0)

            yield Frame(image_buffer, frame.position)

    # We return a generator over of all unaffected and affected frames.
    return itertools.chain(frames_before, GeneratedFrames(), frames_after)

def main(input_video_path, output_video_path, start_frame=0, end_frame=None,
         effect_start_frame=0, effect_end_frame=None,
         motion_multiplier_x=1.0, motion_multiplier_y=1.0,
         motion_threshold=0.0, motion_trail_lenght=None,
         frame_blend_weight=0, preview=False):
    input_video = VideoReader(file_path=input_video_path)
    output_video = VideoWriter.FromReader(
        input_video, file_path=output_video_path)

    if end_frame is None:
        end_frame = input_video.frame_count

    if effect_end_frame is None:
        effect_end_frame = input_video.frame_count

    if motion_trail_lenght is None:
        motion_trail_lenght = input_video.frame_count

    effect_start_frame = max(effect_start_frame, start_frame)
    effect_end_frame = min(effect_end_frame, end_frame)

    print('\n'.join(['Starting mosh effect with parameters:',
                     ' - input: %s' % input_video_path,
                     ' - output: %s' % output_video_path,
                     ' - video:',
                     '   - start frame: %d' % start_frame,
                     '   - end frame: %d' % end_frame,
                     ' - effect:',
                     '   - start frame: %d' % effect_start_frame,
                     '   - effect end frame: %d' % effect_end_frame,
                     '   - motion_multiplier: (%f, %f)' % (
                         motion_multiplier_x, motion_multiplier_y),
                     '   - motion threshold: %f' % motion_threshold,
                     '   - frame blend weight: %f' % frame_blend_weight,
                     '\n']))

    print('\n'.join(['Input video info:',
                     ' - size: %dx%d' % input_video.frame_size,
                     ' - fps: %d' % input_video.fps,
                     ' - frame count: %d' % input_video.frame_count,
                     ' - codec code: %s' % input_video.fourcc,
                     '\n']))

    # Gets a generator of transformed frames.
    generated_frames = GenerateFrames(
        input_video,
        start_frame=start_frame,
        end_frame=end_frame,
        effect_start_frame=effect_start_frame,
        effect_end_frame=effect_end_frame,
        frame_blend_weight=frame_blend_weight,
        motion_multiplier_x=motion_multiplier_x,
        motion_multiplier_y=motion_multiplier_y,
        motion_threshold_x=motion_threshold,
        motion_threshold_y=motion_threshold,
        motion_trail_lenght=motion_trail_lenght)

    # Writes frames to the output video file.
    print('Writing frames to %s...' % output_video_path)
    for frame in output_video.WriteFrames(generated_frames):
        sys.stdout.write(
            'Progress: %d/%d (%.2f%%) \r' %
            (frame.position[0], end_frame,
             float(frame.position[0]) / float(end_frame) * 100))
        sys.stdout.flush()

        # Shows a preview if requested.
        if preview:
            cv2.imshow('Preview', frame.pixels)

    print('\nDone writing %s.' % output_video_path)

if __name__ == '__main__':
    import argparse
    parser = argparse.ArgumentParser(
        description=('Uses Optical Flow to reproduce a Datamosh effect.'))

    parser.add_argument(
        '-i', '--input_video_path',
        metavar='<video file path>',
        required=True,
        type=str,
        help='Input video path')

    parser.add_argument(
        '-o', '--output_video_path',
        metavar='<path>',
        required=True,
        type=str,
        help='Output video file path')

    parser.add_argument(
        '-s', '--start_frame',
        metavar='<frame>',
        type=int,
        default=0,
        help='Output video start frame number. Default: 0 (first frame)')

    parser.add_argument(
        '-e', '--end_frame',
        metavar='<frame>',
        type=int,
        default=None,
        help='Output video end frame number. Default: last frame.')

    parser.add_argument(
        '-fx_s', '--effect_start_frame',
        metavar='<frame>',
        type=int,
        default=0,
        help='Effect start frame number. Default: 0 (first frame)')

    parser.add_argument(
        '-fx_e', '--effect_end_frame',
        metavar='<frame>',
        type=int,
        default=None,
        help='Effect end frame number. Default: last frame.')

    parser.add_argument(
        '--frame_blend_weight',
        metavar='<0.0-1.0>',
        type=float,
        default=0.0,
        help=('Blend weight for the transformed frame in the final image. ' +
              'Used to preserve detail from the frames throuhougt the video. ' +
              'If > 0 the transformed frames will be blended with the result ' +
              'images, otherwise only the first frame\'s pixels will be used.'))

    parser.add_argument(
        '-m_threshold', '--motion_threshold',
        metavar='<pixel_threshold>',
        type=float,
        default=0.0,
        help=('Motion pixel threshold. Motion below this value is ignored. ' +
              'Setting a value > 0 helps to keep slightly moving areas sharp.')
    )

    parser.add_argument(
        '-m_mult_x', '--motion_multiplier_x',
        metavar='<multiplier>',
        type=float,
        default=1.0,
        help=('Multiplier to apply to the motion vectors along the x axis. ' +
              'This value will be multiplied by the global motion multiplier.')
    )

    parser.add_argument(
        '-m_mult_y', '--motion_multiplier_y',
        metavar='<multiplier>',
        type=float,
        default=1.0,
        help=('Multiplier to apply to the motion vectors along the y axis.' +
              'This value will be multiplied by the global motion multiplier.')
    )

    parser.add_argument(
        '-m_mult', '--motion_multiplier',
        metavar='<multiplier>',
        type=float,
        default=1.0,
        help='Multiplier to apply to the motion vectors.'
    )

    parser.add_argument(
        '-m_t_l', '--motion_trail_length',
        metavar='<frames>',
        type=int,
        default=None,
        help='The lenght in frame of the trail mosh effect. Default: All frames'
    )

    parser.add_argument(
        '--preview',
        action='count',
        default=0,
        help='Shows a preview of the generated frames during computation.')

    args = parser.parse_args()

    main(
        args.input_video_path,
        args.output_video_path,
        start_frame=args.start_frame,
        end_frame=args.end_frame,
        effect_start_frame=args.effect_start_frame,
        effect_end_frame=args.effect_end_frame,
        frame_blend_weight=args.frame_blend_weight,
        motion_multiplier_x=args.motion_multiplier_x * args.motion_multiplier,
        motion_multiplier_y=args.motion_multiplier_y * args.motion_multiplier,
        motion_threshold=args.motion_threshold,
        motion_trail_lenght=args.motion_trail_length,
        preview=bool(args.preview))


from __future__ import unicode_literals
import ckanext.baepublisher.controllers.ui_controller as controller
import base64
import os
import unittest
import requests

from mock import MagicMock
from parameterized import parameterized

MISSING_ERROR = 'This field is required to publish the offering'

__dir__ = os.path.dirname(os.path.abspath(__file__))
filepath = os.path.join(__dir__, '../assets/logo-ckan.png')

with open(filepath, 'rb') as f:
    LOGO_CKAN_B64 = base64.b64encode(f.read())

class UIControllerTest(unittest.TestCase):

    def setUp(self):

        controller.plugins.toolkit = MagicMock()
        self._toolkit = controller.plugins.toolkit
        controller.plugins.toolkit.NotAuthorized = self._toolkit.NotAuthorized

        self._request = controller.request
        controller.request = MagicMock()

        self._helpers = controller.helpers
        controller.helpers = MagicMock()

        self._base64 = controller.base64
        controller.base64 = MagicMock()

        self._StoreConnector = controller.StoreConnector
        self._store_connector_instance = MagicMock(store_url='localhost')
        controller.StoreConnector = MagicMock(return_value=self._store_connector_instance)

        # Create the plugin
        self.instanceController = controller.PublishControllerUI()

    def tearDown(self):
        controller.StoreConnector = self._StoreConnector

    class MockResponse:
        def __init__(self, json_data, status_code, dic):
            self.json_data = json_data
            self.status_code = status_code
            self.called_Raise = False
            self.dic = dic

        def __getitem__(self, item):
            return self.dic[item]

        def __contains__(self, key):
            return key in self.dic

        def json(self):
            return self.json_data

        def raise_for_status(self):
            self.called_Raise = True
            if self.status_code != 200:
                raise Exception
            else:
                return self.status_code

        def get(self, field, default=''):
            if field in self.dic:
                return self.dic[field]
            else:
                return default

        def getall(self, field):
            if 'categories' in self.dic:
                return self.dic['categories']
            else:
                return []

    @parameterized.expand([
        # Incorrect parameter
        ('offering', MockResponse({}, 403, []), {'lifecycleStatus': 'Launched'}),
        ('', MockResponse({}, 403, []), {'lifecycleStatus': 'Launched'}),
        # Valid entries
        ('category', MockResponse({'id': '1'}, 200, []), {'lifecycleStatus': 'Launched'}),
        ('catalog', MockResponse({'id': '1'}, 200, []),
         {'lifecycleStatus': 'Launched', 'relatedParty.id': 'eugenio'})
    ])
    def test_get_content(self, content, resp, filters):
        requests.get = MagicMock(return_value=resp)
        controller.plugins.toolkit.c.user = 'eugenio'
        controller.plugins.toolkit.c.errors = {}

        r = self.instanceController._get_content(content)

        requests.get.assert_called_once_with(
            '{0}/DSProductCatalog/api/catalogManagement/v2/{1}'.format(
                self._store_connector_instance.store_url, content),
            params=filters, verify=True)

        if content == 'category' or content == 'catalog':
            self.assertEquals(r, {'id': '1'})
            self.assertEquals(controller.plugins.toolkit.c.errors, {})
        else:
            self.assertEquals(controller.plugins.toolkit.c.errors[content], ['{} couldnt be loaded'.format(content)])
            self.assertEquals(self.instanceController._get_content(content), {})
            self.assertTrue(resp.called_Raise)

    @parameterized.expand([
        # (False, False, {},),
        # # Test missing fields and wrong version
        (True, False, MockResponse({}, 200, {'name': 'a',
                                             'version': '1.0',
                                             'pkg_id': 'package_id'})),
        (True, False, MockResponse({}, 200, {'version': '1.0',
                                             'pkg_id': 'package_id'})),
        (True, False, MockResponse({}, 200, {'name': 'a',
                                             'pkg_id': 'package_id'})),
        (True, False, MockResponse({}, 200, {'pkg_id': 'package_id'})),
        (True, False, MockResponse({}, 200, {'name': 'a',
                                             'version': '1.0.'})),
        # Test invalid prices
        (True, False, MockResponse({}, 200, {'name': 'a',
                                             'version': '1.0',
                                             'pkg_id': 'package_id',
                                             'price': 'a'})),
        (True, False, MockResponse({}, 200, {'name': 'a',
                                             'version': '1.0',
                                             'pkg_id': 'package_id',
                                             'price': '5.a'})),
        # Test open offerings (open offerings must not contain private datasets)
        (True, False, MockResponse({}, 200, {'name': 'a',
                                             'version': '1.0',
                                             'pkg_id': 'package_id',
                                             'open': ''})),
        (True, True, MockResponse({}, 200, {'name': 'a',
                                            'version': '1.0',
                                            'pkg_id': 'package_id',
                                            'open': ''})),
        # Public datastets cannot be offering in paid offerings
        (True, False, MockResponse({}, 200, {'name': 'a',
                                             'version': '1.0',
                                             'pkg_id': 'package_id',
                                             'price': '1.0'})),
        (True, True, MockResponse({}, 200, {'name': 'a',
                                            'version': '1.0',
                                            'pkg_id': 'package_id',
                                            'price': '1.0'})),
        # 'image_upload' == '' happens when the user has not selected a file, so the default one must be used
        (True, False, MockResponse({}, 200, {'name': 'a',
                                             'version': '1.0',
                                             'pkg_id': 'package_id',
                                             'image_upload': ''})),
        (True, False, MockResponse({}, 200, {'name': 'a',
                                             'version': '1.0',
                                             'pkg_id': 'package_id',
                                             'image_upload': MagicMock()})),
        # If 'update_acquire_url' is in the request content, the acquire_url should be updated
        # only when the offering has been published correctly
        (True, False, MockResponse({}, 200, {'name': 'a',
                                             'version': '1.0',
                                             'pkg_id': 'package_id',
                                             'update_acquire_url': ''})),
        (True, False, MockResponse({}, 200, {'name': 'a',
                                             'version': '1.0',
                                             'pkg_id': 'package_id'}),
         controller.StoreException('Impossible to connect with the Store')),
        (True, False, MockResponse({}, 200, {'name': 'a',
                                             'version': '1.0',
                                             'pkg_id': 'package_id',
                                             'update_acquire_url': ''}),
         controller.StoreException('Impossible to connect with the Store')),
        # Requests with the fields not tested above
        # Test without tags
        (True, True, MockResponse({}, 200, {'name': 'a',
                                            'version': '1.0',
                                            'pkg_id': 'package_id',
                                            'description':
                                            '',
                                            'license_title': 'cc',
                                            'license_description': 'Desc',
                                            'price': '1.1',
                                            'categories': [],
                                            'catalogs': '51'})),
        # Request will all the fields
        (True, True, MockResponse({}, 200, {'name': 'A B C D',
                                            'version': '1.0',
                                            'pkg_id': 'package_id',
                                            'description': 'Example Description',
                                            'license_title': 'cc',
                                            'license_description': 'Desc',
                                            'categories': ['1', '5', '14'],
                                            'price': '1.1',
                                            'image_upload': MagicMock(),
                                            'update_acquire_url': '',
                                            'catalogs': '51'}))
    ])
    def test_publish(self, allowed, private, post_content, create_offering_res='http://some_url.com'):

        errors = {}
        current_package = {'categories': [{'name': 'Programacion'},
                                          {'name': 'java'}],
                           'private': private,
                           'acquire_url': 'http://example.com'}
        package_show = MagicMock(return_value=current_package)
        package_update = MagicMock()
        categories = [{'name': 'Programacion', 'isRoot': True, 'id': '1',
                       'parentId': '1',
                       'href': 'http://localhost:8000/DSProductCatalog/api/catalogManagement/v2/category/1:(1.0)'},
                      {'name': 'java', 'isRoot': False, 'id': '5',
                       'parentId': '1',
                       'href': 'http://localhost:8000/DSProductCatalog/api/catalogManagement/v2/category/5:(1.0)'},
                      {'name': 'haskell', 'isRoot': False, 'id': '14',
                       'parentId': '1',
                       'href': 'http://localhost:8000/DSProductCatalog/api/catalogManagement/v2/category/14:(1.0)'}]
        catalog = [{'id': '51',
                    'name': 'catalog1'}]

        self.instanceController._get_content = MagicMock(side_effect=[categories, catalog])

        def _get_action_side_effect(action):
            if action == 'package_show':
                return package_show
            else:
                return package_update

        tkString = 'Offering {1} published correctly.'.format(create_offering_res, post_content.get('name', ''))

        controller.plugins.toolkit.get_action = MagicMock(side_effect=_get_action_side_effect)
        controller.plugins.toolkit.check_access = MagicMock(
            side_effect=self._toolkit.NotAuthorized if allowed is False else None)
        controller.plugins.toolkit._ = self._toolkit._
        controller.plugins.toolkit._.return_value = tkString
        controller.request.GET = []
        controller.request.POST = post_content
        self._store_connector_instance.create_offering = MagicMock(
            side_effect=[create_offering_res])
        self._store_connector_instance.validate_version = MagicMock(return_value='1.0')
        user = controller.plugins.toolkit.c.user
        pkg_id = post_content.get('pkg_id')
        # pkg_id = 'dhjus2-fdsjwdf-fq-dsjager'

        expected_context = {'model': controller.model,
                            'session': controller.model.Session,
                            'user': controller.plugins.toolkit.c.user,
                            'auth_user_obj': controller.plugins.toolkit.c.userobj}

        # Call the function
        self.instanceController.publish(pkg_id, post_content.dic)

        # Check that the check_access function has been called
        controller.plugins.toolkit.check_access.assert_called_once_with(
            'package_update', expected_context, {'id': pkg_id})

        # Check that the abort function is called properly
        if not allowed:
            controller.plugins.toolkit.abort.assert_called_once_with(
                401, 'User %s not authorized to publish %s' % (user, pkg_id))
        else:

            # Get the list of tags
            if post_content.get('categories') == [] or 'categories' not in post_content:
                tags = []
            else:
                tags = [
                    {'id': '14',
                     'href': 'http://localhost:8000/DSProductCatalog/api/catalogManagement/v2/category/14:(1.0)'},
                    {'id': '5',
                     'href': 'http://localhost:8000/DSProductCatalog/api/catalogManagement/v2/category/5:(1.0)'},
                    {'id': '1',
                     'href': 'http://localhost:8000/DSProductCatalog/api/catalogManagement/v2/category/1:(1.0)'}]

            # Get catalog
            catalog = post_content.get('catalogs')

            # Calculate errors
            if 'name' not in post_content:
                errors['Name'] = [MISSING_ERROR]

            if 'pkg_id' not in post_content:
                errors['Pkg_id'] = [MISSING_ERROR]

            price = post_content.get('price', '')
            if price != '':
                try:
                    real_price = float(post_content['price'])
                    if real_price > 0 and not private:
                        errors['Price'] = ['You cannot set a price to a dataset that is public since everyone can access it']
                except Exception:
                    errors['Price'] = ['"%s" is not a valid number' % price]
            else:
                real_price = 0.0

            if 'open' in post_content and private:
                errors['Open'] = ['Private Datasets cannot be offered as Open Offerings']

            if errors:
                # If the parameters are invalid, the function create_offering must not be called
                self.assertEquals(0, self._store_connector_instance.create_offering.call_count)
            else:

                # Default image should be used if the users has not uploaded a image
                image_field = post_content.get('image_upload', '')
                if image_field != '':
                    controller.base64.b64encode.assert_called_once_with(image_field.file.read.return_value)
                    expected_image = controller.base64.b64encode.return_value
                else:
                    self.assertEquals(0, controller.base64.b64encode.call_count)
                    expected_image = LOGO_CKAN_B64

                expected_data = {
                    'name': post_content['name'],
                    'pkg_id': post_content['pkg_id'],
                    'version': post_content['version'] if 'version' in post_content else '1.0',
                    'description': post_content.get('description', ''),
                    'license_title': post_content.get('license_title', ''),
                    'license_description': post_content.get('license_description', ''),
                    'is_open': 'open' in post_content,
                    'categories': tags,
                    'catalog': catalog,
                    'price': real_price,
                    'image_base64': expected_image,
                    'role': ''
                }

                self._store_connector_instance.create_offering.assert_called_once_with(current_package, expected_data)

                if isinstance(create_offering_res, Exception):
                    errors['Store'] = [create_offering_res.message]
                    # The package should not be updated if the create_offering returns an error
                    # even if 'update_acquire_url' is present in the request content.
                    self.assertEquals(0, package_update.call_count)

                else:
                    controller.helpers.flash_success.assert_called_once_with(
                        tkString,
                        allow_html=True)
                    controller.plugins.toolkit._.assert_called_once_with(tkString)

        self.assertEquals(errors, controller.plugins.toolkit.c.errors)

        controller.plugins.toolkit.render('package/publish.html')


from ase.io import read
import pymatgen as pm
from pymatgen.analysis.local_env import CrystalNN
import warnings
from pymatgen.io import ase as pm_ase
import os
bridge = pm_ase.AseAtomsAdaptor()
directory = '/home/zlc6394/tobacco_mc_0'
#directory = '/home/zlc6394/tobacco_mc_0'
write_dir = '/home/zlc6394/removed_hydrogen_mc_0'
for files in os.listdir(directory):
	if (os.path.exists(write_dir + '/' + files) == False):
		os.chdir(directory)
		asemof = read(files)
		mof = bridge.get_structure(asemof)
		nn_object = CrystalNN(x_diff_weight=0) #can optionally set search_cutoff=None

		#ignore warnings about specifying oxidation states
		with warnings.catch_warnings():
			warnings.simplefilter('ignore')
			badidx = []
			#loop through every atom to get the coord num
			for atomidx in range(len(mof)):
				atom = mof[atomidx]
				if atom.species_string == "H" :
					local_env = nn_object.get_nn_info(mof,atomidx)
					coord_num = len(local_env)
					#for a in local_env:
					#	print("connected atom is", a['site'].species_string)
					if not coord_num or coord_num != 1 or local_env[0]['site'].species_string == "Cu":
						badidx.append(atomidx)

			mof.remove_sites(badidx)
			os.chdir(write_dir)
			print("Hey! It is writing stuff!")
			mof.to(filename = files)


import logging

from bedmerger.parameters import Parameters
from bedmerger import merge

def setup_logging(logfile, loglevel):
    """ initializes basic logging"""

    if logfile is not None:
        logging.basicConfig(filename=logfile, level=loglevel)
        logging.debug("set logfile to %s, loglevel to %s",
                logfile, loglevel)
    else:
        logging.basicConfig(level=loglevel)
        logging.debug("no logfile set, loglevel to %s",
                loglevel)

    return None

if __name__ == "__main__":
    params = Parameters.from_command_line()
    params.setup()
    params.sanity_checks()
    logger = setup_logging(params.logfile, params.loglevel)
    merge.merge(params)


from typing import List, Optional

class TreeNode:
    def __init__(self):
        self.left: Optional[TreeNode] = None
        self.right: Optional[TreeNode] = None
        self.index: int = -1

    def partition(self):
        if self.left is None or self.right is None:
            return [[self.index]]

        left_nodes = self.left.partition()
        right_nodes = self.right.partition()

        all_partitions = []
        for l_node in left_nodes:
            for r_node in right_nodes:
                h = l_node.copy()
                h.extend(r_node)
                all_partitions.append(h)

        all_partitions.append([self.index])
        return all_partitions

def create_tree(depth: int) -> TreeNode:
    node = TreeNode()
    if depth == 0:
        return node
    node.left = create_tree(depth-1)
    node.right = create_tree(depth-1)

    return node

def add_indices(node: TreeNode) -> TreeNode:
    nodes: List[TreeNode] = [node]
    i = 0
    while nodes:
        n = nodes.pop(0)
        n.index = i

        if n.left != None:
            nodes.append(n.left)
        if n.right != None:
            nodes.append(n.right)
        i += 1

    return node

if __name__ == "__main__":
    depth = 2
    root = create_tree(depth)
    root = add_indices(root)

    print(root.partition())


import numpy as np, gc
from scipy import interpolate, stats

#from numba import jit, prange
#from astropy.stats import histogram
from tqdm import tqdm

from . import smoothing, cosmology, const

def power_spect_nd(input_array, box_dims, verbose=True):
	'''
	Calculate the power spectrum of input_array and return it as an n-dimensional array,
	where n is the number of dimensions in input_array
	box_side is the size of the box in comoving Mpc. If this is set to None (default),
	the internal box size is used

	Parameters:
		* input_array (numpy array): the array to calculate the
			power spectrum of. Can be of any dimensions.
		* box_dims = None (float or array-like): the dimensions of the
			box. If this is None, the current box volume is used along all
			dimensions. If it is a float, this is taken as the box length
			along all dimensions. If it is an array-like, the elements are
			taken as the box length along each axis.

	Returns:
		The power spectrum in the same dimensions as the input array.
	'''

	if np.array(box_dims).size!=3: box_dims = np.array([box_dims,box_dims,box_dims])
	if verbose: print( 'Calculating power spectrum...')
	ft = np.fft.fftshift(np.fft.fftn(input_array.astype('float64')))
	power_spectrum = np.abs(ft)**2
	if verbose: print( '...done')

	# scale
	#print(box_dims)
	boxvol = np.product(box_dims)
	#print(boxvol)
	pixelsize = boxvol/(np.product(input_array.shape))
	power_spectrum *= pixelsize**2/boxvol

	return power_spectrum

def phase_spect_nd(input_array, box_dims, verbose=True):
	'''
	Calculate the phase spectrum of input_array and return it as an n-dimensional array,
	where n is the number of dimensions in input_array
	box_side is the size of the box in comoving Mpc. If this is set to None (default),
	the internal box size is used

	Parameters:
		* input_array (numpy array): the array to calculate the
			power spectrum of. Can be of any dimensions.
		* box_dims = None (float or array-like): the dimensions of the
			box. If this is None, the current box volume is used along all
			dimensions. If it is a float, this is taken as the box length
			along all dimensions. If it is an array-like, the elements are
			taken as the box length along each axis.

	Returns:
		The power spectrum in the same dimensions as the input array.
	'''

	if np.array(box_dims).size!=3: box_dims = np.array([box_dims,box_dims,box_dims])
	if verbose: print( 'Calculating power spectrum...')
	ft = np.fft.fftshift(np.fft.fftn(input_array.astype('float64')))
	phase_spectrum = np.arctan(np.imag(ft)/np.real(ft)) #np.abs(ft)**2
	if verbose: print( '...done')

	# scale
	#print(box_dims)
	boxvol = np.product(box_dims)
	#print(boxvol)
	pixelsize = boxvol/(np.product(input_array.shape))
	power_spectrum *= pixelsize**2/boxvol

	return power_spectrum

def _get_k(input_array, box_dims):
	'''
	Get the k values for input array with given dimensions.
	Return k components and magnitudes.
	For internal use.
	'''
	if np.array(box_dims).size!=3: box_dims = np.array([box_dims,box_dims,box_dims])
	dim = len(input_array.shape)
	if dim == 1:
		x = np.arange(len(input_array))
		center = x.max()/2.
		kx = 2.*np.pi*(x-center)/box_dims[0]
		return [kx], kx
	elif dim == 2:
		x,y = np.indices(input_array.shape, dtype='int32')
		center = np.array([(x.max()-x.min())/2, (y.max()-y.min())/2])
		kx = 2.*np.pi * (x-center[0])/box_dims[0]
		ky = 2.*np.pi * (y-center[1])/box_dims[1]
		k = np.sqrt(kx**2 + ky**2)
		return [kx, ky], k
	elif dim == 3:
		x,y,z = np.indices(input_array.shape, dtype='int32')
		center = np.array([(x.max()-x.min())/2, (y.max()-y.min())/2, \
						(z.max()-z.min())/2])
		kx = 2.*np.pi * (x-center[0])/box_dims[0]
		ky = 2.*np.pi * (y-center[1])/box_dims[1]
		kz = 2.*np.pi * (z-center[2])/box_dims[2]

		k = np.sqrt(kx**2 + ky**2 + kz**2 )
		return [kx,ky,kz], k

def power_spect_1d(input_array, kbins=10, binning='log', box_dims=244/.7, return_modes=False, kmin=None, kmax=None):
	power = power_spect_nd(input_array, box_dims, verbose=0)
	[kx,ky,kz], k = _get_k(input_array, box_dims)
	if kmin is None: kmin = 2*np.pi/np.array(box_dims).max()
	if kmax is None: kmax = k.max()
	if binning=='log':
		ks = np.linspace(np.log10(kmin), np.log10(kmax), kbins+1)
		k  = np.log10(k)
	elif binning=='linear': ks = np.linspace(kmin, kmax, kbins+1)
	elif binning=='auto':
		#kht = histogram(k.flatten(), bins='knuth')
		n_bin  = 1.*k.size/kbins
		k_sort = np.sort(k.flatten())
		ks = np.array([k_sort[int(i)] for i in np.arange(n_bin/2., k.size, n_bin)])
	if binning!='auto': ks = (ks[:-1]+ks[1:])/2.
	kkk = np.hstack((k.min(),(ks[1:]+ks[:-1])/2, k.max()))
	k_width = kkk[1:]-kkk[:-1]
	ps = np.zeros(kbins)
	n_modes = np.zeros(kbins)
	k, power = k.flatten(), power.flatten()
	for i,a in enumerate(ks):
		arg = np.argwhere(np.abs(k-a)<=k_width[i]/2.)
		ps[i] = power[arg].sum()
		n_modes[i] = arg.size

	ps = ps/n_modes
	if binning=='log': ks = 10**ks
	if return_modes: return ps, ks, n_modes
	return ps, ks

def power_spect_2d(input_array, kbins=10, binning='log', box_dims=244/.7, return_modes=False, nu_axis=2, window=None):
	'''
	Calculate the power spectrum and bin it in kper and kpar
	input_array is the array to calculate the power spectrum from

	Parameters:
		input_array (numpy array): the data array
		nu_axis = 2 (integer): the line-of-sight axis
		kbins = 10 (integer or array-like): The number of bins,
			If you want different bins for kper and kpar, then provide a list [n_kper, n_par]
		box_dims = 244/.7 (float or array-like): the dimensions of the
			box. If this is None, the current box volume is used along all
			dimensions. If it is a float, this is taken as the box length
			along all dimensions. If it is an array-like, the elements are
			taken as the box length along each axis.
		return_n_modes = False (bool): if true, also return the
			number of modes in each bin
		binning = 'log' : It defines the type of binning in k-space. The other options are
				    'linear' or 'mixed'.
		window = None : It tappers the data in the frequency direction to control shape change at the boundary slices.
					The other options are 'blackmanharris' and 'tukey'. If the data has sharp change in the angular/spatial
					direction, please provide a 3D window as a numpy array.

	Returns:
		A tuple with (Pk, kper_bins, kpar_bins) if return_modes is False else (Pk, kper_bins, kpar_bins, n_modes),
		where Pk is an array with the power spectrum of dimensions (n_kper x n_kpar),
		mubins is an array with the mu bin centers,
		kbins is an array with the k bin centers and
		n_modes is the number of modes.

	'''
	if window is not None:
		from scipy.signal import windows
		if window.lower()=='blackmanharris':
				input_array *= windows.blackmanharris(input_array.shape[-1])[None,None,:]
		elif window.lower()=='tukey':
				input_array *= windows.tukey(input_array.shape[-1])[None,None,:]
		else:
				input_array *= window

	if np.array(kbins).size==1:
		kbins = [kbins, kbins]
	if not isinstance(kbins[0], int):
		binning = None

	power = power_spect_nd(input_array, box_dims, verbose=0)
	[kx,ky,kz], k = _get_k(input_array, box_dims)
	kdict = {}
	kdict['0'], kdict['1'], kdict['2'] = kx, ky, kz
	del kx, ky, kz
	kz = kdict[str(nu_axis)]
	kp = np.sqrt(kdict[str(np.setdiff1d([0,1,2],nu_axis)[0])]**2+kdict[str(np.setdiff1d([0,1,2],nu_axis)[1])]**2)
	kz = np.abs(kz)
	# print(np.abs(kp[kp!=0]).min(),np.abs(kz[kz!=0]).min())
	if binning is None:
		kper = np.array(kbins[0])
		kpar = np.array(kbins[1])
		kbins = [len(kper),len(kpar)]
	elif binning=='log':
		kper = np.linspace(np.log10(np.abs(kp[kp!=0]).min()), np.log10(kp.max()), kbins[0]+1)
		kpar = np.linspace(np.log10(np.abs(kz[kz!=0]).min()), np.log10(kz.max()), kbins[1]+1)
		kp, kz  = np.log10(kp), np.log10(kz)
	elif binning=='linear':
		kper = np.linspace(np.abs(kp[kp!=0]).min(), kp.max(), kbins[0]+1)
		kpar = np.linspace(np.abs(kz[kz!=0]).min(), kz.max(), kbins[1]+1)
	k_width = kper[1]-kper[0], kpar[1]-kpar[0]
	# print(10**kper,10**kpar)
	kper = (kper[:-1]+kper[1:])/2.
	kpar = (kpar[:-1]+kpar[1:])/2.
	# print(10**kper,10**kpar)
	ps = np.zeros((kbins[0],kbins[1]))
	n_modes = np.zeros((kbins[0],kbins[1]))
	kp, kz, power = kp.flatten(), kz.flatten(), power.flatten()
	for i,a in tqdm(enumerate(kper)):
		for j,b in enumerate(kpar):
			arg = np.intersect1d(np.argwhere(np.abs(kp-a)<=k_width[0]/2.), np.argwhere(np.abs(kz-b)<=k_width[1]/2.))
			ps[i,j] = power[arg].sum()
			n_modes[i,j] = arg.size

	ps = ps/n_modes
	if binning=='log': kper, kpar = 10**kper, 10**kpar
	if return_modes: return ps, kper, kpar, n_modes
	# print(kper,kpar)
	return ps, kper, kpar
	ps = ps/n_modes
	if binning=='log': kper, kpar = 10**kper, 10**kpar
	if return_modes: return ps, kper, kpar, n_modes
	# print(kper,kpar)
	return ps, kper, kpar

def dimensional_power(input_array, kbins=10, binning='log', box_dims=244/.7, return_modes=False):
	ps, ks, n_modes = power_spect_1d(input_array, kbins=kbins, binning=binning, box_dims=box_dims, return_modes=1)
	if return_modes: return ps*ks**3/2/np.pi**2, ks, n_modes
	return ps*ks**3/2/np.pi**2, ks

def power_spect_mu(input_array, kbins=10, box_dims=244/.7, return_modes=False, mubins=10, binning='log', nu_axis=2):
	if type(binning)==str: binning = [binning, binning]
	power = power_spect_nd(input_array, box_dims, verbose=0)
	[kx,ky,kz], k = _get_k(input_array, box_dims)
	kdict = {}
	kdict['0'], kdict['1'], kdict['2'] = kx, ky, kz
	del kx, ky, kz
	kpar = kdict[str(nu_axis)]
	kper = np.sqrt(kdict[str(np.setdiff1d([0,1,2],nu_axis)[0])]**2+kdict[str(np.setdiff1d([0,1,2],nu_axis)[1])]**2)
	m = np.abs(kpar/k)

	if binning[0]=='log':
		ks = np.linspace(np.log10(np.abs(k[k!=0]).min()), np.log10(k.max()), kbins+1)
		k  = np.log10(k)
	else: ks = np.linspace(np.abs(k[k!=0]).min(), k.max(), kbins+1)
	ks = (ks[:-1]+ks[1:])/2.
	k_width = ks[1]-ks[0]

	if binning[1]=='log':
		m1 = m[np.isfinite(m)]
		mu = np.linspace(np.log10(np.abs(m1[m1!=0]).min()), np.log10(m1.max()), mubins+1)
		m  = np.log10(m)
	else: mu = np.linspace(0,1,mubins+1);
	mu = (mu[:-1]+mu[1:])/2.
	m_width = mu[1]-mu[0]

	ps = np.zeros((kbins, mubins))
	n_modes = np.zeros((kbins, mubins))

	k, m, power = k.flatten(), m.flatten(), power.flatten()
	for i,a in enumerate(ks):
		for j,b in enumerate(mu):
			arg = np.intersect1d(np.argwhere(np.abs(k-a)<=k_width/2.), np.argwhere(np.abs(m[np.isfinite(m)]-b)<=m_width/2.))
			ps[i,j] = power[arg].sum()
			n_modes[i,j] = arg.size

	ps = ps/n_modes
	if binning[0]=='log': ks = 10**ks
	if binning[1]=='log': mu = 10**mu
	if return_modes: return ps, ks, mu, n_modes
	return ps, ks, mu

def plot_2d_power(ps, xlabel='$k_\perp$', ylabel='$k_\parallel$', ps_label='$P(k_\perp,k_\parallel)$',
				  fig=None, ax=None, plotting_scale={'x': 'log', 'y': 'log', 'z': 'log'},
				  draw_wedge={'z': 9.0, 'fov_deg': 90.0, 'ls':'--', 'color': 'k'}, **kwargs):
	'''
	Plotting the 2D or cylindrical power spectrum.

	Parameters:
		ps (tuple or dict): The data in the form of tuple (Pk, kper_bins, kpar_bins) or
							dictionary {'Pk': Pk, 'kper': kper_bins, 'kpar': kpar_bins}
		xlabel = '$k_\perp$' : Label to use for the x-axis.
		ylabel = '$k_\parallel$' : Label to use for the y-axis.
		fig = None : Provide the matplotlib figure for plotting.
		plotting_scale = {'x': 'log', 'y': 'log', 'z': 'log'} : Provide the plotting scales.
		draw_wedge={'z': 9.0, 'fov_deg': 90.0, 'ls':'--', 'color': 'k'} : If not None, then the wedge is drawn.

	Returns:
		The matplotlib figure where the power spectrum is plotted.
	'''
	import matplotlib.pyplot as plt
	import matplotlib.colors as colors

	try: pp, kper, kpar = (ps[ke] for ke in ['Pk','kper','kpar'])
	except: pp, kper, kpar = ps
	fp = interpolate.interp2d(kper, kpar, pp.T, kind='linear')

	if (fig == None) and (ax == None):
		fig, ax = plt.subplots(1,1,figsize=(7,5))
	elif (fig == None) and (ax != None):
		pass
	else:
		ax = fig.axes[0]

	#X, Y = kper[:-1]/2+kper[1:]/2, kpar[:-1]/2+kpar[1:]/2
	X, Y = kper, kpar

	C = fp(X,Y)
	norm = colors.LogNorm(vmin=C[np.isfinite(C)].min(), vmax=C[np.isfinite(C)].max()) if plotting_scale['z']=='log' else None
	pcm = ax.pcolormesh(X, Y, C, norm=norm, **kwargs)
	if draw_wedge is not None:
		f_kpar = horizon_wedge_equation(draw_wedge['z'], fov_deg=draw_wedge['fov_deg'])
		ax.plot(X, f_kpar(X), ls=draw_wedge['ls'], color=draw_wedge['color'])
		ax.axis([X.min(),X.max(),Y.min(),Y.max()])

	plt.colorbar(pcm, ax=ax, label=ps_label, pad=0.01)

	ax.set_xlabel(xlabel)
	ax.set_ylabel(ylabel)
	ax.set_xscale(plotting_scale['x'])
	ax.set_yscale(plotting_scale['y'])
	#plt.show()
	return 1

def horizon_wedge_equation(z, fov_deg=90.0):
	'''
	Equation 14 in arXiv:2201.10798

	Parameters:
		z (float) : Redshift.
		fov_deg = 90 : The field of view (FoV) of the horizon wedge equation in degrees.
	Returns:
		A lambda function k_parallel(k_perpendicular).
	'''
	f_kpar = lambda kper: kper*np.sin(fov_deg*np.pi/180)/(1+z)*\
							smoothing.hubble_parameter(z)/const.c*cosmology.z_to_cdist(z)
	return f_kpar

# def plot_2d_power(ps, xticks, yticks, xlabel, ylabel):
# 	import matplotlib.pyplot as plt
# 	xticks, yticks = np.round(xticks, decimals=2), np.round(yticks, decimals=2)
# 	plt.imshow(ps, origin='lower')
# 	locs, labels = plt.yticks()
# 	new_labels = yticks[locs.astype(int)[1:-1]]
# 	plt.yticks(locs[1:-1], new_labels)
# 	plt.ylabel(ylabel)
# 	locs, labels = plt.xticks()
# 	new_labels = xticks[locs.astype(int)[1:-1]]
# 	plt.xticks(locs[1:-1], new_labels)
# 	plt.xlabel(xlabel)
# 	plt.colorbar()
# 	plt.show()


import bpy
from zpy import Get, Is, utils

def draw_header(self, context):
    layout = self.layout

    prefs = utils.prefs(__package__).motion

    if context.mode == 'POSE':
        src = context.active_pose_bone
    else:
        src = context.object

    if not src:
        return

    layout.separator()
    sub = layout.row()
    sub.emboss = ('PULLDOWN_MENU', 'NORMAL')[prefs.show_panel]
    sub.active = prefs.show_panel
    sub.prop(prefs, 'show_panel', text="", icon='CURVE_DATA')

    if not prefs.show_panel:
        return

    if Is.posebone(src):
        mp = src.id_data.pose.animation_visualization.motion_path
    else:
        mp = src.animation_visualization.motion_path

    if mp.type == 'CURRENT_FRAME':
        mp_text = "Around Frame"
        mp_icon = 'PREVIEW_RANGE'
        mp_start = 'frame_before'
        mp_end = 'frame_after'
        mp_type = 'RANGE'  # value to toggle to
    else:  # mp.type == 'RANGE':
        mp_icon = 'TIME'
        mp_text = "      In Range   "
        mp_start = 'frame_start'
        mp_end = 'frame_end'
        mp_type = 'CURRENT_FRAME'  # value to toggle to

    row = layout.row(align=True)
    row.context_pointer_set('src', src)
    row.context_pointer_set('mp', mp)

    row.menu('MOTIONP_MT_subpanel', text="", icon='THREE_DOTS')

    sub = row.row(align=True)
    sub.scale_x = 0.6
    sub.prop(mp, mp_start, text="")
    row.operator('zpy.motion_path_toggle_type', text=mp_text, icon=mp_icon,
    depress=False).type = mp_type

    sub = row.row()
    sub.scale_x = 0.6
    sub.prop(mp, mp_end, text="")

    # prefs.operator(row, 'toggle mp relative range', text="",
        #            icon=('TIME', 'PREVIEW_RANGE')
        #            [prefs.prefs().motion.use_relative_range],
        #            emboss=True, depress=False, code='''
        # mot = prefs.prefs().motion
        # mot.use_relative_range = not mot.use_relative_range
    sub = row.row()
    sub.emboss = 'PULLDOWN_MENU'

    if prefs.use_relative_range:
        text = "Around"
        icon = 'PREVIEW_RANGE'
    else:
        text = "Range"
        icon = 'TIME'
    sub.prop(prefs, 'use_relative_range', text=text, icon=icon, icon_only=True)

    mpath = src.motion_path
    if mpath:
        sub = row.row(align=True)
        # sub.scale_x = 0.5
        if mpath.use_custom_color:
            sub.prop(mpath, 'color', icon_only=True)
        else:
            sub.active = False
            sub.prop(mpath, 'use_custom_color', icon_only=True,
                        icon='COLORSET_20_VEC')
        sub = row.row(align=True)
        sub.scale_x = 0.5
        sub.prop(mpath, 'line_thickness', icon_only=True, slider=True)

    if mp.has_motion_paths:
        if context.mode == 'POSE':
            clear = 'pose.paths_clear'
        else:
            clear = 'object.paths_clear'

        row.operator(clear, text="", icon='PANEL_CLOSE')

class MOTIONP_MT_subpanel(bpy.types.Menu):
    bl_description = ""
    bl_label = ""

    @classmethod
    def poll(self, context):
        return hasattr(context, 'src') and hasattr(context, 'mp')

    def draw(self, context):
        layout = self.layout
        src = context.src
        mp = context.mp
        mpath = src.motion_path

        layout.prop(mp, 'show_frame_numbers')  # , text="Frame Numbers")
        layout.prop(mp, 'show_keyframe_highlight')  # , text="Keyframes")
        if mp.show_keyframe_highlight:
            if Is.posebone(src):
                layout.prop(mp, 'show_keyframe_action_all',
                            text="+ Non-Grouped Keyframes")
            layout.prop(mp, 'show_keyframe_numbers', text="Keyframe Numbers")

        layout.separator()
        if Is.posebone(src):
            layout.label(text=src.name, icon='BONE_DATA')
        else:
            layout.label(text=src.name, icon='OBJECT_DATA')
        if mpath:
            layout.prop(mpath, 'lines')  # , text="Lines")
            layout.prop(mpath, 'use_custom_color')  # , text="Custom Color")
        else:
            op = 'zpy.update_motion_paths'
            layout.label(text="Add Motion Paths")
            layout.operator(op, text="At Heads").use_tails = False
            layout.operator(op, text="At Tails").use_tails = True

        layout.separator()
        mot = utils.prefs(__package__).motion
        layout.prop(mot, 'frame_before')
        layout.prop(mot, 'frame_after')

def register():
    bpy.types.TOPBAR_MT_editor_menus.append(draw_header)

def unregister():
    bpy.types.TOPBAR_MT_editor_menus.remove(draw_header)


# %%
import os
from pprint import pprint

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import tensorflow as tf
from classes.DataAccessor import get_data_for_composer, get_list_of_composers, load_data
from classes.DataIngester import Ingester
from classes.ModelCreator import Creator
from classes.DataGenerator import Generator

tf.config.run_functions_eagerly(True)
# %%
# In case you don't know which composers are available, you can use this function
main_data = load_data("./data/maestrov3.csv")
composers = get_list_of_composers(main_data)
# uncomment this next line to print the list of composers
# print(*composers, sep="\n")

# %%
# Load full dataset and filter data from a set of composers
midi_data = get_data_for_composer(main_data, ["Medtner"])
startTimes = midi_data[:, 0]
endTimes = midi_data[:, 1]
pitches = midi_data[:, 2]
velocities = midi_data[:, 3]
durations = np.round(midi_data[:, 4], 3)
# %%
# Roll dataset by memory length:
# How this works is, we feed the network a sequence of notes and attributes
# And we ask it to predict the next note and set of attributes
MEMORY = 32
startTimesIn, startTimesOut = Ingester().ingest_midi_for_neural_net1_ROLLFUNCTION(
    startTimes, MEMORY
)
pitchesIn, pitchesOut = Ingester().ingest_midi_for_neural_net1_ROLLFUNCTION(
    pitches, MEMORY
)
velocitiesIn, velocitiesOut = Ingester().ingest_midi_for_neural_net1_ROLLFUNCTION(
    velocities, MEMORY
)
durationsIn, durationsOut = Ingester().ingest_midi_for_neural_net1_ROLLFUNCTION(
    durations, MEMORY
)

# %%
# Construct our neural_net1 model
model = Creator().createModelForNeuralNet1(MEMORY, params_multiplier=10)

# %%
# The model.fit in this case might look abit scary but it's just a lot of parameters
# The important thing is that we are feeding the model the input and output data
# early_stopping = Creator().createEarlyStopper()
model.fit(
    {
        "startTimes": startTimesIn,
        "pitches": pitchesIn,
        "velocities": velocitiesIn,
        "durations": durationsIn,
    },
    {
        "outputStartTimes": startTimesOut,
        "outputPitches": pitchesOut,
        "outputVelocities": velocitiesOut,
        "outputDurations": durationsOut,
    },
    epochs=5,
    batch_size=1000,
)
# %%
# We use built in tensorflow save model function as RTNeural is not necessary for this model
model.save("saved_models_h5/neural_net1.h5")
# %%
# If you have already trained your model, you can load the model weights and skip the training step
model = tf.keras.models.load_model("saved_models_h5/neural_net1.h5")
print("Model Weights Loaded!")

# %%

outputArray = Generator().continuePieceUsingNeuralNet1(
    model, startTimesIn[-1], pitchesIn[-1], velocitiesIn[-1], durationsIn[-1], 100
)
# %%
plt.plot(outputArray[:, 1])
# %%
pathForMidi = "../neural_nets/output_midi/NeuralNet1_output.mid"
Generator().saveArrayAsMidi(outputArray, pathForMidi)

# %%


# Imports

__author__ = 'Fabian Schreier'
__version__ = "0.1.0"
__status__ = "Prototype"

import os
from typing import List, Tuple, Any, Iterable

import mat4py
import numpy as np
import scipy.io
from PIL import Image
from nptyping import NDArray

from . import datasets_folder, InputData, swap_columns

name = 'SaliCon'

def images_path(datasets_root: str = None) -> str:
    if datasets_root is None:
        datasets_root = datasets_folder
    return os.path.join(datasets_root, 'SaliCon/images/train')

def fixations_path(datasets_root: str = None) -> str:
    if datasets_root is None:
        datasets_root = datasets_folder
    return os.path.join(datasets_root, 'SaliCon/fixations/train')

def data_files(datasets_root: str = None) -> NDArray[(Any, 2), np.str]:

    ip = images_path(datasets_root)
    fp = fixations_path(datasets_root)

    res = []

    for f in os.listdir(ip):
        if not f.endswith('.jpg'):
            continue
        filename,_ = os.path.splitext(f)
        image_file = os.path.join(ip, f)
        fixation_file = os.path.join(fp, filename+'.mat')
        if not os.path.isfile(image_file) or not os.path.isfile(fixation_file):
            continue

        res.append((image_file,fixation_file))

    arry = np.asarray(res)
    # noinspection PyTypeChecker
    return arry

def load_data(randomize: bool = True, datasets_root: str = None) -> Iterable[InputData]:
    files = data_files(datasets_root)

    if randomize:
        np.random.shuffle(files)

    for img, fix in files[:,:]:
        img_data = Image.open(img)
        fix_data = scipy.io.loadmat(fix)

        name = fix_data['image'][0]
        image = np.asarray(img_data)
        scanpaths = [(str(obs_i), swap_columns(sp)) for obs_i, sp in enumerate(np.squeeze(fix_data['gaze']['fixations']))]

        yield InputData(
            name=name,
            image_data=image,
            scanpaths=scanpaths,
            gt_scanpaths=[]
        )


import tornado.web
import config

from tornado.escape import json_decode
from services import LoanService

# Constants of the module
_bad_request_code = 400
_bad_request_message = 'Bad Request. Your browser sent a request that this server could not understand.'

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write(config.version)

class LoanHandler(tornado.web.RequestHandler):
    def set_default_headers(self):
        methods = 'POST, OPTIONS'
        headers = 'access-control-allow-origin,authorization,content-type,x-requested-with'
        self.set_header('Access-Control-Allow-Origin', '*')
        self.set_header('Access-Control-Allow-Methods', methods)
        self.set_header('Access-Control-Allow-Headers', headers)

    def options(self):
        self.set_status(204)
        self.finish()

    def post(self):
        try:
            request = json_decode(self.request.body)
            self.validate_request(request)
            result = LoanService().validate_loan(request['amount'])
            self.write(result)
        except:
            self.clear()
            self.set_status(_bad_request_code)
            self.write(_bad_request_message)

    def validate_request(self, request):
        if not request['amount']:
            raise ValueError(_bad_request_message)
        else:
            request['amount'] = int(float(request['amount']))


from PattRecClasses.MarkovChain import MarkovChain
from PattRecClasses.GaussD import GaussD
from PattRecClasses.HMM import HMM
from utils.functionality import likelihood, hmm_test
from utils.load_data import plot_data
import numpy as np
import matplotlib.pyplot as plt

# define distribution and observed data
g1 = GaussD(means=[0, 0, 0], cov=np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]))
g2 = GaussD(means=[0, 0, 0], cov=np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]))
g3 = GaussD(means=[0, 0, 0], cov=np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]))
g = [g1, g2, g3]
q = np.array([1, 0, 0])
A = np.array([[0.8, 0.1, 0.1], [0.1, 0.8, 0.1], [0.1, 0.1, 0.8]])

train_data = np.load('./data/train_data.npy').T
def hmm_train(q, A, g, x):
    """
    One iteration HMM training function using the EM algorithm
        Input parameters:
            q: the initial state probabilities, len(q) = num_state
            A: transition matrix of hmm, len(q) = A.shape[0]
            g: the output distribution list, each element of g should be an object created from
                the class GaussD. The length of g len(g) should equal to the number of State
                that is, len(g) = len(q) = A.shape[0]
            x: observed sequence of shape [data dimensions, number of samples: T]
                data dimensions = mean.shape[0] = cov.shape[0], mean and cov are the mean and covariance
                matrix of the GaussianD objects.

        Output parameters:
            q_new: updated q
            A_new: updated A
            mean_new: list of new mean matrix for the updated Gaussian distributions
            cov_new: list of new covariance matrix for the updated Gaussian distributions
    """

    mc = MarkovChain(q, A)
    pX = likelihood(g, x)
    # print(pX)
    pX_scaled = pX / np.max(pX, axis=0)  # normalized
    # print(pX_scaled)

    # forward
    alpha_hat, c = mc.forward(pX_scaled)

    # backward
    beta_hat = mc.backward(c, pX_scaled)

    # total conditional probability
    gamma = [[] for t in range(len(alpha_hat))]

    for j in range(len(gamma)):
        gamma[j] = [alpha_hat[j][t] * beta_hat[j][t] * c[t] for t in range(len(alpha_hat[0]))]

    # training
    # update q
    q_new = [gamma[0][i] for i in range(len(gamma[0]))]  # eq 7.55
    # print("q_new = \n", q_new)

    # update A
    epsilon = [np.zeros(A.shape) for t in range(len(alpha_hat))]
    alpha_hat = np.array(alpha_hat).T
    beta_hat = np.array(beta_hat).T
    num_state = A.shape[0]
    epsilon_bar = np.zeros(epsilon[0].shape)

    for t in range(len(epsilon) - 1):
        for i in range(num_state):
            for j in range(num_state):
                epsilon[t][i, j] = alpha_hat[i, t] * A[i, j] * pX_scaled[j, t + 1] * beta_hat[j, t + 1]
                # eq 6.19
        epsilon_bar += epsilon[t]

    epsilon_sum = np.sum(epsilon_bar)  # eq 6.15 and eq 6.16
    A_new = np.zeros(A.shape)

    for i in range(A.shape[0]):
        for j in range(A.shape[1]):
            A_new[i, j] = epsilon_bar[i, j] / np.sum(epsilon_bar[i, :])  # eq 6.13

    # print("A = \n", A)
    # print("A_new = \n", A_new)

    # update B
    gamma = np.array(gamma).T
    mean_new = []
    for i in range(len(g)):
        numerator = [gamma[i, t] * x[:, t] for t in range(x.shape[1])]
        numerator = np.sum(numerator, axis=0)
        mu_new_i = numerator / np.sum(gamma[i, :])
        mean_new.append(mu_new_i)

    # print("covariance new = \n", mean_new)

    cov_new = []
    for i in range(len(g)):
        numerator = None
        for t in range(x.shape[1]):
            res1 = np.expand_dims((x[:, t] - mean_new[i]), axis=1)
            res_product = res1 @ res1.T
            numerator = gamma[i, t] * res_product if t == 0 else numerator + gamma[i, t] * res_product
        cov_new.append(numerator / np.sum(gamma[i, :]))  # eq 7.70

    # print("covariance new = \n", cov_new)

    return q_new, A_new, mean_new, cov_new

# train
epochs = 20  # number of training iterations
q_i, A_i, mean_i, cov_i, g_i = None, None, None, None, None
for iteration in range(epochs):
    print("training iteration:", iteration+1)
    if iteration == 0:
        q_i, A_i, mean_i, cov_i = hmm_train(q, A, g, train_data)  # first update based on initialized parameters
    else:
        g1 = GaussD(means=mean_i[0], cov=cov_i[0])
        g2 = GaussD(means=mean_i[1], cov=cov_i[1])
        g3 = GaussD(means=mean_i[2], cov=cov_i[2])
        g_i = [g1, g2, g3]
        q_i, A_i, mean_i, cov_i = hmm_train(q_i, A_i, g_i, train_data)  # update based on previous updated parameters

print('updated q=','\n', q_i, '\n', 'updated A matrix=', '\n', A_i,'\n', 'updated mean vector=', '\n', mean_i,'\n',
      'updated Covariance matrix=', '\n', cov_i, '\n')
# test
test_data = np.load('./data/test_data.npy').T
state_seq, gamma = hmm_test(q_i, A_i, g_i, train_data)

plt.plot(state_seq)
plt.xlabel("t")
plt.ylabel("predicted state")
plt.title("State predicted state sequence")
plt.show()

plot_data(test_data.T)


try:
    from time import perf_counter_ns

    def time_ns():
        return perf_counter_ns()

except:
    # python < 3.7
    from time import perf_counter

    def time_ns():
        return int(perf_counter() * (1000000))

import sys
import logging

logger = logging.getLogger(__name__)

"""
    a simplified line by line profiler

    usage:

        ...
        checkpoint_start() #1
        ...
        checkpoint('name1') #2
        ...
        checkpoint('name2') #3

    saves information how much cummulative time
    passed between #1 and #2 (name1), and #2 and #3 (name2)

    use log_checkpoints to show results

    func_caller is useful, when you want to differenciate by function
    caller

    usage:

    def some_func():
        checkpoint_start()
        STUFF
        checkpoint('name'+func_caller())

    def func_a():
        some_func()

    def func_b():
        some_func()

    log_checkpoints()
    shows time spent in some_func, split by the time
    when it was called by func_a and func_b

"""

results = {}
last_checkpoint = ""
last_ns = time_ns()

def checkpoint(name):
    global results
    global last_ns

    new_ns = time_ns()

    if name in results:
        results[name] += new_ns - last_ns
    else:
        results[name] = new_ns - last_ns

    last_ns = new_ns

def checkpoint_start():
    global last_ns
    last_ns = time_ns()

def log_checkpoints():
    return
    for name, elapsed in results.items():
        logger.info(f"Profiler: {name}\t\t- {elapsed / 1000000000}")

    for name, elapsed in counters.items():
        logger.info(f"Profiler: {name}\t\t- {elapsed}")

print_checkpoints = log_checkpoints

counters = {}

def count(x):
    if x in counters:
        counters[x] += 1
    else:
        counters[x] = 1

def func_caller(depth=1):
    # returns caller of a function
    # useful when you want to differenciate checkpoints by who the function caller is
    return sys._getframe(2 + depth).f_code.co_name


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import socket
import crcmod
import struct
import json
import time
import random
import datetime,os

DURATION = 10.0 # in seconds
DEVICE_IP = "192.168.5.32"
LOCAL_IP = "192.168.2.6"
LOCAL_PORT = 2229

def CreateDir():
    print('CreateDir')
    now_date = datetime.datetime.now().strftime('%Y_%m_%d')
    now_time = datetime.datetime.now().strftime('%H_%M_%S')
    pwd = '/Users/alexis/Desktop/pickup-test' + '/' + now_date + '/' + now_time + '/'
    os.makedirs(pwd)

    for i in range(9):
        a[i] = open('%s' % pwd + 'org_channel%d.pcm' % (i + 1), 'wb')

def test_build_packet(req, packet_type=1):
    if isinstance(req, dict):
        payload = json.dumps(req).encode()
    elif isinstance(req, bytes):
        payload = req
    else:
        assert False
    header = struct.pack('<HHB',
        0x7E7E,
        len(payload) + 3,
        packet_type,
    )
    crc = crcmod.predefined.Crc('modbus')
    crc.update(header[4:])
    crc.update(payload)
    chksum = struct.pack('<H', crc.crcValue)
    return header, payload, chksum

def test_net_request(req, packet_type=1):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((DEVICE_IP, 2228))
    s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
    header, payload, chksum = test_build_packet(req, packet_type)
    print('request: header =', header, ', checksum =', chksum)
    print(req)
    s.sendall(header)
    s.sendall(payload)
    s.sendall(chksum)
    s.close()

def test_main():
    test_net_request(dict(cmd='set_device_info', device_id='xxxxxx'))
    test_net_request(dict(cmd='get_device_info'))
    test_net_request(dict(cmd='set_audio', output_gain=35))
    test_net_request(dict(cmd='get_audio'))

    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind((LOCAL_IP, LOCAL_PORT))

    # Create a new session ID
    session_id = random.randint(1, 0xFFFFFFFF)

    test_net_request(dict(
        cmd='open_audio',
        session_id=session_id,
        server_addr='{}:{}'.format(LOCAL_IP, LOCAL_PORT),
        output_channel=9,
        audio_encoder=3, # SG_AUDIO_PCMS24LE
        audio_channels=1, # mono
        audio_frame_size=320, # samples per frame
        audio_sample_rate=16000,
        audio_bitrate=0, # no use for PCM
        retrans_timeout=1000, # threshold of retransmission timeout, in milliseconds
    ))

    packets = {}

    # Variables to calculate the actual audio frame size
    samples_per_frame = None
    fragments_per_frame = 0
    frag_size = 0
    frag_sn = -1
    frag_ts = -1

    recv_data = b''

    with open("pickup.pcm", "wb") as f:
        current_sn = None
        now = time.time()
        n = 0
        while now + DURATION >= time.time():
            (rsp, addr) = s.recvfrom(1500)
            n += 1

            if n % 100 == 0 and current_sn is not None:
                # Send ACK
                ack = struct.pack('<IHHI', session_id, 1, 0, current_sn)
                #s.sendto(b''.join(test_build_packet(ack, packet_type=4)), addr)

            magic, len_, type_ = struct.unpack('<HHB', rsp[:5])
            assert len_ + 4 == len(rsp)
            crc = crcmod.predefined.Crc('modbus')
            crc.update(rsp[4:])
            assert crc.crcValue == 0

            audio_pkt = rsp[5:-2]
            (sid, sn, timestamp, reserved, output_channel, audio_encoder,
             audio_channels, audio_sample_rate, audio_frame_size, payload_size) = struct.unpack(
                '<IIQBBBBIHH', audio_pkt[:28]
            )
            assert 28 + payload_size == len(audio_pkt)

            # Session ID must match.
            if sid != session_id:
                continue

            # Here, we calculate the actual frame size.
            # A frame may be splitted into several fragments, and each fragment has the same timestamp.
            if samples_per_frame is None:
                if frag_sn + 1 == sn:
                    if frag_size == 0:
                        if frag_ts != timestamp:
                            frag_size = audio_frame_size
                            fragments_per_frame = 1
                    elif frag_ts == timestamp:
                        frag_size += audio_frame_size
                        fragments_per_frame += 1
                    else:
                        samples_per_frame = frag_size
                        print("Samples per frame:", samples_per_frame, ", fragments:", fragments_per_frame)
                else:
                    frag_size = 0
                frag_sn = sn
                frag_ts = timestamp

            if current_sn is None:
                # The first frame.
                current_sn = sn
            else:
                delta = (sn - current_sn) & 0xFFFFFFFF
                if delta & 0x80000000:
                    delta -= 0x100000000
                if delta == 1:
                    # Sn is continuous.
                    current_sn += 1
                elif delta < 0:
                    print("****************** delta", delta, sn)
                    continue
                elif delta > 0:
                    print("****************** delta", delta, sn)
                    continue

            print(sid, sn, timestamp / 1000, output_channel, audio_encoder,
                audio_channels, audio_sample_rate, audio_frame_size, payload_size)

            recv_data = audio_pkt[-payload_size:]
            pData = bytearray(payload_size + 1)

            for i in range(audio_frame_size):
                for j in range(output_channel):
                    pData[3 * audio_frame_size * j + 3 * i] = (recv_data[3 * output_channel * i + 3 * j ] & 0xFF)
                    pData[3 * audio_frame_size * j + 3 * i + 1] = (recv_data[3 * output_channel * i + 3 * j + 1] & 0xFF)
                    pData[3 * audio_frame_size * j + 3 * i + 2] = (recv_data[3 * output_channel * i + 3 * j + 2] & 0xFF)
                    if i == (audio_frame_size-1):
                        tempData = pData[3 * audio_frame_size * j: 3 * audio_frame_size * j + audio_frame_size * 3]
                        a[j].write(tempData)

            # f.write(audio_pkt[-payload_size:])

    test_net_request(dict(cmd='close_audio', session_id=session_id))

if __name__ == "__main__":
    a = {}
    CreateDir()
    test_main()


import argparse
import os

from pytorch_fid.fid_score import calculate_fid_given_paths

if __name__ == '__main__':

    parser = argparse.ArgumentParser()
    parser.add_argument("--inpainted_dir", type=str, default="places2/images/inpainted/0.2/DF-Net",
                        help='directory of the images to classify')
    parser.add_argument("--original_image_dir", type=str, default="places2/images/original",
                        help='directory of the original images')
    parser.add_argument("--batch_size", type=int, default=50, help='batch size')
    parser.add_argument("--gpu", type=str, default='0', help='GPU id, -1 for CPU')

    args = parser.parse_args()

    os.environ['VISIBLE_CUDA_DEVICES'] = args.gpu

    method = args.inpainted_dir.split('/')[-1]
    mask = float(args.inpainted_dir.split('/')[-2])

    fid = calculate_fid_given_paths([args.original_image_dir, args.inpainted_dir], args.batch_size, args.gpu, 2048)
    print('FID for {}, with {}% mask: {}'.format(method, int(mask * 100), fid))


from itertools import permutations

class Box:
    def __init__(self, width, length, height):
        self.width = width
        self.length = length
        self.height = height

    def __lt__(self, other):
        return self.width < other.width and self.length < other.length

    def __repr__(self):
        return f"({self.width},{self.length},{self.height})"

def max_height(boxes):
    boxes = sorted(boxes, key=lambda box: (box.width, box.length))
    max_stack_height = [box.height for box in boxes]
    for i in range(0, len(boxes)):
        for j in range(0, i):
            if boxes[j] < boxes[i]:
                new_max_stack_height = max_stack_height[j] + boxes[i].height
                if new_max_stack_height > max_stack_height[i]:
                    max_stack_height[i] = new_max_stack_height

    return max(max_stack_height)

if __name__ == "__main__":
    boxes = [(4, 2, 5), (3, 1, 6), (3, 2, 1), (6, 3, 8)]
    all_possible_arrangements = list()
    for box_dimension in boxes:
        for dimensions in permutations(box_dimension):
            all_possible_arrangements.append(
                Box(dimensions[0], dimensions[1], dimensions[2])
            )
    print(max_height(all_possible_arrangements))


import logging

import numpy

import imagecat.data
import imagecat.operator.util
import imagecat.units

log = logging.getLogger(__name__)

def gaussian(graph, name, inputs):
    """Blur an :ref:`image<images>` using a Gaussian kernel.

    Parameters
    ----------
    graph: :ref:`graph`, required
        Graph that owns this task.
    name: hashable object, required
        Name of the task executing this function.
    inputs: :ref:`named-inputs`, required
        Inputs for this operator.

    Named Inputs
    ------------
    image: :class:`imagecat.data.Image`, required
        Image containing layer to be blurred.
    layer: :class:`str`, optional
        Name of the layer to be blurred.  Default: :any:`None`.
    sigma: (x, y) tuple, required
        Width of the gaussian kernel in pixels along each dimension.

    Returns
    -------
    image: :class:`imagecat.data.Image`
        A copy of the input image with some layers blurred.
    """
    import skimage.filters

    inlayer = imagecat.operator.util.optional_input(name, inputs, "layer", default=None)
    layer_name, layer = imagecat.operator.util.require_layer(name, inputs, "image", layer=inlayer)
    radius = imagecat.operator.util.optional_input(name, inputs, "radius", default=["5px", "5px"])

    data = layer.data
    sigma = [
        imagecat.units.length(radius[1], layer.res),
        imagecat.units.length(radius[0], layer.res),
        ]
    data = numpy.atleast_3d(skimage.filters.gaussian(data, sigma=sigma, multichannel=True, preserve_range=True).astype(data.dtype))

    image = imagecat.data.Image(layers={layer_name: layer.copy(data=data)})
    imagecat.operator.util.log_result(log, name, "gaussian", image, layer=inlayer, radius=radius)
    return image


from ferris import BasicModel, ndb

from google.appengine.api import users
from google.appengine.api import app_identity
from app.models.beck_user import BeckUser
from app.models.customer import Customer
from app.settings import settings
import logging
import uuid
from plugins.firebase_rest import FirebaseRest

def user_authorization(controller):

    from_mobile = False
    is_admin = False
    user = None

    public_routes = (
        'refresh_token',
        'register',
        'vehicle_refresh_token',
        'web_order',
        'get_all_orders',
        'auth_refresh_token_cron'
    )

    # filter route with no credentials needed
    if controller.route.action in public_routes:
        return True

    # Special testing override for the automated performance tests.
    # Enabled only on localhost and the QA server.
    # Hardcoded testing only token.
    testing_token = controller.request.headers.get('testing_token')
    if (app_identity.get_application_id() == 'cs-becktaxi-omda-dev' \
        or app_identity.get_application_id() == 'cs-becktaxi-omda-qa') \
        and testing_token \
        and testing_token == settings['testing_override']['token']:
        user = BeckUser.get_by_email_address(
            settings['testing_override']['email']
        )
        # Create a new testing override user
        if not user:
            user = BeckUser()
            user.first_name = 'testing'
            user.last_name = 'override'
            user.email = settings['testing_override']['email']
            user.role = "SYSTEM_ADMINISTRATOR"
            user.put()
        controller.context['user_role'] = 'SYSTEM_ADMINISTRATOR'
        logging.info("Test token authentication successful")
        # return True

    # # route with temporary access
    # if controller.route.action in ('validate_sms', 'request_sms'):
    #     from_mobile = True
    #     temp_code = controller.request.headers.get('temporary_code')
    #     user = Auth.validate_temp(temp_code)

    # get user by token
    token = controller.request.headers.get('token')
    logging.info("TOKEN ===> %s" % token)
    if token:
        from_mobile = True
        user = Auth.validate(token)
        if user:
            # user exist but check if pending or locked
            if user.status == 'PENDING' or user.status == 'SUSPENDED' or user.locked:
                user = None

    # if no token, check if has google credentials logged in
    if user is None:
        # get user by google credentials
        try:
            user_email = str(users.get_current_user().email())
            user = BeckUser.get_by_id(user_email)

            if not user:
                # allow admin and create profile
                if users.is_current_user_admin():
                    user = BeckUser(id=user_email)
                    user.first_name = user_email
                    user.last_name = user_email
                    user.email = user_email
                    user.role = "SYSTEM_ADMINISTRATOR"
                    user.put()
        except:
            pass

        if user:
            # check IP address if allowed
            ip = controller.request.remote_addr
            allowed_ip = settings.get('allowed_ip')

            if ip in allowed_ip or user.role in ('SYSTEM_ADMINISTRATOR', 'ADMINISTRATOR'):
                pass
            else:
                return False

    if user is None:
        """ Unauthorized """
        return False

    else:
        logging.info('=== USER IS %s ===' % str(user))
        """ valid users """
        if not from_mobile:

            """ users from google """

            if user.locked:
                return False

            controller.context['user_role'] = user.role
            if user.email == settings['testing_override']['email']:
                controller.context['user_object'] = None
                controller.context['logout_url'] = None
            else:
                controller.context['user_object'] = users.get_current_user()
                controller.context['logout_url'] = users.create_logout_url(controller.request.uri)
            controller.session['logged_in_user'] = user

            f = FirebaseRest('foo')
            firebase_setting = f.get_env_settings()

            controller.context['FIREBASE_URL'] = firebase_setting['url']

            if user.role == 'SYSTEM_ADMINISTRATOR' or user.role == 'ADMINISTRATOR' or user.role == 'SUPERVISOR' or user.role == 'SHIFT_LEADER':
                is_admin = True

        """ default user details """

        # customers and drivers
        controller.context['user_email'] = user.email if isinstance(user, BeckUser) else None
        controller.context['auth_user'] = user
        controller.context['auth_user_dict'] = user.to_dict()
        controller.context['is_admin'] = is_admin
        controller.context['from_mobile'] = from_mobile
        logging.info('auth allowed!')
        return True

def allow_access(controller, roles=None, allow_admin=True):
    if allow_admin:
        if controller.context.get('user_role') in ('SYSTEM_ADMINISTRATOR', 'ADMINISTRATOR', 'SUPERVISOR', 'SHIFT_LEADER'):
            return True

        if users.is_current_user_admin():
            return True

        if controller.context.get('is_admin'):
            return True

    context_user_role = controller.context.get('user_role', None)
    if context_user_role:
        if context_user_role in roles:
            return True
        else:
            return False

    # last check, OMDA users should not reach this point, only for authenticatd users via Auth
    if controller.context.get('auth_user'):
        return True

    return False

def csr(f):
    def wrapper(*args, **kw):
        if args[0].context.get('user_role') == 'CSR':
            return False
        else:
            return f(*args, **kw)
    return wrapper

class AuthModel(BasicModel):
    object_key = ndb.KeyProperty(required=False)
    code = ndb.StringProperty(indexed=True, required=True)
    code_last_refreshed = ndb.DateTimeProperty(required=False)
    temporary_code = ndb.StringProperty(indexed=True, required=False)
    token = ndb.StringProperty(indexed=True, required=False)
    token_last_refreshed = ndb.DateTimeProperty(required=False)

    def all(cls):
        return cls.query()

    @classmethod
    def delete(cls, key):
        logging.info(key)
        obj = AuthModel.query(AuthModel.object_key == key).get()
        obj.key.delete()

class Auth(object):

    @classmethod
    def validate(self, token):
        obj = AuthModel.find_by_properties(token=token)
        if obj:
            entity = obj.object_key.get()
            logging.info('Auth Object =====> %s' % entity)
            self.user = entity
            return entity
        else:
            return None

    @classmethod
    def validate_temp(self, code):
        obj = AuthModel.find_by_properties(temporary_code=code)
        if obj:
            entity = obj.object_key.get()
            logging.info('Auth Object =====> %s' % entity)
            self.user = entity
            return entity
        else:
            return None

    @classmethod
    def create_code(self, object_key, code=None):
        auth = AuthModel(id=object_key.urlsafe())
        auth.object_key = object_key

        auth.code = str(uuid.uuid4()) if code is None else code
        auth.temporary_code = str(uuid.uuid4())
        auth.put()
        return auth

    @classmethod
    def refresh_token(self, code, field, value):

        find_token = AuthModel.find_by_properties(code=code)
        token = None
        logging.info("ibject ==> %s" % find_token)
        if find_token:
            obj = find_token.object_key.get()
            if getattr(obj, field) == value:
                find_token.token = str(uuid.uuid4())
                find_token.put()

                token = find_token.token
        if token:
            return '{"token" : "%s"}' % token
        return 401

    @classmethod
    def generate_code(self):
        return str(uuid.uuid4())

    @classmethod
    def find(self, object_key):
        user = AuthModel.find_by_properties(object_key=object_key)
        return user