import numpy as np
from math import sqrt, hypot

from .point import Point
from .vector import Vector

class Line():

    def __init__(self, *args):
        """ Constructs a line object. If 2 arguments given it is constructed
        between two points. If 3 arguments are given it is constructed from
        start point, direction vector and length along the vector.
        """
        if len(args) == 2:
            self.by2Points(args[0], args[1])
        elif len(args) == 3:
            self.bySDL(args[0], args[1], args[2])

    def by2Points(self, start=Point([0,0]), end=Point([1,1])):
        # Convert to geom classes if lists given
        if type(start) in [list,tuple]:
            start = Point(start)
        if type(end) in [list,tuple]:
            end = Point(end)
        self.start = start
        self.end = end

    def bySDL(self, start=Point(0,0), direction=Vector(1,0), length=2):
        # Convert to geom classes if lists given
        if type(start) in [list, tuple, Vector]:
            start = Point(start)
        if type(direction) in [list, tuple, Point]:
            direction = Vector(direction)

        self.start = start

        #Normalize direction vector and set it to correct length
        move_vector = Vector(direction).set_length(length)
        self.end = self.start + move_vector

    def __str__(self):
        return "Line(start=%s, end=%s)"%(self.start,self.end)

    def length(self):
        line_vector = self.end-self.start
        return hypot(line_vector[0], line_vector[1])

    def intersects(self, line):
        """ function computes the point of collision between self and line.
        Input: line

        Returns:
        Tuple of coordinates (x,y,z) for the point of collision. If no collision
        exists, (None,None,None) is returned. """

        # Definitions
        def overlap(a, b):
            return max(0, min(a[1], b[1]) - max(a[0], b[0]))

        p, p2 = np.array(self.start), np.array(self.end)
        q, q2 = np.array(line.start), np.array(line.end)
        r = np.subtract(p2, p)
        s = np.subtract(q2, q)
        qpr = np.cross(np.subtract(q, p), r)
        rs = np.cross(r, s)

        # Determine if Directions intersect
        if np.all(rs == 0) and np.all(qpr == 0):
            #lines are colinear (ligger på linie)
            t0 = np.dot(np.subtract(line.start, p), r) / np.dot(r, r)
            t1 = t0 + np.dot(s, r) / np.dot(r, r)
            if overlap([0.,1.], [t0,t1]) > 0:
                # colinear and overlapping (på linie og oveni hinanden)
                return (np.inf, np.inf)
            else:
                # colinear and disjoint (på linie men efter hinanden)
                return (None,None)

        # Determine if Directions intersect
        elif np.all(rs == 0):
            # Parallel and non-intersecting
            return (None,None)

        # Determine if segments intersect
        t = np.divide(np.cross(np.subtract(q,p),s),rs)
        u = np.divide(qpr, rs)
        if not np.all(qpr == 0) and 0 >= t or t >= 1 or 0 >= u or u >= 1:
            # Not parallel but do not intersect
            return (None,None)

        # Calculate point of intersection
        intersection = (line.start + u*s)

        return intersection

if __name__ == "__main__":
    line = Line([0,0],[10,10])
    print(line)

    line2 = Line([10,0],[-0.5, 0.5], 14.14)
    print(line2)

    intersection = line.intersects(line2)
    print(intersection)


import typing
import warnings

import tensorflow as tf

@tf.keras.utils.register_keras_serializable(package="Addons")
class MultiHeadAttention(tf.keras.layers.Layer):
    r"""MultiHead Attention layer.

    Defines the MultiHead Attention operation as described in
    [Attention Is All You Need](https://arxiv.org/abs/1706.03762) which takes
    in the tensors `query`, `key`, and `value`, and returns the dot-product attention
    between them:

    >>> mha = MultiHeadAttention(head_size=128, num_heads=12)
    >>> query = np.random.rand(3, 5, 4) # (batch_size, query_elements, query_depth)
    >>> key = np.random.rand(3, 6, 5) # (batch_size, key_elements, key_depth)
    >>> value = np.random.rand(3, 6, 6) # (batch_size, key_elements, value_depth)
    >>> attention = mha([query, key, value]) # (batch_size, query_elements, value_depth)
    >>> attention.shape
    TensorShape([3, 5, 6])

    If `value` is not given then internally `value = key` will be used:

    >>> mha = MultiHeadAttention(head_size=128, num_heads=12)
    >>> query = np.random.rand(3, 5, 5) # (batch_size, query_elements, query_depth)
    >>> key = np.random.rand(3, 6, 10) # (batch_size, key_elements, key_depth)
    >>> attention = mha([query, key]) # (batch_size, query_elements, key_depth)
    >>> attention.shape
    TensorShape([3, 5, 10])

    Args:
        head_size: int, dimensionality of the `query`, `key` and `value` tensors
            after the linear transformation.
        num_heads: int, number of attention heads.
        output_size: int, dimensionality of the output space, if `None` then the
            input dimension of `value` or `key` will be used,
            default `None`.
        dropout: float, `rate` parameter for the dropout layer that is
            applied to attention after softmax,
        default `0`.
        use_projection_bias: bool, whether to use a bias term after the linear
            output projection.
        return_attn_coef: bool, if `True`, return the attention coefficients as
            an additional output argument.
        kernel_initializer: initializer, initializer for the kernel weights.
        kernel_regularizer: regularizer, regularizer for the kernel weights.
        kernel_constraint: constraint, constraint for the kernel weights.
        bias_initializer: initializer, initializer for the bias weights.
        bias_regularizer: regularizer, regularizer for the bias weights.
        bias_constraint: constraint, constraint for the bias weights.

    Call Args:
        inputs:  List of `[query, key, value]` where
            * `query`: Tensor of shape `(..., query_elements, query_depth)`
            * `key`: `Tensor of shape '(..., key_elements, key_depth)`
            * `value`: Tensor of shape `(..., key_elements, value_depth)`, optional, if not given `key` will be used.
        mask: a binary Tensor of shape `[batch_size?, num_heads?, query_elements, key_elements]`
        which specifies which query elements can attendo to which key elements,
        `1` indicates attention and `0` indicates no attention.

    Output shape:
        * `(..., query_elements, output_size)` if `output_size` is given, else
        * `(..., query_elements, value_depth)` if `value` is given, else
        * `(..., query_elements, key_depth)`
    """

    def __init__(
        self,
        head_size: int,
        num_heads: int,
        output_size: int = None,
        dropout: float = 0.0,
        use_projection_bias: bool = True,
        return_attn_coef: bool = False,
        kernel_initializer: typing.Union[str, typing.Callable] = "glorot_uniform",
        kernel_regularizer: typing.Union[str, typing.Callable] = None,
        kernel_constraint: typing.Union[str, typing.Callable] = None,
        bias_initializer: typing.Union[str, typing.Callable] = "zeros",
        bias_regularizer: typing.Union[str, typing.Callable] = None,
        bias_constraint: typing.Union[str, typing.Callable] = None,
        **kwargs,
    ):
        warnings.warn(
            "`MultiHeadAttention` will be deprecated in Addons 0.13. "
            "Please use `tf.keras.layers.MultiHeadAttention` instead.",
            DeprecationWarning,
        )

        super().__init__(**kwargs)

        if output_size is not None and output_size < 1:
            raise ValueError("output_size must be a positive number")

        self.head_size = head_size
        self.num_heads = num_heads
        self.output_size = output_size
        self.use_projection_bias = use_projection_bias
        self.return_attn_coef = return_attn_coef

        self.kernel_initializer = tf.keras.initializers.get(kernel_initializer)
        self.kernel_regularizer = tf.keras.regularizers.get(kernel_regularizer)
        self.kernel_constraint = tf.keras.constraints.get(kernel_constraint)
        self.bias_initializer = tf.keras.initializers.get(bias_initializer)
        self.bias_regularizer = tf.keras.regularizers.get(bias_regularizer)
        self.bias_constraint = tf.keras.constraints.get(bias_constraint)

        self.dropout = tf.keras.layers.Dropout(dropout)
        self._droput_rate = dropout

    def build(self, input_shape):

        num_query_features = input_shape[0][-1]
        num_key_features = input_shape[1][-1]
        num_value_features = (
            input_shape[2][-1] if len(input_shape) > 2 else num_key_features
        )
        output_size = (
            self.output_size if self.output_size is not None else num_value_features
        )

        self.query_kernel = self.add_weight(
            name="query_kernel",
            shape=[self.num_heads, num_query_features, self.head_size],
            initializer=self.kernel_initializer,
            regularizer=self.kernel_regularizer,
            constraint=self.kernel_constraint,
        )
        self.key_kernel = self.add_weight(
            name="key_kernel",
            shape=[self.num_heads, num_key_features, self.head_size],
            initializer=self.kernel_initializer,
            regularizer=self.kernel_regularizer,
            constraint=self.kernel_constraint,
        )
        self.value_kernel = self.add_weight(
            name="value_kernel",
            shape=[self.num_heads, num_value_features, self.head_size],
            initializer=self.kernel_initializer,
            regularizer=self.kernel_regularizer,
            constraint=self.kernel_constraint,
        )
        self.projection_kernel = self.add_weight(
            name="projection_kernel",
            shape=[self.num_heads, self.head_size, output_size],
            initializer=self.kernel_initializer,
            regularizer=self.kernel_regularizer,
            constraint=self.kernel_constraint,
        )

        if self.use_projection_bias:
            self.projection_bias = self.add_weight(
                name="projection_bias",
                shape=[output_size],
                initializer=self.bias_initializer,
                regularizer=self.bias_regularizer,
                constraint=self.bias_constraint,
            )
        else:
            self.projection_bias = None

        super().build(input_shape)

    def call(self, inputs, training=None, mask=None):

        # einsum nomenclature
        # ------------------------
        # N = query elements
        # M = key/value elements
        # H = heads
        # I = input features
        # O = output features

        query = inputs[0]
        key = inputs[1]
        value = inputs[2] if len(inputs) > 2 else key

        # verify shapes
        if key.shape[-2] != value.shape[-2]:
            raise ValueError(
                "the number of elements in 'key' must be equal to the same as the number of elements in 'value'"
            )

        if mask is not None:
            if len(mask.shape) < 2:
                raise ValueError("'mask' must have atleast 2 dimensions")
            if query.shape[-2] != mask.shape[-2]:
                raise ValueError(
                    "mask's second to last dimension must be equal to the number of elements in 'query'"
                )
            if key.shape[-2] != mask.shape[-1]:
                raise ValueError(
                    "mask's last dimension must be equal to the number of elements in 'key'"
                )

        # Linear transformations
        query = tf.einsum("...NI , HIO -> ...NHO", query, self.query_kernel)
        key = tf.einsum("...MI , HIO -> ...MHO", key, self.key_kernel)
        value = tf.einsum("...MI , HIO -> ...MHO", value, self.value_kernel)

        # Scale dot-product, doing the division to either query or key
        # instead of their product saves some computation
        depth = tf.constant(self.head_size, dtype=query.dtype)
        query /= tf.sqrt(depth)

        # Calculate dot product attention
        logits = tf.einsum("...NHO,...MHO->...HNM", query, key)

        # apply mask
        if mask is not None:
            mask = tf.cast(mask, tf.float32)

            # possibly expand on the head dimension so broadcasting works
            if len(mask.shape) != len(logits.shape):
                mask = tf.expand_dims(mask, -3)

            logits += -10e9 * (1.0 - mask)

        attn_coef = tf.nn.softmax(logits)

        # attention dropout
        attn_coef_dropout = self.dropout(attn_coef, training=training)

        # attention * value
        multihead_output = tf.einsum("...HNM,...MHI->...NHI", attn_coef_dropout, value)

        # Run the outputs through another linear projection layer. Recombining heads
        # is automatically done.
        output = tf.einsum(
            "...NHI,HIO->...NO", multihead_output, self.projection_kernel
        )

        if self.projection_bias is not None:
            output += self.projection_bias

        if self.return_attn_coef:
            return output, attn_coef
        else:
            return output

    def compute_output_shape(self, input_shape):
        num_value_features = (
            input_shape[2][-1] if len(input_shape) > 2 else input_shape[1][-1]
        )
        output_size = (
            self.output_size if self.output_size is not None else num_value_features
        )

        output_shape = input_shape[0][:-1] + (output_size,)

        if self.return_attn_coef:
            num_query_elements = input_shape[0][-2]
            num_key_elements = input_shape[1][-2]
            attn_coef_shape = input_shape[0][:-2] + (
                self.num_heads,
                num_query_elements,
                num_key_elements,
            )

            return output_shape, attn_coef_shape
        else:
            return output_shape

    def get_config(self):
        config = super().get_config()

        config.update(
            head_size=self.head_size,
            num_heads=self.num_heads,
            output_size=self.output_size,
            dropout=self._droput_rate,
            use_projection_bias=self.use_projection_bias,
            return_attn_coef=self.return_attn_coef,
            kernel_initializer=tf.keras.initializers.serialize(self.kernel_initializer),
            kernel_regularizer=tf.keras.regularizers.serialize(self.kernel_regularizer),
            kernel_constraint=tf.keras.constraints.serialize(self.kernel_constraint),
            bias_initializer=tf.keras.initializers.serialize(self.bias_initializer),
            bias_regularizer=tf.keras.regularizers.serialize(self.bias_regularizer),
            bias_constraint=tf.keras.constraints.serialize(self.bias_constraint),
        )

        return config


from autobahn.twisted.websocket import WebSocketServerProtocol, \
                                                    WebSocketServerFactory

import armatureio
import json

g_armature = None

class MyServerProtocol(WebSocketServerProtocol):

    def onConnect(self, request):
        print("Client connecting: {0}".format(request.peer))

    def onOpen(self):
        print("WebSocket connection open.")

    def onMessage(self, payload, isBinary):
        global g_armature

        g_armature.read_values()
        jointstate = g_armature.get_named_joint_values()

        # Ignore message and just send back joints
        jointmsg = json.dumps(jointstate)

        ## echo back message verbatim
        self.sendMessage(jointmsg, False)

    def onClose(self, wasClean, code, reason):
        print("WebSocket connection closed: {0}".format(reason))

if __name__ == '__main__':
    global g_armature

    import sys

    from twisted.python import log
    from twisted.internet import reactor

    log.startLogging(sys.stdout)

    g_armature = armatureio.ArmatureReader("COM3")
    joints = armatureio.read_old_json_config("arm_config.json")
    g_armature.add_named_joints(joints)

    factory = WebSocketServerFactory("ws://localhost:9000", debug = False)
    factory.protocol = MyServerProtocol

    reactor.listenTCP(9000, factory)
    reactor.run()


#    (C) Roan LaPlante 2013 rlaplant@nmr.mgh.harvard.edu
#
#	 This file is part of cvu, the Connectome Visualization Utility.
#
#    cvu is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

from traits.api import (HasTraits,Any,List,Str,Enum,Dict,Instance,Either,
    Property,Button,on_trait_change)
from traitsui.api import (Item,Handler,View,ButtonEditor,InstanceEditor,
    TextEditor)
from options_struct import OptionsDatabase
from utils import DatasetMetadataElement,CVUError,DisplayMetadata
from viewport import ViewPanel

class ViewportManagerEntry(HasTraits):
    window_name=Str
    window_group=Enum('1','2')
    all_datasets=List

class ViewportManager(Handler):
    #TODO make this a dialog
    from traitsui.api import (Item,View,ObjectColumn,TableEditor,RangeEditor,
        CheckListEditor,OKButton)

    ctl=Any
    selected_col=Any

    def __init__(self,ctl,**kwargs):
        super(Handler,self).__init__(**kwargs)
        self.ctl = ctl

    traits_view=View(
        Item(name='metadata_list',object='object.ctl',
            editor=TableEditor(columns= [
                ObjectColumn(label='Window',name='panel_scratch',
                    editor=TextEditor(enter_set=True, auto_set=False)),
                ObjectColumn(label='Dataset',name='ds_name_scratch',
                    editor=TextEditor(enter_set=True, auto_set=False))],
                edit_view='tabular_view'),
            show_label=False,height=200,width=700,
        ),
        kind='nonmodal',buttons=[OKButton],
        title='If it were up to me it would all be in Swahili',
    )

class DatasetUIMetadata(DatasetMetadataElement):
    controller = Any
    panel,panel_scratch = 2*(Str,)
    ds_name,ds_name_scratch = 2*(Str,)

    display_metadata = Instance(DisplayMetadata)

    rebuild_button = Button
    rebuild_label = Property(Str)
    def _get_rebuild_label(self): return 'Rebuild %s'%self.panel

    delete_button = Button
    delete_label = Property(Str)
    def _get_delete_label(self): return 'Delete %s'%self.ds_name

    def __init__(self,controller,panel,name,display_metadata,**kwargs):
        self.panel = self.panel_scratch = panel
        self.ds_name = self.ds_name_scratch = name
        super(DatasetUIMetadata,self).__init__(controller,**kwargs)
        self.controller = controller
        self.display_metadata = display_metadata

    def _rebuild_button_fired(self):
        if self.panel == 'base_gui':
            self.controller.error_dialog(
                'Rebuilding the base GUI is not allowed'); return
        self.controller.rebuild_panel(self.panel)
    def _delete_button_fired(self):
        if (self.controller.ds_instances[self.ds_name] is
                self.controller.ds_orig):
            self.controller.error_dialog(
                "Removal of the sample data is not allowed"); return
        self.controller.remove_dataset(self.ds_name)

    @on_trait_change('panel_scratch')
    def _rename_panel(self):
        if self.panel == 'base_gui':
            self.controller.warning_dialog(
                'Renaming the base gui window is not allowed'); return
        old_name = self.controller.panel_instances[self.panel].panel_name
        new_name = self.panel_scratch
        self.controller.rename_panel(old_name,new_name)
        self.panel = self.panel_scratch

    @on_trait_change('ds_name_scratch')
    def _rename_ds(self):
        old_name = self.controller.ds_instances[self.ds_name].name
        new_name = self.ds_name_scratch
        self.controller.rename_dataset(old_name,new_name)
        self.ds_name = self.ds_name_scratch

    tabular_view = View(
        Item(name='rebuild_button',
            editor=ButtonEditor(label_value='rebuild_label'),show_label=False),
        Item(name='delete_button',
            editor=ButtonEditor(label_value='delete_label'),show_label=False),
        #Item(name='rename_button',
        #	editor=ButtonEditor(label_value='rename_label')),
        Item(name='display_metadata',style='custom',show_label=False,
            editor=InstanceEditor(),),
    )

class Controller(HasTraits):
    gui=Any						#handle to the gui
    options_db=Instance(OptionsDatabase)

    ds_orig = Any			#convenience reference to the original dataset

    ds_instances = Dict		#map: dataset name -> metadata
    ds_metadatae = Dict		#map: panel name -> metadata
    panel_instances = Dict	#map: dataset name -> DS instance
    panel_metadatae = Dict	#map: panel name -> panel instance
    #metadata_list = List	#all instances of metadata elements
    metadata_list = Property(List)
    def _get_metadata_list(self):
        return self.ds_metadatae.values()
    #def _set_metadata_list(self,val): pass

    viewport_manager=Instance(ViewportManager)

    #HASHING STRATEGY
    #
    # 4 hash tables
    # 	dataset name -> associated metadata
    #	panel name -> associated metadata
    #	dataset name -> Dataset Instance
    #	panel name -> Panel Instance

    def __init__(self,gui,sample_data,sample_metadata):
        super(Controller,self).__init__()
        self.gui=gui

        self.ds_orig = sample_data

        ds_meta = DatasetUIMetadata(self,'base_gui',sample_data.name,
            sample_metadata)
        self.ds_instances = {sample_data.name : sample_data}
        self.panel_instances = {'base_gui' : self.gui}
        self.ds_metadatae = {sample_data.name : ds_meta}
        self.panel_metadatae = {'base_gui' : ds_meta}

        self.options_db=OptionsDatabase(sample_data)
        self.viewport_manager=ViewportManager(self)

    #listen to the GUI for changes in the current dataset and set the control
    #accordingly for the unstable windows
    @on_trait_change('gui:options_window:current_dataset')
    def options_window_ctl_listener(self):
        self.gui.options_window.ctl=self.gui.options_window.current_dataset.opts
    @on_trait_change('gui:configure_scalars_window:current_dataset')
    def configure_scalars_window_ctl_listener(self):
        csw=self.gui.configure_scalars_window
        csw.ctl=csw.current_dataset.scalar_display_settings

    ##########################################################
    #viewport allocation
    def add_dataset(self,ds,display_metadata,panel=None,group=None):
        '''Given a dataset, add it to the controller.  If panel and group
           are specified, add it to that panel, otherwise any panel will do'''
        if ds.name in self.ds_instances:
            raise CVUError('A dataset with this name already exists')

        if panel is None and group is None:
            panel_ref = self._create_new_panel(ds.name)
            panel = panel_ref.panel_name
            group = 2 if panel_ref.is_full(group=1) else 1
        elif group is not None:
            raise CVUError('Cannot specify group without panel')
        elif panel is not None:
            panel_ref = self.get_named_panel(panel)
            if panel_ref.is_full():
                raise CVUError('That panel is full')
            group = 2 if panel_ref.is_full(group=1) else 1
        else:
            panel_ref = self.get_named_panel(panel)

        panel_ref.populate(ds,group=group)	#group can be none, doesnt matter

        ds_meta = DatasetUIMetadata(self,panel,ds.name,display_metadata)
        self.ds_instances.update({ds.name:ds})
        self.ds_metadatae.update({ds.name:ds_meta})
        self.panel_instances.update({panel_ref.panel_name:panel_ref})
        self.panel_metadatae.update({panel_ref.panel_name:ds_meta})

        self.show_panel(panel_ref)

    def show_panel(self,panel):
        panel.edit_traits(panel.produce_view())

    def rebuild_panel(self,panel_name):
        '''we havent actually destroyed the editor here.
            have to destroy the panel and create a new one.
            otherwise the panel still refers to the wrong editor'''

        panel=self.panel_instances[panel_name]

        #have the panel dispose of itself if necessary
        panel.conditionally_dispose()

        #find the associated dataset and reset its DataViews
        ds=self._get_dataset_from_panel(panel)
        ds.reset_dataviews()

        #actually ask the panel to drop the old references to the editor
        panel.populate(ds,force=True)

        #then show the panel
        self.show_panel(panel)

    def rename_panel(self,old_name,new_name):
        try:
            panel = self.panel_instances[old_name]
            ds_meta = self.panel_metadatae[old_name]
        except KeyError:
            raise CVUError('No such panel')
        del self.panel_instances[old_name]
        del self.panel_metadatae[old_name]
        self.panel_instances.update({new_name:panel})
        self.panel_metadatae.update({new_name:ds_meta})
        panel.panel_name = new_name

    def rename_dataset(self,old_name,new_name):
        try:
            ds = self.ds_instances[old_name]
            ds_meta = self.ds_metadatae[old_name]
        except KeyError:
            raise CVUError('No such dataset')
        del self.ds_instances[old_name]
        del self.ds_metadatae[old_name]
        self.ds_instances.update({new_name:ds})
        self.ds_metadatae.update({new_name:ds_meta})
        ds.name = new_name

    def find_dataset_views(self,ds):
        '''Given a dataset, return the three viewports that refer to it'''
        ds_meta = self.ds_metadatae[ds.name]
        panel=self.panel_instances[ds_meta.panel]

        from viewport import DatasetViewportInterface
        #if panel is base gui, return it
        if isinstance(panel,DatasetViewportInterface): layout_obj=panel
        #otherwise, return its group
        else: layout_obj = panel.group_1
        return layout_obj

    def update_display_metadata(self,ds_name,subject_name=None,parc_name=None,
            adj_filename=None):
        ds_meta=self.ds_metadatae[ds_name]
        if subject_name is not None:
            ds_meta.display_metadata.subject_name=subject_name
        if parc_name is not None:
            ds_meta.display_metadata.parc_name=parc_name
        if adj_filename is not None:
            ds_meta.display_metadata.adj_filename=adj_filename

    def remove_dataset(self,ds_name):
        #remove the metadata elements associated with this dataset
        ds_meta = self.ds_metadatae[ds_name]
        panel_name = ds_meta.panel

        #dispose of the window if necessary
        panel = self.panel_instances[panel_name]
        panel.conditionally_dispose()

        ds = self.ds_instances[ds_name]
        self.gui.reset_controls(ds)

        try:
            del self.ds_instances[ds_name]
            del self.ds_metadatae[ds_name]
            del self.panel_instances[panel_name]
            del self.panel_metadatae[panel_name]
        except KeyError as e:
            raise CVUError('Inconsistent metadata')

    #internal methods for panel manipulation
    def _get_named_panel(self,panel_name):
        try:
            return self.panel_instances[panel_name]
        except KeyError as e:
            raise CVUError('No such panel')

    def _get_dataset_from_panel(self,panel):
        ds_meta = self.panel_metadatae[panel.panel_name]
        return self._get_named_dataset(ds_meta.ds_name)

    def _get_named_dataset(self,ds_name):
        try:
            return self.ds_instances[ds_name]
        except KeyError as e:
            raise CVUError('No such dataset')

    #panel creation
    def __ctr_generate():
        i=0
        while True:
            i+=1
            yield i
    __ctr_generator = Any(__ctr_generate())
    def _panel_counter(self):
        return self.__ctr_generator.next()

    def _create_new_panel(self,ds_name):
        panel_name='Extra View %i'%self._panel_counter()
        #panel = ViewPanel(panel_name=panel_name)
        #self.panel_instances[panel_name]=panel
        panel = ViewPanel(panel_name=ds_name)
        self.panel_instances[ds_name]=panel
        return panel

    def _destroy_panel(self,name):
        del self.panel_instances[name]

    #error messages
    def error_dialog(self,message):
        return self.gui.error_dialog(message)
    def warning_dialog(self,message):
        return self.gui.warning_dialog(message)
    def verbose_msg(self,message):
        return self.gui.verbose_msg(message)

{'Item': 'traitsui.api.Item', 'View': 'traitsui.api.View', 'ObjectColumn': 'traitsui.api.ObjectColumn', 'TableEditor': 'traitsui.api.TableEditor', 'RangeEditor': 'traitsui.api.RangeEditor', 'CheckListEditor': 'traitsui.api.CheckListEditor', 'OKButton': 'traitsui.api.OKButton'}


import numpy as np
import pyopencl as cl
import pyopencl.array as cl_array

from PySoap2_gpu.Exceptions import check_for_valid_context

class BroadcastError(Exception):
    pass

class Broadcast:
    device_context = None
    device_queue = None

    device_program = None

    initialized = False

    def __init__(self, context, queue):
        # If this class is initialized, it means that the programs is already on the device
        if Broadcast.initialized:
            return
        Broadcast.device_context = context
        Broadcast.device_queue = queue

        Broadcast.device_program = cl.Program(context, broadcast_across_axis_c_code).build()

        Broadcast.initialized = True

    @staticmethod
    def broadcast_across_0_axis(operation, x_device, y_device):
        """ It is assumed that the operation to be performed is

            x_device 'operation' y_device

            If operation = '-', then this will return x_device - y_device

            Parameters
            ----------
            x_device : (N, ...) cl_array.Array (or (...))
            y_device : (...) cl_array.Array (or (N, ...))
        """
        check_for_valid_context(Broadcast.device_context, x_device, y_device)

        error_msg = f'Broadcasting two arrays must the last dimension equal. ' \
                    f'In particular, x.shape={x_device.shape} not compatible y.shape={y_device.shape}.'
        try:
            return Broadcast._broadcast_across_0_axis(operation, x_device, y_device, error_msg)
        except BroadcastError:
            """ Now assumed that

                x_device : (...) cl_array.Array
                y_device : (N, ...) cl_array.Array
            """
            if operation == "-":  # These are special operation that is sensitive on the position
                return Broadcast._broadcast_across_0_axis('+', -y_device, x_device, error_msg)
            elif operation == '/':
                # Special divide
                return Broadcast._broadcast_across_0_axis('_/', y_device, x_device, error_msg)
            else:
                return Broadcast._broadcast_across_0_axis(operation, y_device, x_device, error_msg)

    @staticmethod
    def _broadcast_across_0_axis(operation, x_device, y_device, error_msg):
        """ Performs broadcasting on the gpu

            Parameters
            ----------
            x_device : (N, ...) cl_array.Array
            y_device : (...) cl_array.Array
            operation : str
                The operation to be performed. Only +,-,*,/ are supported

            y is to be broadcast against x
        """
        N, *input_shape = x_device.shape

        if tuple(input_shape) != y_device.shape:
            raise BroadcastError(error_msg)

        input_shape = tuple(input_shape)
        input_length = np.int32(np.prod(input_shape))
        N = np.int32(N)

        out = cl_array.empty_like(x_device)

        broadcast_program = Broadcast._get_broadcast_program(operation)
        event = broadcast_program(Broadcast.device_queue, (N, input_length), None,
                                  x_device.data, y_device.data, input_length, N, out.data)
        event.wait()
        return out

    @staticmethod
    def _get_broadcast_program(operation):
        if operation == "+":
            return Broadcast.device_program.broadcast_add_across_0_axis
        elif operation == "-":
            return Broadcast.device_program.broadcast_sub_across_0_axis
        elif operation == "*":
            return Broadcast.device_program.broadcast_mul_across_0_axis
        elif operation == "/":
            return Broadcast.device_program.broadcast_div_across_0_axis
        elif operation == "_/":
            return Broadcast.device_program._broadcast_div_across_0_axis
        else:
            raise ValueError(f"{operation} is not a valid operation. Choose from +,-,*,/.")

broadcast_across_axis_c_code = """
__kernel void broadcast_add_across_0_axis(__global const double *x, __global const double *y, const int input_length,
                                          const int N, __global double *out)
{
    int i = get_global_id(0);
    int j = get_global_id(1);

    out[j + i*input_length] = x[j + i*input_length] + y[j];
}

__kernel void broadcast_sub_across_0_axis(__global const double *x, __global const double *y, const int input_length,
                                          const int N, __global double *out)
{
    int i = get_global_id(0);
    int j = get_global_id(1);

    out[j + i*input_length] = x[j + i*input_length] - y[j];
}

__kernel void broadcast_mul_across_0_axis(__global const double *x, __global const double *y, const int input_length,
                                          const int N, __global double *out)
{
    int i = get_global_id(0);
    int j = get_global_id(1);

    out[j + i*input_length] = x[j + i*input_length] * y[j];
}

__kernel void broadcast_div_across_0_axis(__global const double *x, __global const double *y, const int input_length,
                                          const int N, __global double *out)
{
    int i = get_global_id(0);
    int j = get_global_id(1);

    out[j + i*input_length] = x[j + i*input_length] /  y[j];
}

__kernel void _broadcast_div_across_0_axis(__global const double *x, __global const double *y, const int input_length,
                                           const int N, __global double *out)
{
    int i = get_global_id(0);
    int j = get_global_id(1);

    out[j + i*input_length] =  y[j] / x[j + i*input_length];
}
"""


import math
import random

import cvzone
import cv2
import numpy as np
from cvzone.HandTrackingModule import HandDetector

import base64
from memory_pic import *

def get_pic(pic_code, pic_name):
    image = open(pic_name, 'wb')
    image.write(base64.b64decode(pic_code))
    image.close()

get_pic(donut_png, 'donut.png')

cap = cv2.VideoCapture(0)  # 0代表自己电脑的摄像头
cap.set(3, 1280)  # 宽
cap.set(4, 720)  # 高

# 手部检测方法，置信度为0.8，最多检测一只手
detector = HandDetector(detectionCon=0.8, maxHands=1)

class SnakeGameClass:
    def __init__(self, pathFood):  # 构造方法
        self.points = []  # 蛇身上所有的点
        self.lengths = []  # 每个点之间的长度
        self.currentLength = 0  # 蛇的总长
        self.allowedLength = 150  # 蛇允许的总长度
        self.previousHead = 0, 0  # 第二个头结点

        self.imgFood = cv2.imread(pathFood, cv2.IMREAD_UNCHANGED)
        self.hFood, self.wFood, _ = self.imgFood.shape
        self.foodPoint = 0, 0
        self.randomFoodLocation()

        self.score = 0
        self.gameOver = False

    def randomFoodLocation(self):
        self.foodPoint = random.randint(100, 1000), random.randint(100, 600)

    def update(self, imgMain, currentHead):  # 实例方法

        if self.gameOver:
            cvzone.putTextRect(imgMain, "Game Over", [300, 400],
                               scale=7, thickness=5, offset=20)
            cvzone.putTextRect(imgMain, f'Your Score:{self.score}', [300, 550],
                               scale=7, thickness=5, offset=20)
        else:
            px, py = self.previousHead
            cx, cy = currentHead

            self.points.append([cx, cy])  # 添加蛇的点列表节点
            distance = math.hypot(cx - px, cy - py)  # 两点之间的距离
            self.lengths.append(distance)  # 添加蛇的距离列表内容
            self.currentLength += distance
            self.previousHead = cx, cy

            # Length Reduction
            if self.currentLength > self.allowedLength:
                for i, length in enumerate(self.lengths):
                    self.currentLength -= length
                    self.lengths.pop(i)
                    self.points.pop(i)
                    if self.currentLength < self.allowedLength:
                        break

            # Check if snake ate the food
            rx, ry = self.foodPoint
            if rx - self.wFood // 2 < cx < rx + self.wFood // 2 and \
                    ry - self.hFood // 2 < cy < ry + self.hFood // 2:
                self.randomFoodLocation()
                self.allowedLength += 50
                self.score += 1
                # print(self.score)

            # Draw Snake
            if self.points:
                for i, point in enumerate(self.points):
                    if i != 0:
                        cv2.line(imgMain, self.points[i - 1], self.points[i], (0, 0, 255), 20)
                # 对列表最后一个点也就是蛇头画为紫色点
                cv2.circle(imgMain, self.points[-1], 20, (200, 0, 200), cv2.FILLED)

            # Draw Food

            imgMain = cvzone.overlayPNG(imgMain, self.imgFood,
                                        (rx - self.wFood // 2, ry - self.hFood // 2))

            cvzone.putTextRect(imgMain, f'Your Score:{self.score}', [50, 80],
                               scale=3, thickness=5, offset=10)

            # Check for Collision
            pts = np.array(self.points[:-2], np.int32)
            pts = pts.reshape((-1, 1, 2))  # 重塑为一个行数未知但只有一列且每个元素有2个子元素的矩阵
            # 第三个参数是False，我们得到的是不闭合的线
            cv2.polylines(imgMain, [pts], False, (0, 200, 0), 3)
            # 参数True表示输出该像素点到轮廓最近距离
            minDist = cv2.pointPolygonTest(pts, (cx, cy), True)
            # print(minDist)

            if -0.05 <= minDist <= 0.05:
                # print("Hit")
                self.gameOver = True
                self.points = []  # 蛇身上所有的点
                self.lengths = []  # 每个点之间的长度
                self.currentLength = 0  # 蛇的总
                self.allowedLength = 150  # 蛇允许的总长度
                self.previousHead = 0, 0  # 第二个头结点
                self.randomFoodLocation()

        return imgMain

game = SnakeGameClass("donut.png")

# 处理每一帧图像
while True:  # 不断迭代更新
    success, img = cap.read()
    # 翻转图像，使自身和摄像头中的自己呈镜像关系
    img = cv2.flip(img, 1)  # 将手水平翻转
    hands, img = detector.findHands(img, flipType=False)  # 左手是左手，右手是右手，映射正确

    if hands:
        lmList = hands[0]['lmList']  # hands是由N个字典组成的列表
        pointIndex = lmList[8][0:2]  # 只要食指指尖的x和y坐标
        img = game.update(img, pointIndex)

    cv2.imshow("Image", img)
    key = cv2.waitKey(1)

    if key == ord('r'):  # 重置游戏
        game.gameOver = False
        game.score = 0

    if key == 27:  # 按下 Esc退出 (27是按键ESC对应的ASCII值)
        break

    if cv2.getWindowProperty("Image", cv2.WND_PROP_AUTOSIZE) < 1:  # 判断是否点击窗口关闭按键
        break

cap.release()
cv2.destroyAllWindows()


import multiprocessing

def download_data(q):
    """下载数据"""
    data = [45, 56, 2, 3]

    #向队列中写入数据
    for temp in data:
        q.put(temp)
    print("数据下载完成！")

def recv_data(q):
    """数据处理"""
    recv_list = list()  #创建空列表，用来存数据
    #从队列中获取数据
    while True:
        dataa = q.get()
        recv_list.append(dataa)
        #判断队列中是否还有数据，如果没有则终止循环
        if q.empty():
            break

    print(recv_list)

def main():

    #创建一个队列
    q = multiprocessing.Queue()

    #实例化对象
    t1 = multiprocessing.Process(target=download_data,args=(q,))
    t2 = multiprocessing.Process(target=recv_data,args=(q,))
    #创建两个进程
    t1.start()
    t2.start()

if __name__ == "__main__":
    main()

队列进程配合使用，下载列表.py

队列进程配合使用，下载列表.py


from django.contrib import admin
from django.urls import path

from .views import (
    edit_car, get_all_cars, get_all_cars_by_location, get_all_cars_distances_by_location,
    create_good, get_goods, certain_good, update_good, delete_good, filter_goods
)

urlpatterns = [
    path('car/edit/<int:id>/', edit_car, name='edit_car'),
    path('car/all/', get_all_cars, name='get_all_cars'),
    path('car/all/filter/', filter_goods),
    path('car/location/<int:location_id>/', get_all_cars_by_location, name='get_all_cars_by_location'),
    path('car/distance/<int:location_id>/', get_all_cars_distances_by_location, name='get_all_cars_distances_by_location'),

    path('good/create/', create_good, name='create_good'),
    path('good/all/', get_goods, name='get_goods'),
    path('good/<int:id>/', certain_good, name='certain_good'),
    path('good/update/<int:id>/', update_good, name='update_good'),
    path('good/delete/<int:id>/', delete_good, name='delete_good'),

    path('admin/', admin.site.urls),
]


import torch
from skimage.color import rgb2hsv

from experts.basic_expert import BasicExpert

class HSVExpert(BasicExpert):
    def __init__(self, full_expert=True):
        self.n_maps = 3
        self.domain_name = "hsv"
        self.str_id = ""
        self.identifier = self.domain_name

    def apply_expert_batch(self, batch_rgb_frames):
        batch_rgb_frames = batch_rgb_frames
        outp_maps = rgb2hsv(batch_rgb_frames)
        hsv_maps = outp_maps.astype('float32').transpose(0, 3, 1, 2) / 255.
        return hsv_maps


from typing import Optional, Union

import torch
from mmengine.analysis.print_helper import (
    FlopAnalyzer,
    ActivationAnalyzer,
    parameter_count,
    complexity_stats_str,
    complexity_stats_table,
    _format_size,
)

def get_model_complexity_info(
    model: torch.nn.Module,
    input_shape: tuple,
    inputs: Optional[torch.Tensor] = None,
    show_table: bool = True,
    show_arch: bool = True,
    device: Optional[Union[torch.device, str]] = None,
):
    """Interface to get the complexity of a model.

    Args:
        model (nn.Module): The model to analyze.
        input_shape (tuple): The input shape of the model.
        inputs (torch.Tensor, optional): The input tensor of the model.
            If not given the input tensor will be generated automatically
            with the given input_shape.
        show_table (bool): Whether to show the complexity table.
            Defaults to True.
        show_arch (bool): Whether to show the complexity arch.
            Defaults to True.
        device (torch.device, str, optional): Setting the device to be
            used for inference

    Returns:
        dict: The complexity information of the model.
    """
    if inputs is None:
        inputs = (torch.randn(1, *input_shape, device=(device)),)
    else:
        inputs = inputs.to(device=device)

    flop_handler = FlopAnalyzer(model, inputs)
    activation_handler = ActivationAnalyzer(model, inputs)

    flops = flop_handler.total()
    activations = activation_handler.total()
    params = parameter_count(model)['']

    flops_str = _format_size(flops)
    activations_str = _format_size(activations)
    params_str = _format_size(params)

    if show_table:
        complexity_table = complexity_stats_table(
            flops=flop_handler,
            activations=activation_handler,
            show_param_shapes=True,
        )
        complexity_table = '\n' + complexity_table
    else:
        complexity_table = ''

    if show_arch:
        complexity_arch = complexity_stats_str(
            flops=flop_handler,
            activations=activation_handler,
        )
        complexity_arch = '\n' + complexity_arch
    else:
        complexity_arch = ''

    return {
        'flops': flops,
        'flops_str': flops_str,
        'activations': activations,
        'activations_str': activations_str,
        'params': params,
        'params_str': params_str,
        'out_table': complexity_table,
        'out_arch': complexity_arch,
    }


"""adding cost to Pan

Revision ID: 561e1d3d0a47
Revises: 3718e72dbfe7
Create Date: 2018-06-04 11:01:37.059569

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '561e1d3d0a47'
down_revision = '3718e72dbfe7'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('pan', sa.Column('Cost', sa.Numeric(), nullable=True))
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_column('pan', 'Cost')
    # ### end Alembic commands ###


from mako import runtime, filters, cache
UNDEFINED = runtime.UNDEFINED
__M_dict_builtin = dict
__M_locals_builtin = locals
_magic_number = 5
_modified_time = 1248197032.671
_template_filename='C:\\fox\\rentfox\\rentfox\\templates/base/index.html'
_template_uri='/base/index.html'
_template_cache=cache.Cache(__name__, _modified_time)
_source_encoding='utf-8'
from webhelpers.html import escape
_exports = ['flash', 'header', 'head', 'footer', 'title']

def render_body(context,**pageargs):
    context.caller_stack._push_frame()
    try:
        __M_locals = __M_dict_builtin(pageargs=pageargs)
        self = context.get('self', UNDEFINED)
        next = context.get('next', UNDEFINED)
        __M_writer = context.writer()
        # SOURCE LINE 2
        __M_writer(u'\n<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"\n"http://www.w3.org/TR/html4/strict.dtd">\n\n\n    <title>')
        # SOURCE LINE 7
        __M_writer(escape(self.title()))
        __M_writer(u'</title>\n    ')
        # SOURCE LINE 8
        __M_writer(escape(self.head()))
        __M_writer(u'\n\n\n    ')
        # SOURCE LINE 11
        __M_writer(escape(self.header()))
        __M_writer(u'\n    ')
        # SOURCE LINE 12
        __M_writer(escape(next.heading()))
        __M_writer(u'\n    ')
        # SOURCE LINE 13
        __M_writer(escape(self.flash()))
        __M_writer(u'\n    ')
        # SOURCE LINE 14
        __M_writer(escape(next.body()))
        __M_writer(u'\n    ')
        # SOURCE LINE 15
        __M_writer(escape(self.footer()))
        __M_writer(u'\n\n\n\n')
        # SOURCE LINE 19
        __M_writer(u'\n')
        # SOURCE LINE 22
        __M_writer(u'\n')
        # SOURCE LINE 23
        __M_writer(u'\n')
        # SOURCE LINE 24
        __M_writer(u'\n')
        # SOURCE LINE 33
        __M_writer(u'\n\n')
        return ''
    finally:
        context.caller_stack._pop_frame()

def render_flash(context):
    context.caller_stack._push_frame()
    try:
        session = context.get('session', UNDEFINED)
        __M_writer = context.writer()
        # SOURCE LINE 25
        __M_writer(u'\n')
        # SOURCE LINE 26
        if session.has_key('flash'):
            # SOURCE LINE 27
            __M_writer(u'

')
            __M_writer(escape(session.get('flash')))
            __M_writer(u'

\n    ')
            # SOURCE LINE 28

            del session['flash']
            session.save()

            # SOURCE LINE 31
            __M_writer(u'\n')
        return ''
    finally:
        context.caller_stack._pop_frame()

def render_header(context):
    context.caller_stack._push_frame()
    try:
        h = context.get('h', UNDEFINED)
        __M_writer = context.writer()
        # SOURCE LINE 23
        __M_writer(u'
Home
')
        return ''
    finally:
        context.caller_stack._pop_frame()

def render_head(context):
    context.caller_stack._push_frame()
    try:
        h = context.get('h', UNDEFINED)
        __M_writer = context.writer()
        # SOURCE LINE 20
        __M_writer(u'\n    ')
        # SOURCE LINE 21
        __M_writer(escape(h.stylesheet_link(h.url_for('/css/global.css'))))
        __M_writer(u'\n')
        return ''
    finally:
        context.caller_stack._pop_frame()

def render_footer(context):
    context.caller_stack._push_frame()
    try:
        __M_writer = context.writer()
        # SOURCE LINE 24
        __M_writer(u'

')
        return ''
    finally:
        context.caller_stack._pop_frame()

def render_title(context):
    context.caller_stack._push_frame()
    try:
        __M_writer = context.writer()
        # SOURCE LINE 19
        __M_writer(u'Rentfox')
        return ''
    finally:
        context.caller_stack._pop_frame()


from django.urls import path, include
from . import views

urlpatterns = [
    path('signup/', views.SignUp, name="Registraton"),
    path('login/', views.LogIn, name="LogIn"),
    path('logout/', views.logout_view, name="LogOut"),
    path('ChangePassword/', views.ChangePassword),
    path('profile/<str:pk>', views.get_user, name="Get Profile"),
    path('updateprofile/', views.updateProfile, name="Update Profile"),

    # chat urls
    path('sendd/<str:pk>', views.sendMessages),
    path('rec_msg/<str:uid>/<str:pk>', views.receivedMessages, name = "rec_msg"),
    path('Doctor/<str:user_id>', views.Doctor.as_view(), name = "Doctor"),
    path('detail/<str:uid>/<str:pk>', views.chat_history, name="detail"),
    path('seen/<str:uid>/<str:pk>', views.markMessagesAsSeen),

    # searchURL
    path('search',views.search),

    # get doctors for specialization
    path('doctors/', views.get_allDoctors),

    # track and update the location
    # user side
    path('ambulance/',views.requestAmbulance),
    path('updateUserLoc/', views.update_user_location),
    path('checkConnection/', views.checkConnection),
    path('getConnection/<str:ambid>', views.getConnection),
    # hospital side
    path('hospitalLogin/', views.HosLogin),
    path('HandleRequest/',views.HandleRequest),
    # ambulance
    path('ambLogin/', views.AmbLogin, name="ambulance login"),
    path('updateAmbulanceLoc/', views.update_ambulance_location),

    path('deleteConnection/',views.deleteConnection),

    #First Aid
    path('firstaid/',views.get_firstAid),
    path('firstaid/<str:pk>',views.get_oneFirstAid),
    path('firstaidd/<str:pk>',views.updateFirstAid),

    path('getdata/', views.getdata),
]


# ------------------------------------------------
# augment_package for CDeep3M -- NCMIR/NBCR, UCSD
# ------------------------------------------------
import os
import numpy as np
import h5py
from augment_data import augment_img

def augment_package(original, outsubdir, fmnumber, speed):
    allowed_speed = [1, 2, 4, 10]
    if speed not in allowed_speed:
        speed = allowed_speed[abs(np.array(allowed_speed) - speed).argmin()]

    if speed == 10:
        augment_choices = {
            1: [1],
            3: [1],
            5: [1]
        }
    elif speed == 1:
        augment_choices = {
            1: [1, 2, 3, 4, 5, 6, 7, 8],
            3: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
            5: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
        }
    elif speed == 2:
        augment_choices = {
            1: [1, 6, 11, 15],
            3: [1, 2, 3, 4, 13, 14, 15, 16],
            5: [5, 6, 7, 8, 9, 10, 11, 12]
        }
    elif speed == 4:
        augment_choices = {
            1: [2, 3, 6, 7],
            3: [7, 8, 10, 12],
            5: [1, 6, 11, 15]
        }

    do_var = augment_choices.get(fmnumber)

    original_flip = np.flip(original, 0)
    d_details = '/data'

    for i in do_var:
        if i < 9:
            stack_out = augment_img(original, i - 1)
        else:
            stack_out = augment_img(original_flip, i - 9)

        print('Create Hd5 file Variation ', str(i))

        stack_out = stack_out.transpose([1, 2, 0])

        filename = os.path.join(outsubdir, 'image_stacks_v%d.h5' % (i))
        print('Saving: ', filename)
        hdf5_file = h5py.File(filename, mode='w')
        hdf5_file.create_dataset(d_details, data=stack_out)
        hdf5_file.close()


import gc
from os import remove
from unittest import mock

import numpy as np
import pytest

from hyperspy._signals.signal1d import Signal1D
from hyperspy.components1d import Expression, Gaussian, GaussianHF
from hyperspy.io import load

def clean_model_dictionary(d):
    for c in d['components']:
        for p in c['parameters']:
            del p['self']
    return d

class TestModelStoring:

    def setup_method(self, method):
        s = Signal1D(range(100))
        m = s.create_model()
        m.append(Gaussian())
        m.fit()
        self.m = m

    def test_models_getattr(self):
        m = self.m
        s = m.signal
        m.store()
        assert s.models.a is s.models['a']

    def test_models_stub_methods(self):
        m = self.m
        s = m.signal
        m.store()
        s.models.pop = mock.MagicMock()
        s.models.remove = mock.MagicMock()
        s.models.restore = mock.MagicMock()
        s.models.a.restore()
        s.models.a.remove()
        s.models.a.pop()

        assert s.models.pop.call_count == 1
        assert s.models.remove.call_count == 1
        assert s.models.restore.call_count == 1

        assert s.models.pop.call_args[0] == ('a',)
        assert s.models.remove.call_args[0] == ('a',)
        assert s.models.restore.call_args[0] == ('a',)

    def test_models_pop(self):
        m = self.m
        s = m.signal
        m.store()
        s.models.remove = mock.MagicMock()
        s.models.restore = mock.MagicMock()
        s.models.pop('a')
        assert s.models.remove.call_count == 1
        assert s.models.restore.call_count == 1
        assert s.models.remove.call_args[0] == ('a',)
        assert s.models.restore.call_args[0] == ('a',)

    def test_model_store(self):
        m = self.m
        m.store()
        d = m.as_dictionary(True)
        np.testing.assert_equal(
            d,
            m.signal.models._models.a._dict.as_dictionary())

    def test_actually_stored(self):
        m = self.m
        m.store()
        m[0].A.map['values'][0] += 13.33
        m1 = m.signal.models.a.restore()
        assert m[0].A.map['values'] != m1[0].A.map['values']

    def test_models_restore_remove(self):
        m = self.m
        s = m.signal
        m.store('a')
        m1 = s.models.restore('a')
        m2 = s.models.a.restore()
        d_o = clean_model_dictionary(m.as_dictionary())
        d_1 = clean_model_dictionary(m1.as_dictionary())
        d_2 = clean_model_dictionary(m2.as_dictionary())
        np.testing.assert_equal(d_o, d_1)
        np.testing.assert_equal(d_o, d_2)
        assert 1 == len(s.models)
        s.models.a.remove()
        assert 0 == len(s.models)

    def test_store_name_error1(self):
        s = self.m.signal
        with pytest.raises(KeyError):
            s.models.restore('a')

    def test_store_name_error2(self):
        s = self.m.signal
        with pytest.raises(KeyError):
            s.models.restore(3)

    def test_store_name_error3(self):
        s = self.m.signal
        with pytest.raises(KeyError):
            s.models.restore('_a')

    def test_store_name_error4(self):
        s = self.m.signal
        with pytest.raises(KeyError):
            s.models.restore('a._dict')

    def test_store_name_error5(self):
        s = self.m.signal
        self.m.store('b')
        with pytest.raises(KeyError):
            s.models.restore('a')

@pytest.mark.parametrize('save_std', [True, False])
@pytest.mark.parametrize('only_free', [True, False])
@pytest.mark.parametrize('only_active', [True, False])
def test_model_export(tmp_path, save_std, only_free, only_active):
    s = Signal1D(range(100))
    m = s.create_model()
    m.append(Gaussian())
    m.fit()
    m.export_results(tmp_path, save_std=save_std, only_free=only_free,
                     only_active=only_active)

class TestModelSaving:

    def setup_method(self, method):
        s = Signal1D(range(100))
        m = s.create_model()
        m.append(Gaussian(A=13))
        m[-1].name = 'something'
        m.append(GaussianHF(module="numpy"))
        m[-1].height.value = 3
        m.append(Expression(name="Line", expression="a * x + b", a=1, c=0, rename_pars={"b": "c"}))
        self.m = m

    def test_save_and_load_model(self):
        m = self.m
        m.save('tmp.hdf5', overwrite=True)
        s = load('tmp.hdf5')
        assert hasattr(s.models, 'a')
        mr = s.models.restore('a')
        assert mr.components.something.A.value == 13
        assert mr.components.GaussianHF.height.value == 3
        assert mr.components.Line.a.value == 1
        assert mr.components.Line.c.value == 0
        assert mr.components.Line.function(10) == 10

    def teardown_method(self, method):
        gc.collect()        # Make sure any memmaps are closed first!
        remove('tmp.hdf5')

class TestEELSModelSaving:

    def setup_method(self, method):
        s = Signal1D(range(100))
        s.axes_manager[0].offset = 280
        s.set_signal_type("EELS")
        s.add_elements(["C"])
        s.set_microscope_parameters(100, 10, 10)
        m = s.create_model(auto_background=False)
        m.components.C_K.fine_structure_smoothing = 0.5
        m.components.C_K.fine_structure_width = 50
        m.components.C_K.fine_structure_active = True
        self.m = m

    def test_save_and_load_model(self):
        m = self.m
        m.save('tmp.hdf5', overwrite=True)
        l = load('tmp.hdf5')
        assert hasattr(l.models, 'a')
        n = l.models.restore('a')
        assert n[0].fine_structure_width == 50

    def teardown_method(self, method):
        gc.collect()        # Make sure any memmaps are closed first!
        remove('tmp.hdf5')


#!/usr/bin/env python3

import pdb
import sys
import tqdm
import numpy as np
import pandas as pd
import seaborn as sb
import matplotlib.pyplot as plt
import sklearn
from statsmodels.stats.contingency_tables import mcnemar
import os
from pandas import Series, DataFrame

file1 = pd.read_csv(sys.argv[1], delimiter=',')
file2 = pd.read_csv(sys.argv[2], delimiter=',')

corrs1 = file1['correct']
corrs2 = file2['correct']

golds = open(sys.argv[3], 'r').readlines()
training_labels = open('rares.txt', 'r').readlines()
rares = [x.strip().split() for x in training_labels]
rares = [x[1] for x in rares if int(x[0]) < 21]

bothright = 0
YesNo = 0
NoYes = 0
bothwrong = 0

acc1 = 0
acc2 = 0
total = 0

rare_bothright = 0
rare_YesNo = 0
rare_NoYes = 0
rare_bothwrong = 0

rare_acc1 = 0
rare_acc2 = 0
rare_total = 0

statistic = lambda x,y: (x - y)**2 / (x + y)

for c1, c2, true in zip(corrs1, corrs2, golds):
    gold_label = true.split('\t')[0]
    if gold_label not in ['359', '360']:
        if c1 == True and c2 == True:
            bothright += 1
            acc1 += 1
            acc2 += 1
            if gold_label in rares:
                rare_bothright += 1
                rare_acc1 += 1
                rare_acc2 += 1
        elif c1 == True and c2 == False:
            YesNo += 1
            acc1 += 1
            if gold_label in rares:
                rare_YesNo += 1
                rare_acc1 += 1
        elif c1 == False and c2 == True:
            NoYes += 1
            acc2 += 1
            if gold_label in rares:
                rare_NoYes += 1
                rare_acc2 += 1
        elif c1 == False and c2 == False:
            bothwrong += 1
            if gold_label in rares:
                rare_bothwrong += 1
        else:
            print("Error")
            pdb.set_trace()
        total += 1
        if gold_label in rares:
            rare_total += 1

print("sys1 acc:", acc1 / total)
print("sys2 acc:", acc2 / total)

print("manual:", statistic(YesNo, NoYes))
print("statsmodels", mcnemar(np.array([[bothright, YesNo], [NoYes, bothwrong]])))
print("statsmodels exact false", mcnemar(np.array([[bothright, YesNo], [NoYes, bothwrong]]), exact=False))
print("statsmodels correction false", mcnemar(np.array([[bothright, YesNo], [NoYes, bothwrong]]), correction=False))
print("statsmodels exact false correction false", mcnemar(np.array([[bothright, YesNo], [NoYes, bothwrong]]), exact=False, correction=False))

print('\nrare labels!!!')
print('\nthere are {} total labels'.format(total))
print("sys1 acc:", rare_acc1 / rare_total)
print("sys2 acc:", rare_acc2 / rare_total)

print("manual:", statistic(rare_YesNo, rare_NoYes))
print("statsmodels", mcnemar(np.array([[rare_bothright, rare_YesNo], [rare_NoYes, rare_bothwrong]])))
print("statsmodels exact false", mcnemar(np.array([[rare_bothright, rare_YesNo], [rare_NoYes, rare_bothwrong]]), exact=False))
print("statsmodels correction false", mcnemar(np.array([[rare_bothright, rare_YesNo], [rare_NoYes, rare_bothwrong]]), correction=False))
print("statsmodels exact false correction false", mcnemar(np.array([[rare_bothright, rare_YesNo], [rare_NoYes, rare_bothwrong]]), exact=False, correction=False))


import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

data = np.genfromtxt("./timedel_sorted.dat", delimiter='    ').T
#  print(data)

date = data[0]
magA = data[1] + 1.8
sigmaMagA = data[2]
magB = data[3]
sigmaMagB = data[4]

k = 0
plt.figure(num=k, figsize=(10,7))
plt.errorbar(date, magA, yerr=sigmaMagA, label="Image A (mag+1.8)", capsize=2, fmt="o-", color="black")
plt.errorbar(date, magB, yerr=sigmaMagB, label="Image B", capsize=2, fmt="^-", color="black")

ax = plt.gca()
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)

plt.xticks(np.linspace(np.amin(date), np.amax(date), 12))
#  plt.xlim(np.amin(date), np.amax(date))
plt.legend()
plt.xlabel("Julian date")
plt.ylabel("Magnitude")
plt.savefig("timeDelay.pdf", bbox_inches="tight")
plt.close(k)
k += 1

data = np.genfromtxt("./disp.out_MCprob.tab", delimiter="\t").T
timeDel = data[0]
prob = data[1]

def gauss(x, mu, sigma):
    return 1/(sigma * np.sqrt(2*np.pi)) * np.exp(-(x-mu)**2/sigma**2/2)

plt.figure(num=k, figsize=(10,7))
plt.scatter(timeDel, prob, color="black", marker="^", label="from MC")

popt, pcov = curve_fit(gauss, timeDel, prob, p0=[34, 2])
print("Parameters", popt)
print("Covariance matrix", pcov)
xArray = np.linspace(np.amin(timeDel), np.amax(timeDel), 100)
probFit = gauss(xArray, *popt)
plt.plot(xArray, probFit, label="fit", color="black")
plt.legend()

plt.xlabel("Time delay")
plt.ylabel("Probability")
ax = plt.gca()
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
plt.savefig("MCProb.pdf", bbox_inches="tight")
plt.close(k)
k += 1


import ipaddress

from django.contrib.auth import get_user_model
from django.core.management import BaseCommand, call_command, CommandError
from django.db import transaction

from ralph.accounts.tests.factories import RegionFactory
from ralph.assets.models import ConfigurationClass, ConfigurationModule
from ralph.data_importer.management.commands.create_network import \
    Command as NetworkCommand
from ralph.data_importer.management.commands.create_server_model import \
    Command as ServerModelCommand
from ralph.data_importer.management.commands.create_transitions import \
    Command as TransitionsCommand

class Command(BaseCommand):
    """
    Generate data useful to start a fresh and empty Ralph instance.
    """
    @transaction.atomic
    def handle(self, *args, **options):
        try:
            parent_network = ipaddress.ip_network(
                options.get('parent_network')
            )
            dc_name = options.get('dc_name')
            server_room_name = options.get('server_room_name')
            network_address = parent_network.network_address
            dns_1 = ipaddress.ip_address(options.get('dns_1'))
            dns_2 = ipaddress.ip_address(options.get('dns_2'))
            number_of_subnets = int(options.get('number_of_subnets'))
            region = options.get('region')
            configuration_path = options.get('configuration_path')
        except ValueError as e:
            raise CommandError(e)

        self._validate_network(parent_network, number_of_subnets)
        self._validate_configuration_path(configuration_path)

        self.create_users(region)
        self.create_configuration_path(configuration_path)
        TransitionsCommand.create_data_center_asset_transitions()

        NetworkCommand.create_network(
            dc_name=dc_name,
            dns1_address=dns_1,
            dns2_address=dns_2,
            gateway_address=network_address + 1,
            network=parent_network,
            server_room_name=server_room_name
        )
        for _ in range(0, number_of_subnets):
            network = ipaddress.ip_network('{}/{}'.format(network_address, 24))
            NetworkCommand.create_network(
                dc_name=dc_name,
                dns1_address=dns_1,
                dns2_address=dns_2,
                gateway_address=network_address + 1,
                network=network,
                server_room_name=server_room_name,
                create_rack=True
            )
            network_address += 256

        for name in ["A", "B", "C"]:
            ServerModelCommand.create_model(
                    model_name="Model {}".format(name)
            )
            ServerModelCommand.create_model(
                model_name="Blade server model {}".format(name),
                is_blade=True
            )

        call_command('sitetree_resync_apps')

    def add_arguments(self, parser):
        parser.add_argument(
            '-d', '--dc-name',
            default='dc1',
            dest='dc_name',
            help='Data center name.'
        )
        parser.add_argument(
            '-s', '--server-room-name',
            default='server room',
            dest='server_room_name',
            help='Server room name.'
        )
        parser.add_argument(
            '-p', '--parent-network',
            default='10.0.0.0/16',
            dest='parent_network',
            help='Parent network address.'
        )
        parser.add_argument(
            '--dns1',
            default='10.0.0.11',
            dest='dns_1',
            help='Primary DNS server.'
        )
        parser.add_argument(
            '--dns2',
            default='10.0.0.12',
            dest='dns_2',
            help='Secondary DNS server.'
        )
        parser.add_argument(
            '-n', '--number-of-subnets',
            default='3',
            dest='number_of_subnets',
            help='Number of /24 subnets to be generated.'
        )
        parser.add_argument(
            '-r', '--region',
            default='PL',
            dest='region',
            help='Geographical region (eg. your location).'
        )
        parser.add_argument(
            '-c', '--configuration-path',
            default='configuration_module/default',
            dest='configuration_path',
            help='Default configuration path.'
        )

    def _validate_network(self, network, number_of_subnets):
        num_addresses = number_of_subnets * 256
        if network.num_addresses < num_addresses:
            raise CommandError(
                "Network {} will not accommodate {} /24 subnets.".format(
                    network, number_of_subnets
                )
            )
        max_netmask = ipaddress.ip_address('255.255.254.0')
        if network.netmask > max_netmask:
            raise CommandError(
                "Net mask must be /23 or less."
            )

    def _validate_configuration_path(self, configuration_path):
        if len(configuration_path.split('/')) != 2:
            raise CommandError(
                "Configuration path must be a string with no spaces including"
                "one slash."
            )

    def create_users(self, region):
        user_model = get_user_model()
        user, _ = user_model.objects.get_or_create(
            username='admin', is_staff=True, is_superuser=True
        )
        user.regions.add(RegionFactory(name=region))
        user.set_password('admin')
        user.save()

    def create_configuration_path(self, configuration_path):
        configuration_module, configuration_class = configuration_path.split(
            '/'
        )
        module = ConfigurationModule.objects.create(name=configuration_module)
        ConfigurationClass.objects.create(
            class_name=configuration_class, module=module
        )


import logging
import sys
import json
from test_consignment import TestConsignment
from consignment_tester import ConsignmentTester
from environment import Environment
from tests.test_tdr_bagit_retry import test_tdr_bagit_retry
from tests.test_tdr_bagit_function_error import test_tdr_bagit_function_error
from tests.test_tdr_files_retry import test_tdr_files_retry
from tests.test_parser_error_path import test_parser_error_path
from tests.test_editorial_retry import test_editorial_retry

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)

# Instantiate logger
logger = logging.getLogger(__name__)

def main(s3_data_bucket, environment_file, consignment_file, aws_profile_data=None, aws_profile_env=None):
    """
    s3_data_bucket          : Name of S3 bucket holding test data files
    environment_file        : Name of config file for test environment
    consignment_file        : Name of config file describing test consignments
    aws_profile_data        : AWS profile to locate test data files; defaults to AWS_PROFILE
    aws_profile_env         : AWS profile to access environment to test; defaults to aws_profile_data
    """
    logger.info(f'main: s3_data_bucket={s3_data_bucket} '
        f'environment_file={environment_file} '
        f'consignment_file={consignment_file} '
        f'aws_profile_data={aws_profile_data} '
        f'aws_profile_env={aws_profile_env}')

    config = None
    with open(environment_file) as f:
        config = Environment(json.load(f))

    ct = ConsignmentTester(
        s3_data_bucket=s3_data_bucket,
        environment=config,
        aws_profile_data=aws_profile_data,
        aws_profile_env=aws_profile_env)

    test_consignments = None
    with open(consignment_file) as f:
        test_consignments = json.load(f)

    tc_shared_consignment = TestConsignment(config=test_consignments['shared-consignment'])
    tc_bagit_retry = TestConsignment(config=test_consignments['test-bagit-retry'])
    tc_files_retry = TestConsignment(config=test_consignments['test-files-retry'])
    tc_parser_error = TestConsignment(config=test_consignments['test-parser-error'])

    test_editorial_retry(ct=ct, tc=tc_shared_consignment)  # good 1st test as also runs test_ok_path.py
    test_tdr_bagit_retry(ct=ct, tc=tc_bagit_retry)
    test_tdr_bagit_function_error(ct=ct)  # no tc param; uses malformed message to deliberately fail
    test_tdr_files_retry(ct=ct, tc=tc_files_retry)
    test_parser_error_path(ct=ct, tc=tc_parser_error)
    # test_tdr_duplicate_resend_parallel(ct=ct, tc=tc_shared_consignment)

    logger.info('###########################################################')
    logger.info('#                 All tests completed OK                  #')
    logger.info('###########################################################')

if __name__ == "__main__":
    if (len(sys.argv) < 4) or (len(sys.argv) > 6):
        raise ValueError('Usage: s3_data_bucket environment_file consignment_file '
            '[aws_profile_data] [aws_profile_env]')

    main(
        sys.argv[1],
        sys.argv[2],
        sys.argv[3],
        None if len(sys.argv) < 5 else sys.argv[4],
        None if len(sys.argv) < 6 else sys.argv[5]
    )


from copy import deepcopy
from functools import partial

import jax
import jax.numpy as jnp
import optax
from flax.training.train_state import TrainState
from ml_collections import ConfigDict

from algos.mf_algos.model import update_target_network
from core.core_api import Algo
from utilities.jax_utils import mse_loss, next_rng, value_and_multi_grad

class TD3(Algo):

  @staticmethod
  def get_default_config(updates=None):
    config = ConfigDict()
    config.nstep = 1
    config.discount = 0.99
    config.tau = 0.005
    config.policy_noise = 0.2
    config.noise_clip = 0.5
    config.policy_freq = 2
    config.alpha = 2.5
    config.policy_lr = 3e-4
    config.qf_lr = 3e-4
    config.use_scheduler = False
    config.target_entropy = 0.0

    if updates is not None:
      config.update(ConfigDict(updates).copy_and_resolve_references())
    return config

  def __init__(self, config, policy, qf, max_steps):
    self.config = self.get_default_config(config)
    self.policy = policy
    self.qf = qf
    self.observation_dim = policy.observation_dim
    self.action_dim = policy.action_dim
    self.policy_noise = self.config.policy_noise * policy.max_action
    self.max_action = policy.max_action
    self.max_step = max_steps

    self._total_steps = 0
    self._train_states = {}

    policy_params = self.policy.init(
      {
        'dropout': next_rng(),
        'params': next_rng()
      },
      next_rng(),
      jnp.zeros((10, self.observation_dim)),
    )
    policy_optim = optax.adam(self.config.policy_lr)
    if self.config.use_scheduler:
      schedule_fn = optax.cosine_decay_schedule(
        -self.config.policy_lr, self.max_steps
      )
      policy_optim = optax.chain(
        optax.scale_by_adam(), optax.scale_by_schedule(schedule_fn)
      )
    self._train_states['policy'] = TrainState.create(
      params=policy_params, tx=policy_optim, apply_fn=None
    )

    qf1_params = self.qf.init(
      next_rng(),
      jnp.zeros((10, self.observation_dim)),
      jnp.zeros((10, self.action_dim)),
    )
    self._train_states['qf1'] = TrainState.create(
      params=qf1_params,
      tx=optax.adam(self.config.qf_lr),
      apply_fn=None,
    )
    qf2_params = self.qf.init(
      next_rng(),
      jnp.zeros((10, self.observation_dim)),
      jnp.zeros((10, self.action_dim)),
    )
    self._train_states['qf2'] = TrainState.create(
      params=qf2_params,
      tx=optax.adam(self.config.qf_lr),
      apply_fn=None,
    )

    self._tgt_params = deepcopy(
      {
        'policy': policy_params,
        'qf1': qf1_params,
        'qf2': qf2_params,
      }
    )

    self._model_keys = ('policy', 'qf1', 'qf2')

  @partial(jax.jit, static_argnames=('self', 'policy_update'))
  def _train_step(
    self, train_states, tgt_params, rng, batch, policy_update=False
  ):

    def loss_fn(params, tgt_params, rng):
      observations = batch['observations']
      actions = batch['actions']
      rewards = batch['rewards']
      next_observations = batch['next_observations']
      dones = batch['dones']

      rng, split_rng = jax.random.split(rng)
      # Select next actions according to policy and add noise
      noise = jax.random.truncated_normal(
        split_rng,
        -self.config.noise_clip,
        self.config.noise_clip,
        shape=actions.shape,
        dtype=actions.dtype,
      ) * self.policy_noise

      rng, split_rng = jax.random.split(rng)
      next_action = self.policy.apply(
        params['policy'], rng, next_observations, rngs={'dropout': split_rng}
      )
      next_action = jnp.clip(
        next_action + noise, -self.max_action, self.max_action
      )

      # Compute the target Q values (without gradient)
      tgt_q1 = self.qf.apply(tgt_params['qf1'], next_observations, next_action)
      tgt_q2 = self.qf.apply(tgt_params['qf2'], next_observations, next_action)
      tgt_q = jnp.minimum(tgt_q1, tgt_q2)
      tgt_q = rewards + (1 - dones) * self.config.discount * tgt_q
      tgt_q = jax.lax.stop_gradient(tgt_q)

      # Compute the current Q estimates
      cur_q1 = self.qf.apply(params['qf1'], observations, actions)
      cur_q2 = self.qf.apply(params['qf2'], observations, actions)

      # qf loss
      qf1_loss = mse_loss(cur_q1, tgt_q)
      qf2_loss = mse_loss(cur_q2, tgt_q)
      qf_loss = qf1_loss + qf2_loss

      # Compute the policy loss
      rng, split_rng = jax.random.split(rng)
      new_actions = self.policy.apply(
        params['policy'], rng, observations, rngs={'dropout': split_rng}
      )
      q = self.qf.apply(params['qf1'], observations, new_actions)
      q_abs_mean = jax.lax.stop_gradient(jnp.abs(q).mean())
      lmbda = self.config.alpha / q_abs_mean
      bc_loss = mse_loss(new_actions, actions)
      policy_loss = -lmbda * q.mean() + bc_loss

      loss_collection = {'policy': policy_loss, 'qf1': qf_loss, 'qf2': qf_loss}
      return tuple(loss_collection[key] for key in self.model_keys), locals()

    # Calculate losses and grads
    params = {key: train_states[key].params for key in self.model_keys}
    (_, aux_values), grads = value_and_multi_grad(
      loss_fn, len(self.model_keys), has_aux=True
    )(params, tgt_params, rng)

    # Update qf train states
    train_states['qf1'] = train_states['qf1'].apply_gradients(
      grads=grads[1]['qf1']
    )
    train_states['qf2'] = train_states['qf2'].apply_gradients(
      grads=grads[2]['qf2']
    )

    # Update policy train states if necessary
    if policy_update:
      train_states['policy'] = train_states['policy'].apply_gradients(
        grads=grads[0]['policy']
      )

      # Update target parameters
      tgt_params['policy'] = update_target_network(
        train_states['policy'].params, tgt_params['policy'], self.config.tau
      )
      tgt_params['qf1'] = update_target_network(
        train_states['qf1'].params, tgt_params['qf1'], self.config.tau
      )
      tgt_params['qf2'] = update_target_network(
        train_states['qf2'].params, tgt_params['qf2'], self.config.tau
      )

    metrics = dict(
      policy_loss=aux_values['policy_loss'],
      qf_loss=aux_values['qf_loss'],
      qf1_loss=aux_values['qf1_loss'],
      qf2_loss=aux_values['qf2_loss'],
      bc_loss=aux_values['bc_loss'],
      cur_q1=aux_values['cur_q1'].mean(),
      cur_q2=aux_values['cur_q2'].mean(),
      tgt_q1=aux_values['tgt_q1'].mean(),
      tgt_q2=aux_values['tgt_q2'].mean(),
      tgt_q=aux_values['tgt_q'].mean(),
      lmbda=aux_values['lmbda'],
      q_abs_mean=aux_values['q_abs_mean'],
    )

    return train_states, tgt_params, metrics

  def train(self, batch, update_target_policy):
    self._total_steps += 1
    self._train_states, self._tgt_params, metrics = self._train_step(
      self._train_states, self._tgt_params, next_rng(), batch,
      self._total_steps % self.config.policy_freq == 0
    )
    return metrics

  @property
  def model_keys(self):
    return self._model_keys

  @property
  def train_states(self):
    return self._train_states

  @property
  def train_params(self):
    return {key: self.train_states[key].params for key in self.model_keys}

  @property
  def total_steps(self):
    return self._total_steps


import pytest

from medkit.core import ProvTracer
from medkit.core.text import Segment, Span
from medkit.text.segmentation import SentenceTokenizer

_TEXT = (
    "Sentence testing the dot. We are testing the carriage return\rthis is the"
    " newline\n Test interrogation ? Now, testing semicolon;Exclamation! Several"
    " punctuation characters?!..."
)

def _get_clean_text_segment(text):
    return Segment(
        label="clean_text",
        spans=[Span(0, len(text))],
        text=text,
    )

TEST_CONFIG = [
    # basic
    (
        SentenceTokenizer(),
        _TEXT,
        [
            ("Sentence testing the dot", [Span(start=0, end=24)]),
            ("We are testing the carriage return", [Span(start=26, end=60)]),
            ("this is the newline", [Span(start=61, end=80)]),
            ("Test interrogation ", [Span(start=82, end=101)]),
            ("Now, testing semicolon", [Span(start=103, end=125)]),
            ("Exclamation", [Span(start=126, end=137)]),
            ("Several punctuation characters", [Span(start=139, end=169)]),
        ],
    ),
    # keep punct chars in sentence
    (
        SentenceTokenizer(keep_punct=True),
        _TEXT,
        [
            ("Sentence testing the dot.", [Span(start=0, end=25)]),
            ("We are testing the carriage return", [Span(start=26, end=60)]),
            ("this is the newline", [Span(start=61, end=80)]),
            ("Test interrogation ?", [Span(start=82, end=102)]),
            ("Now, testing semicolon;", [Span(start=103, end=126)]),
            ("Exclamation!", [Span(start=126, end=138)]),
            ("Several punctuation characters?!...", [Span(start=139, end=174)]),
        ],
    ),
    # don't split on newlines
    (
        SentenceTokenizer(split_on_newlines=False),
        _TEXT,
        [
            ("Sentence testing the dot", [Span(start=0, end=24)]),
            (
                (
                    "We are testing the carriage return\rthis is the newline\n Test"
                    " interrogation "
                ),
                [Span(start=26, end=101)],
            ),
            ("Now, testing semicolon", [Span(start=103, end=125)]),
            ("Exclamation", [Span(start=126, end=137)]),
            ("Several punctuation characters", [Span(start=139, end=169)]),
        ],
    ),
    # trailing sentence with no final punct char
    (
        SentenceTokenizer(),
        "This is a sentence. This is a trailing sentence with no punct",
        [
            ("This is a sentence", [Span(start=0, end=18)]),
            ("This is a trailing sentence with no punct", [Span(start=20, end=61)]),
        ],
    ),
    # sentence ending with both punct and newline, keep only punct
    (
        SentenceTokenizer(keep_punct=True),
        "This is a sentence ending with punct and newline.\nThis is another sentence.",
        [
            (
                "This is a sentence ending with punct and newline.",
                [Span(start=0, end=49)],
            ),
            ("This is another sentence.", [Span(start=50, end=75)]),
        ],
    ),
    # empty sentence shall not be returned
    (
        SentenceTokenizer(),
        "This is a sentence.    ",
        [
            (
                "This is a sentence",
                [Span(start=0, end=18)],
            ),
        ],
    ),
    # empty sentence shall not be returned (keep_punct:true)
    (
        SentenceTokenizer(keep_punct=True),
        "This is a sentence.  !  ",
        [
            (
                "This is a sentence.",
                [Span(start=0, end=19)],
            ),
        ],
    ),
]

@pytest.mark.parametrize(
    "sentence_tokenizer,text,expected_sentences",
    TEST_CONFIG,
    ids=[
        "default",
        "keep_punct",
        "multiline",
        "trailing",
        "punct_and_newline",
        "empty_sentence",
        "empty_sentence_with_punct",
    ],
)
def test_run(sentence_tokenizer, text, expected_sentences):
    clean_text_segment = _get_clean_text_segment(text)
    sentences = sentence_tokenizer.run([clean_text_segment])

    assert len(sentences) == len(expected_sentences)
    for i, (text, spans) in enumerate(expected_sentences):
        assert sentences[i].text == text
        assert sentences[i].spans == spans

def test_prov():
    clean_text_segment = _get_clean_text_segment(
        "This is a sentence. This is another sentence."
    )

    tokenizer = SentenceTokenizer()
    prov_tracer = ProvTracer()
    tokenizer.set_prov_tracer(prov_tracer)
    sentences = tokenizer.run([clean_text_segment])

    sentence_1 = sentences[0]
    prov_1 = prov_tracer.get_prov(sentence_1.uid)
    assert prov_1.data_item == sentence_1
    assert prov_1.op_desc == tokenizer.description
    assert prov_1.source_data_items == [clean_text_segment]

    sentence_2 = sentences[1]
    prov_2 = prov_tracer.get_prov(sentence_2.uid)
    assert prov_2.data_item == sentence_2
    assert prov_2.op_desc == tokenizer.description
    assert prov_2.source_data_items == [clean_text_segment]


# Always prefer setuptools over distutils
from setuptools import setup, find_packages

# To use a consistent encoding
from codecs import open
from os import path

# The directory containing this file
HERE = path.abspath(path.dirname(__file__))

# Get the long description from the README file
with open(path.join(HERE, 'README.md'), encoding='utf-8') as f:
    long_description = f.read()

# This call to setup() does all the work
setup(
    name="opensea",
    version="0.2.0",
    description="wrapper library for opensea api",
    long_description=long_description,
    long_description_content_type="text/markdown",
    # url="https://opensea.readthedocs.io/", # TASKETE KUDASAI :(
    author="Ankush Singh",
    author_email="ankush4singh@gmail.com",
    license="MIT",
    classifiers=[
        "Intended Audience :: Developers",
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python :: 3",
        "Operating System :: OS Independent"
    ],
    packages=find_packages(),
    include_package_data=True,
    install_requires=["requests"]
)


# https://leetcode.com/problems/target-sum/
# Question : You are given an integer array nums and an integer target.
# You want to build an expression out of nums by adding one of the symbols '+' and '-'
# before each integer in nums and then concatenate all the integers.
# For example, if nums = [2, 1], you can add a '+' before 2 and a '-' before 1 and
# concatenate them to build the expression "+2-1".
# Return the number of different expressions that you can build, which evaluates to target.
#
# Question Type : ShouldSee
# Used : Make dp of size -total to +total
#        Run 2 loops, 1 for all elements and 1 for all possible total
#        After the loop, get result for target from dp.
#           Choose element and the next count.
#        Note that we are using 2 dp arrays here
# Logic: dp[-nums[0]] = 1
#        dp[nums[0]] += 1
#        for i in range(1, n):
#           next = defaultdict(int)
#           for k in range(-total, total + 1, 1):
#               next[k + nums[i]] += dp[k]
#               next[k - nums[i]] += dp[k]
#           dp = next
#        return dp.get(target, 0)
# Complexity : O(n*m) n is no of elements, m is sum of elements

from collections import defaultdict

def find_number(nums, target):
    total = sum(nums)
    n = len(nums)
    dp = defaultdict(int)

    dp[-nums[0]] = 1
    dp[nums[0]] += 1

    for i in range(1, n):
        next = defaultdict(int)
        for k in range(-total, total + 1, 1):
            next[k + nums[i]] += dp[k]
            next[k - nums[i]] += dp[k]
        dp = next

    return dp.get(target, 0)

if __name__ == "__main__":
    nums = [1, 1, 1, 1, 1]
    target = 3
    print(find_number(nums, target))

    nums = [2, 1]
    target = 1
    print(find_number(nums, target))

    nums = [0, 0, 0, 0, 0, 0, 0, 0, 1]
    target = 1
    print(find_number(nums, target))


import datetime
import itertools
import collections
from typing import List
x = 3 and 1 # and first judge if the first argument is None, '' or 0, if yes then return it, if not return the second argument

print(f'template is {x==3} or x = {x}')

a = [[0, 1], [1, 3]]
b = [[2, 4]]
a += b
print(a) # list add list = new combined list

dict = {None: 2}
# print(dict.setdefault(None, None.left)) # fail, because setdefault always execute the default first

def f1(x):
    if x:
        print(f"f1: {str(x)}")
        f2(x+1)

x = 2

def f2(x):
    print(f"f2: {str(x)}")

f1(5) # works because python define functions regardless of the order

for i in range(5):
    xx = i
print(xx) # variable can live outside of loop

print(5/2) # divide / in python3 return float, while // return int

s1 = 'aabccccdeeefg' #itertools.groupby required sorted first
dict1 = { k: len(list(g)) for k, g in itertools.groupby(s1) }
print(dict1)

x = 1
def f(y):
    global x  # global to access outside function, nonlocal in nested functions to access parent function variables
    x += y
    print(x)
f(2)

it = iter([1,2,3])
it2 = iter([4,5,6])

it3 = itertools.chain(it, it2)
for i in it3:
    print(i)

it3 = itertools.chain([1,1,1], [2,3,4])
for i in it3:
    print(i)

print(type(it))
list1 = [1,2,3]
print(type(list1[-1]))

print(1+1j*1 == 1+1j**1)

print(1 < 5 > 2)
print({1, 2} | {2, 3})


import datetime

class TimeCounter:

    def __init__(self):

        self.start_time = datetime.datetime.now()
        [self.t_hr, self.t_min, self.t_sec] =self.start_time.hour,self.start_time.minute,self.start_time.second

        self.old_t_hr = self.t_hr
        self.old_t_min = self.t_min
        self.old_t_sec = self.t_sec

        str_time_start = datetime.datetime.now()

    def get_time_str(self):
        #global str_time_start, str_time, old_str_time

        old_t_sec = self.t_sec
        [self.t_hr, self.t_min, self.t_sec] = datetime.now().hour, datetime.now().minute, datetime.now().second
        str_to_return = 0
        if not old_t_sec == self.t_sec:
            str_to_return = "{0}:{1}.{2}".format(self.t_hr, self.t_min, self.t_sec)

        return str_to_return

    def get_time_diff(self):
        now_time = datetime.datetime.now()

        old_t_sec = self.t_sec
        [self.t_hr, self.t_min, self.t_sec] = now_time.hour, now_time.minute, now_time.second
        str_to_return = 0
        if not old_t_sec == self.t_sec:
            hr_diff = self.t_hr - self.old_t_hr
            min_diff = self.t_min - self.old_t_min
            sec_diff = self.t_sec - self.old_t_sec

            str_to_return = datetime.timedelta(hours=hr_diff, minutes=min_diff, seconds=sec_diff)

        return str_to_return

    def make_two_digit_num(int_to_check):
        str_temp = '{}'.format(int_to_check)
        if int_to_check < 10: str_temp = '0{}'.format(int_to_check)
        return str_temp


import pytest
import numpy as np
import matplotlib.pyplot as plt

from tests.base import VisualTestCase
from tests.fixtures import Dataset
from sklearn.datasets import make_regression

from yellowbrick.regressor.influence import *
from yellowbrick.datasets import load_concrete

try:
    import pandas as pd
except ImportError:
    pd = None

##########################################################################
## Fixtures
##########################################################################

@pytest.fixture(scope="class")
def data(request):
    """
    Creates a random regression fixture that has a R2 score below 0.85 and several
    outliers that best demonstrate the effectiveness of influence visualizers.
    """
    X, y = make_regression(
        n_samples=100,
        n_features=14,
        n_informative=6,
        bias=1.2,
        noise=49.8,
        tail_strength=0.6,
        random_state=637,
    )

    request.cls.data = Dataset(X, y)

##########################################################################
## Assertion Helpers
##########################################################################

LEARNED_FIELDS = (
    "distance_",
    "p_values_",
    "influence_threshold_",
    "outlier_percentage_",
)

def assert_not_fitted(oz):
    for field in LEARNED_FIELDS:
        assert not hasattr(oz, field)

def assert_fitted(oz):
    for field in LEARNED_FIELDS:
        assert hasattr(oz, field)

##########################################################################
## Test CooksDistance Visualizer
##########################################################################

@pytest.mark.usefixtures("data")
class TestCooksDistance(VisualTestCase):
    """
    CooksDistance visual test cases
    """

    def test_cooks_distance(self):
        """
        Test image similarity of Cook's Distance on a random dataset
        """
        _, ax = plt.subplots()
        viz = CooksDistance(ax=ax)

        assert_not_fitted(viz)
        assert viz.fit(self.data.X, self.data.y) is viz
        assert_fitted(viz)

        # Test fitted values
        assert viz.distance_.shape == (self.data.X.shape[0],)
        assert viz.p_values_.shape == viz.distance_.shape
        assert 0.0 <= viz.influence_threshold_ <= 4.0
        assert 0.0 <= viz.outlier_percentage_ <= 100.0

        self.assert_images_similar(viz)

    def test_cooks_distance_quickmethod(self):
        """
        Test the cooks_distance quick method on a random dataset
        """
        _, ax = plt.subplots()
        viz = cooks_distance(
            self.data.X,
            self.data.y,
            ax=ax,
            draw_threshold=False,
            linefmt="r-",
            markerfmt="ro",
            show=False
        )

        assert_fitted(viz)
        self.assert_images_similar(viz)

    @pytest.mark.skipif(pd is None, reason="test requires pandas")
    def test_pandas_integration(self):
        """
        Test on the concrete dataset with pandas DataFrame and Series
        """
        data = load_concrete(return_dataset=True)
        X, y = data.to_pandas()

        assert isinstance(X, pd.DataFrame)
        assert isinstance(y, pd.Series)

        _, ax = plt.subplots()
        viz = CooksDistance(ax=ax).fit(X, y)
        assert_fitted(viz)

        assert viz.distance_.sum() == pytest.approx(1.2911900571300652)
        assert viz.p_values_.sum() == pytest.approx(1029.9999525376425)
        assert viz.influence_threshold_ == pytest.approx(0.003883495145631068)
        assert viz.outlier_percentage_ == pytest.approx(7.3786407766990285)

        viz.finalize()
        self.assert_images_similar(viz)

    def test_numpy_integration(self):
        """
        Test on concrete dataset with numpy arrays
        """
        data = load_concrete(return_dataset=True)
        X, y = data.to_numpy()

        assert isinstance(X, np.ndarray)
        assert isinstance(y, np.ndarray)

        _, ax = plt.subplots()
        viz = CooksDistance(ax=ax).fit(X, y)
        assert_fitted(viz)

        assert viz.distance_.sum() == pytest.approx(1.2911900571300652)
        assert viz.p_values_.sum() == pytest.approx(1029.9999525376425)
        assert viz.influence_threshold_ == pytest.approx(0.003883495145631068)
        assert viz.outlier_percentage_ == pytest.approx(7.3786407766990285)

        viz.finalize()
        self.assert_images_similar(viz)


from django.shortcuts import render

from django.contrib.auth.models import User
from django.views.generic import TemplateView

from report.utils import convert_to_64
from report.report import report
from core.models import Person

class Index(TemplateView):
    template_name = "index.html"

def exportUsersPDF(request):
    """Example of ExportPDF"""
    users = User.objects.all()

    users_list = []
    for user in users:
        users_list.append({
            'name': user.first_name,
            'username': user.username
        })

    person = Person.objects.filter(id=1).first()
    data = {
        'users': users_list,
        'image': convert_to_64(person.image.url)
    }

    return report(request, 'users', data)