# -*- coding: utf-8 -*-
"""
Profile: http://hl7.org/fhir/StructureDefinition/HealthcareService
Release: R4B
Version: 4.3.0
Build ID: c475c22
Last updated: 2022-05-28T12:47:40.239+10:00
"""
import typing

from pydantic import Field, root_validator
from pydantic.error_wrappers import ErrorWrapper, ValidationError
from pydantic.errors import MissingError, NoneIsNotAllowedError

from . import backboneelement, domainresource, fhirtypes

class HealthcareService(domainresource.DomainResource):
    """Disclaimer: Any field name ends with ``__ext`` doesn't part of
    Resource StructureDefinition, instead used to enable Extensibility feature
    for FHIR Primitive Data Types.

    The details of a healthcare service available at a location.
    """

    resource_type = Field("HealthcareService", const=True)

    active: bool = Field(
        None,
        alias="active",
        title="Whether this HealthcareService record is in active use",
        description=(
            "This flag is used to mark the record to not be used. This is not used "
            "when a center is closed for maintenance, or for holidays, the "
            "notAvailable period is to be used for this."
        ),
        # if property is element of this resource.
        element_property=True,
    )
    active__ext: fhirtypes.FHIRPrimitiveExtensionType = Field(
        None, alias="_active", title="Extension field for ``active``."
    )

    appointmentRequired: bool = Field(
        None,
        alias="appointmentRequired",
        title="If an appointment is required for access to this service",
        description=(
            "Indicates whether or not a prospective consumer will require an "
            "appointment for a particular service at a site to be provided by the "
            "Organization. Indicates if an appointment is required for access to "
            "this service."
        ),
        # if property is element of this resource.
        element_property=True,
    )
    appointmentRequired__ext: fhirtypes.FHIRPrimitiveExtensionType = Field(
        None,
        alias="_appointmentRequired",
        title="Extension field for ``appointmentRequired``.",
    )

    availabilityExceptions: fhirtypes.String = Field(
        None,
        alias="availabilityExceptions",
        title="Description of availability exceptions",
        description=(
            "A description of site availability exceptions, e.g. public holiday "
            "availability. Succinctly describing all possible exceptions to normal "
            "site availability as details in the available Times and not available "
            "Times."
        ),
        # if property is element of this resource.
        element_property=True,
    )
    availabilityExceptions__ext: fhirtypes.FHIRPrimitiveExtensionType = Field(
        None,
        alias="_availabilityExceptions",
        title="Extension field for ``availabilityExceptions``.",
    )

    availableTime: typing.List[fhirtypes.HealthcareServiceAvailableTimeType] = Field(
        None,
        alias="availableTime",
        title="Times the Service Site is available",
        description="A collection of times that the Service Site is available.",
        # if property is element of this resource.
        element_property=True,
    )

    category: typing.List[fhirtypes.CodeableConceptType] = Field(
        None,
        alias="category",
        title="Broad category of service being performed or delivered",
        description="Identifies the broad category of service being performed or delivered.",
        # if property is element of this resource.
        element_property=True,
    )

    characteristic: typing.List[fhirtypes.CodeableConceptType] = Field(
        None,
        alias="characteristic",
        title="Collection of characteristics (attributes)",
        description=None,
        # if property is element of this resource.
        element_property=True,
    )

    comment: fhirtypes.String = Field(
        None,
        alias="comment",
        title=(
            "Additional description and/or any specific issues not covered " "elsewhere"
        ),
        description=(
            "Any additional description of the service and/or any specific issues "
            "not covered by the other attributes, which can be displayed as further"
            " detail under the serviceName."
        ),
        # if property is element of this resource.
        element_property=True,
    )
    comment__ext: fhirtypes.FHIRPrimitiveExtensionType = Field(
        None, alias="_comment", title="Extension field for ``comment``."
    )

    communication: typing.List[fhirtypes.CodeableConceptType] = Field(
        None,
        alias="communication",
        title="The language that this service is offered in",
        description=(
            "Some services are specifically made available in multiple languages, "
            "this property permits a directory to declare the languages this is "
            "offered in. Typically this is only provided where a service operates "
            "in communities with mixed languages used."
        ),
        # if property is element of this resource.
        element_property=True,
    )

    coverageArea: typing.List[fhirtypes.ReferenceType] = Field(
        None,
        alias="coverageArea",
        title="Location(s) service is intended for/available to",
        description=(
            "The location(s) that this service is available to (not where the "
            "service is provided)."
        ),
        # if property is element of this resource.
        element_property=True,
        # note: Listed Resource Type(s) should be allowed as Reference.
        enum_reference_types=["Location"],
    )

    eligibility: typing.List[fhirtypes.HealthcareServiceEligibilityType] = Field(
        None,
        alias="eligibility",
        title="Specific eligibility requirements required to use the service",
        description=(
            "Does this service have specific eligibility requirements that need to "
            "be met in order to use the service?"
        ),
        # if property is element of this resource.
        element_property=True,
    )

    endpoint: typing.List[fhirtypes.ReferenceType] = Field(
        None,
        alias="endpoint",
        title=(
            "Technical endpoints providing access to electronic services operated "
            "for the healthcare service"
        ),
        description=(
            "Technical endpoints providing access to services operated for the "
            "specific healthcare services defined at this resource."
        ),
        # if property is element of this resource.
        element_property=True,
        # note: Listed Resource Type(s) should be allowed as Reference.
        enum_reference_types=["Endpoint"],
    )

    extraDetails: fhirtypes.Markdown = Field(
        None,
        alias="extraDetails",
        title=(
            "Extra details about the service that can't be placed in the other "
            "fields"
        ),
        description=None,
        # if property is element of this resource.
        element_property=True,
    )
    extraDetails__ext: fhirtypes.FHIRPrimitiveExtensionType = Field(
        None, alias="_extraDetails", title="Extension field for ``extraDetails``."
    )

    identifier: typing.List[fhirtypes.IdentifierType] = Field(
        None,
        alias="identifier",
        title="External identifiers for this item",
        description=None,
        # if property is element of this resource.
        element_property=True,
    )

    location: typing.List[fhirtypes.ReferenceType] = Field(
        None,
        alias="location",
        title="Location(s) where service may be provided",
        description="The location(s) where this healthcare service may be provided.",
        # if property is element of this resource.
        element_property=True,
        # note: Listed Resource Type(s) should be allowed as Reference.
        enum_reference_types=["Location"],
    )

    name: fhirtypes.String = Field(
        None,
        alias="name",
        title="Description of service as presented to a consumer while searching",
        description=(
            "Further description of the service as it would be presented to a "
            "consumer while searching."
        ),
        # if property is element of this resource.
        element_property=True,
    )
    name__ext: fhirtypes.FHIRPrimitiveExtensionType = Field(
        None, alias="_name", title="Extension field for ``name``."
    )

    notAvailable: typing.List[fhirtypes.HealthcareServiceNotAvailableType] = Field(
        None,
        alias="notAvailable",
        title="Not available during this time due to provided reason",
        description=(
            "The HealthcareService is not available during this period of time due "
            "to the provided reason."
        ),
        # if property is element of this resource.
        element_property=True,
    )

    photo: fhirtypes.AttachmentType = Field(
        None,
        alias="photo",
        title="Facilitates quick identification of the service",
        description=(
            "If there is a photo/symbol associated with this HealthcareService, it "
            "may be included here to facilitate quick identification of the service"
            " in a list."
        ),
        # if property is element of this resource.
        element_property=True,
    )

    program: typing.List[fhirtypes.CodeableConceptType] = Field(
        None,
        alias="program",
        title="Programs that this service is applicable to",
        description=None,
        # if property is element of this resource.
        element_property=True,
    )

    providedBy: fhirtypes.ReferenceType = Field(
        None,
        alias="providedBy",
        title="Organization that provides this service",
        description="The organization that provides this healthcare service.",
        # if property is element of this resource.
        element_property=True,
        # note: Listed Resource Type(s) should be allowed as Reference.
        enum_reference_types=["Organization"],
    )

    referralMethod: typing.List[fhirtypes.CodeableConceptType] = Field(
        None,
        alias="referralMethod",
        title="Ways that the service accepts referrals",
        description=(
            "Ways that the service accepts referrals, if this is not provided then "
            "it is implied that no referral is required."
        ),
        # if property is element of this resource.
        element_property=True,
    )

    serviceProvisionCode: typing.List[fhirtypes.CodeableConceptType] = Field(
        None,
        alias="serviceProvisionCode",
        title="Conditions under which service is available/offered",
        description=(
            "The code(s) that detail the conditions under which the healthcare "
            "service is available/offered."
        ),
        # if property is element of this resource.
        element_property=True,
    )

    specialty: typing.List[fhirtypes.CodeableConceptType] = Field(
        None,
        alias="specialty",
        title="Specialties handled by the HealthcareService",
        description=(
            "Collection of specialties handled by the service site. This is more of"
            " a medical term."
        ),
        # if property is element of this resource.
        element_property=True,
    )

    telecom: typing.List[fhirtypes.ContactPointType] = Field(
        None,
        alias="telecom",
        title="Contacts related to the healthcare service",
        description="List of contacts related to this specific healthcare service.",
        # if property is element of this resource.
        element_property=True,
    )

    type: typing.List[fhirtypes.CodeableConceptType] = Field(
        None,
        alias="type",
        title="Type of service that may be delivered or performed",
        description="The specific type of service that may be delivered or performed.",
        # if property is element of this resource.
        element_property=True,
    )

    @classmethod
    def elements_sequence(cls):
        """returning all elements names from
        ``HealthcareService`` according specification,
        with preserving original sequence order.
        """
        return [
            "id",
            "meta",
            "implicitRules",
            "language",
            "text",
            "contained",
            "extension",
            "modifierExtension",
            "identifier",
            "active",
            "providedBy",
            "category",
            "type",
            "specialty",
            "location",
            "name",
            "comment",
            "extraDetails",
            "photo",
            "telecom",
            "coverageArea",
            "serviceProvisionCode",
            "eligibility",
            "program",
            "characteristic",
            "communication",
            "referralMethod",
            "appointmentRequired",
            "availableTime",
            "notAvailable",
            "availabilityExceptions",
            "endpoint",
        ]

class HealthcareServiceAvailableTime(backboneelement.BackboneElement):
    """Disclaimer: Any field name ends with ``__ext`` doesn't part of
    Resource StructureDefinition, instead used to enable Extensibility feature
    for FHIR Primitive Data Types.

    Times the Service Site is available.
    A collection of times that the Service Site is available.
    """

    resource_type = Field("HealthcareServiceAvailableTime", const=True)

    allDay: bool = Field(
        None,
        alias="allDay",
        title="Always available? e.g. 24 hour service",
        description=(
            "Is this always available? (hence times are irrelevant) e.g. 24 hour "
            "service."
        ),
        # if property is element of this resource.
        element_property=True,
    )
    allDay__ext: fhirtypes.FHIRPrimitiveExtensionType = Field(
        None, alias="_allDay", title="Extension field for ``allDay``."
    )

    availableEndTime: fhirtypes.Time = Field(
        None,
        alias="availableEndTime",
        title="Closing time of day (ignored if allDay = true)",
        description=(
            "The closing time of day. Note: If the AllDay flag is set, then this "
            "time is ignored."
        ),
        # if property is element of this resource.
        element_property=True,
    )
    availableEndTime__ext: fhirtypes.FHIRPrimitiveExtensionType = Field(
        None,
        alias="_availableEndTime",
        title="Extension field for ``availableEndTime``.",
    )

    availableStartTime: fhirtypes.Time = Field(
        None,
        alias="availableStartTime",
        title="Opening time of day (ignored if allDay = true)",
        description=(
            "The opening time of day. Note: If the AllDay flag is set, then this "
            "time is ignored."
        ),
        # if property is element of this resource.
        element_property=True,
    )
    availableStartTime__ext: fhirtypes.FHIRPrimitiveExtensionType = Field(
        None,
        alias="_availableStartTime",
        title="Extension field for ``availableStartTime``.",
    )

    daysOfWeek: typing.List[typing.Optional[fhirtypes.Code]] = Field(
        None,
        alias="daysOfWeek",
        title="mon | tue | wed | thu | fri | sat | sun",
        description=(
            "Indicates which days of the week are available between the start and "
            "end Times."
        ),
        # if property is element of this resource.
        element_property=True,
        # note: Enum values can be used in validation,
        # but use in your own responsibilities, read official FHIR documentation.
        enum_values=["mon", "tue", "wed", "thu", "fri", "sat", "sun"],
    )
    daysOfWeek__ext: typing.List[
        typing.Union[fhirtypes.FHIRPrimitiveExtensionType, None]
    ] = Field(None, alias="_daysOfWeek", title="Extension field for ``daysOfWeek``.")

    @classmethod
    def elements_sequence(cls):
        """returning all elements names from
        ``HealthcareServiceAvailableTime`` according specification,
        with preserving original sequence order.
        """
        return [
            "id",
            "extension",
            "modifierExtension",
            "daysOfWeek",
            "allDay",
            "availableStartTime",
            "availableEndTime",
        ]

class HealthcareServiceEligibility(backboneelement.BackboneElement):
    """Disclaimer: Any field name ends with ``__ext`` doesn't part of
    Resource StructureDefinition, instead used to enable Extensibility feature
    for FHIR Primitive Data Types.

    Specific eligibility requirements required to use the service.
    Does this service have specific eligibility requirements that need to be
    met in order to use the service?
    """

    resource_type = Field("HealthcareServiceEligibility", const=True)

    code: fhirtypes.CodeableConceptType = Field(
        None,
        alias="code",
        title="Coded value for the eligibility",
        description=None,
        # if property is element of this resource.
        element_property=True,
    )

    comment: fhirtypes.Markdown = Field(
        None,
        alias="comment",
        title="Describes the eligibility conditions for the service",
        description=None,
        # if property is element of this resource.
        element_property=True,
    )
    comment__ext: fhirtypes.FHIRPrimitiveExtensionType = Field(
        None, alias="_comment", title="Extension field for ``comment``."
    )

    @classmethod
    def elements_sequence(cls):
        """returning all elements names from
        ``HealthcareServiceEligibility`` according specification,
        with preserving original sequence order.
        """
        return ["id", "extension", "modifierExtension", "code", "comment"]

class HealthcareServiceNotAvailable(backboneelement.BackboneElement):
    """Disclaimer: Any field name ends with ``__ext`` doesn't part of
    Resource StructureDefinition, instead used to enable Extensibility feature
    for FHIR Primitive Data Types.

    Not available during this time due to provided reason.
    The HealthcareService is not available during this period of time due to
    the provided reason.
    """

    resource_type = Field("HealthcareServiceNotAvailable", const=True)

    description: fhirtypes.String = Field(
        None,
        alias="description",
        title="Reason presented to the user explaining why time not available",
        description=(
            "The reason that can be presented to the user as to why this time is "
            "not available."
        ),
        # if property is element of this resource.
        element_property=True,
        element_required=True,
    )
    description__ext: fhirtypes.FHIRPrimitiveExtensionType = Field(
        None, alias="_description", title="Extension field for ``description``."
    )

    during: fhirtypes.PeriodType = Field(
        None,
        alias="during",
        title="Service not available from this date",
        description=(
            "Service is not available (seasonally or for a public holiday) from "
            "this date."
        ),
        # if property is element of this resource.
        element_property=True,
    )

    @classmethod
    def elements_sequence(cls):
        """returning all elements names from
        ``HealthcareServiceNotAvailable`` according specification,
        with preserving original sequence order.
        """
        return ["id", "extension", "modifierExtension", "description", "during"]

    @root_validator(pre=True, allow_reuse=True)
    def validate_required_primitive_elements_3105(
        cls, values: typing.Dict[str, typing.Any]
    ) -> typing.Dict[str, typing.Any]:
        """https://www.hl7.org/fhir/extensibility.html#Special-Case
        In some cases, implementers might find that they do not have appropriate data for
        an element with minimum cardinality = 1. In this case, the element must be present,
        but unless the resource or a profile on it has made the actual value of the primitive
        data type mandatory, it is possible to provide an extension that explains why
        the primitive value is not present.
        """
        required_fields = [("description", "description__ext")]
        _missing = object()

        def _fallback():
            return ""

        errors: typing.List["ErrorWrapper"] = []
        for name, ext in required_fields:
            field = cls.__fields__[name]
            ext_field = cls.__fields__[ext]
            value = values.get(field.alias, _missing)
            if value not in (_missing, None):
                continue
            ext_value = values.get(ext_field.alias, _missing)
            missing_ext = True
            if ext_value not in (_missing, None):
                if isinstance(ext_value, dict):
                    missing_ext = len(ext_value.get("extension", [])) == 0
                elif (
                    getattr(ext_value.__class__, "get_resource_type", _fallback)()
                    == "FHIRPrimitiveExtension"
                ):
                    if ext_value.extension and len(ext_value.extension) > 0:
                        missing_ext = False
                else:
                    validate_pass = True
                    for validator in ext_field.type_.__get_validators__():
                        try:
                            ext_value = validator(v=ext_value)
                        except ValidationError as exc:
                            errors.append(ErrorWrapper(exc, loc=ext_field.alias))
                            validate_pass = False
                    if not validate_pass:
                        continue
                    if ext_value.extension and len(ext_value.extension) > 0:
                        missing_ext = False
            if missing_ext:
                if value is _missing:
                    errors.append(ErrorWrapper(MissingError(), loc=field.alias))
                else:
                    errors.append(
                        ErrorWrapper(NoneIsNotAllowedError(), loc=field.alias)
                    )
        if len(errors) > 0:
            raise ValidationError(errors, cls)  # type: ignore

        return values


## Basic Python imports
import math
import random
from io import BytesIO

## PyTorch imports
import torch
import torch.nn.functional as F
import torchvision.transforms as transforms
import torchvision.transforms.functional as TF

## Image / Array imports
from PIL import Image
from PIL import ImageFilter
import numpy as np

import matplotlib as mpl
import matplotlib.pyplot as plt

class RotationTransform(object):
    """
    Rotates a PIL image by 0, 90, 180, or 270 degrees. Randomly chosen using a uniform distribution.
    """
    def __init__(self, angles=[0, 90, 180, 270]):
        self.angles = angles

    def __call__(self, image):
        angle = random.choice(self.angles)
        return TF.rotate(image, angle)

class GammaJitter(object):
    """
    Jitters the gamma of a PIL image between a uniform distribution of two values (low & high).
    Larger gammas make the shadows darker, smaller gammas make the shadows lighter.
    """
    def __init__(self, low=0.9, high=1.1):
        self.low = low
        self.high = high

    def __call__(self, image):
        gamma = np.random.uniform(self.low, self.high)
        return TF.adjust_gamma(image, gamma)

class BrightnessJitter(object):
    """
    Jitters the gamma of a PIL image between a uniform distribution of two values (low & high).
    Larger gammas make the shadows darker, smaller gammas make the shadows lighter.
    """
    def __init__(self, low=0.9, high=1.1):
        self.low = low
        self.high = high

    def __call__(self, image):
        factor = np.random.uniform(self.low, self.high)
        return TF.adjust_brightness(image, factor)

class RandomScale(object):
    """
    Scales a PIL image based on a value chosen from a uniform distribution of two values (low & high).
    """
    def __init__(self, low=1.0, high=1.1):
        self.low = low
        self.high = high

    def __call__(self, image):
        height = image.height
        width = image.width
        scale = np.random.uniform(self.low, self.high)
        image = TF.resize(image, (math.floor(height * scale), math.floor(width * scale)))
        return TF.center_crop(image, (height, width))

class Interpolate(object):
    """
    Resizes an image to a certain (square) size or by a scale factor.
    """
    def __init__(self, scale=1, size=0):
        self.scale = scale
        self.size = size

    def __call__(self, image):
        if self.size == 0:
            height = image.height
            width = image.width
            return image.resize(((width * self.scale) // 1, (height * self.scale) // 1), Image.BILINEAR)
        else:
            return image.resize((self.size, self.size), Image.BILINEAR)

class InterpolateTorch(object):
    """
    Resizes an image to a certain (square) size or by a scale factor.
    """
    def __init__(self, scale=1, size=0):
        self.scale = scale
        self.size = size

    def __call__(self, image):
        if self.size == 0:
            height = image.shape[1]
            width = image.shape[2]
            if len(image.shape) == 3:
                image = torch.unsqueeze(image, 0)
            return F.interpolate(image, scale_factor=self.scale, mode='bilinear', align_corners=True)
        else:
            return F.interpolate(image, size=(self.size, self.size), mode='bilinear', align_corners=True)

class MaxPool(object):
    """
    Performs Max Pooling on a PIL Image.
    """
    def __init__(self, kernel_size=2):
        self.kernel_size = kernel_size
        self.stride = kernel_size
        self.to_tensor = TF.to_tensor
        self.to_pil = TF.to_pil_image

    def __call__(self, image):
        image = self.to_tensor(image)
        image = F.max_pool2d(image, self.kernel_size, self.stride)
        image = self.to_pil(image)
        return image

class MaxPoolTorch(object):
    """
    Performs Max Pooling on a PyTorch tensor.
    """
    def __init__(self, kernel_size=2):
        self.kernel_size = kernel_size
        self.stride = kernel_size

    def __call__(self, image):
        image = F.max_pool2d(image, self.kernel_size, self.stride)
        return image

class AdaptiveCenterCrop(object):
    """
    Center crops the image to be a square of the smallest edge squared.
    """
    def __init__(self):
        pass

    def __call__(self, image):
        length = min(image.width, image.height)
        return TF.center_crop(image, (length, length))

class MedianFilter(object):
    """
    Randomly applies a median filter to an image.
    """
    def __init__(self, filter_size=3, p=0.1):
        self.filter_size = filter_size
        self.p = p

    def __call__(self, image):
        roll = random.random()
        if roll < self.p:
            return image.filter(ImageFilter.MedianFilter(self.filter_size))
        else:
            return image

class Squeeze(object):
    """
    Squeezes the given PyTorch Tensor object
    """
    def __init__(self):
        ...

    def __call__(self, image):
        if len(image.shape) == 4:
            return image.squeeze_(0)
        else:
            return image

class Unsqueeze(object):
    """
    Unsqueezes the given PyTorch Tensor object in axis=0
    """
    def __init__(self):
        ...

    def __call__(self, image):
        if len(image.shape) == 3:
            return image.unsqueeze_(0)
        else:
            return image

class JPEGCompression(object):
    """
    Compresses the image using jpeg compression and restores
    """
    def __init__(self, quality=75):
        self.quality = quality

    def __call__(self, image):
        save = BytesIO()
        image.save(save, 'JPEG', quality=self.quality)
        image = Image.open(save)
        return image

class JPEGCompressionTorch(object):
    """
    Compresses the image using jpeg compression and restores
    """
    def __init__(self, quality=75):
        self.quality = quality

    def __call__(self, image):
        assert torch.is_tensor(image)
        image = transforms.ToPILImage()(image.cpu().squeeze())
        save = BytesIO()
        image.save(save, 'JPEG', quality=self.quality)
        image = transforms.ToTensor()(Image.open(save))
        return (image.unsqueeze(0).cuda()).requires_grad_(True)

class RandomResizeAndPadTorch(object):
    """
    Randomly resizes and pads an image.
    """
    def __init__(self, initial_size, final_size):
        self.initial_size = initial_size
        self.final_size = final_size
        self.resize = F.interpolate
        self.pad = F.pad

    def __call__(self, image):
        # image = image.unsqueeze(0)

        # Resize the image
        resize_shape = random.randint(self.initial_size, self.final_size)
        image = self.resize(image, size=(resize_shape, resize_shape), mode='bilinear', align_corners=True)

        # Determine how much to pad and do it
        remainder = self.final_size - resize_shape
        left = random.randint(0, remainder)
        right = remainder - left
        top = random.randint(0, remainder)
        bottom = remainder - top
        image = self.pad(image, pad=(left, right, top, bottom), mode='constant', value=0)

        return image

class Normalize(object):
    """
    Normalizes a batch of RGB images [n, 3, H, W]
    """
    def __init__(self, mean, std):
        self.mean = mean
        self.std = std

    def __call__(self, image):
        if len(image.shape) == 3:
            image = image.unsqueeze(0)
        image[:, 0, :, :] = (image[:, 0, :, :] - self.mean[0]) / self.std[0]
        image[:, 1, :, :] = (image[:, 1, :, :] - self.mean[1]) / self.std[1]
        image[:, 2, :, :] = (image[:, 2, :, :] - self.mean[2]) / self.std[2]
        image = image.squeeze()
        return image


import math
from pykalman import KalmanFilter
import numpy as np
class info_updator():
    def __init__(self,list_lens=5,frequency=10):
        self.v_list=[0]*list_lens
        self.u_list=[0]*list_lens
        self.p_list=[0]*2
        self.r_list=[0]*2  #heading
        self.list_lens=list_lens
        self.course_angle_list=[0]*list_lens
        self.position=[0,0,0,0]
        self.frequency=10
        self.init_filter()

    def init_filter(self):
        random_state = np.random.RandomState(0)
        transition_matrix = [[1, 0.1], [0, 1]]
        transition_offset = [-0.1, 0.1]
        observation_matrix = np.eye(2) + random_state.randn(2, 2) * 0.1
        observation_offset = [1.0, -1.0]
        transition_covariance = np.eye(2)
        observation_covariance = np.eye(2) + random_state.randn(2, 2) * 0.1
        initial_state_mean = [5, -5]
        initial_state_covariance = [[1, 0.1], [-0.1, 1]]
        # sample from model
        self.kf = KalmanFilter(
            transition_matrix, observation_matrix, transition_covariance,
            observation_covariance, transition_offset, observation_offset,
            initial_state_mean, initial_state_covariance,
            random_state=random_state
        )

    def update_velocity(self,new_location,position):
            [x,y,roll,heading_angle]=new_location
            [last_x,last_y,last_roll,last_heading]=self.position

            velocity=self.get_velocity(x,last_x,y,last_y,heading_angle,last_heading,roll,last_roll)

            course_angle=math.atan2(self.position[1]-last_y,self.position[0]-last_x)

            self.position=new_location

            return velocity,course_angle,self.position

    def get_velocity(self,x,last_x,y,last_y,heading_angle,last_heading,roll,last_roll):
        del_x=x-last_x
        del_y=y-last_y

        v=(del_x*math.cos(self.position[3])+del_y*math.sin(self.position[3]))*self.frequency

        u=(-del_x*math.sin(self.position[3])+del_y*math.cos(self.position[3]))*self.frequency
        r=(heading_angle-last_heading)*self.frequency
        p=(roll-last_roll)*self.frequency

        ### due to the noise, the velocity we choose is the mean value of the velocities in 0.7 second.
        self.v_list.pop(0)
        if abs(v)>3:
            v=self.v_list[self.list_lens-2]
        self.v_list.append(v)

        self.u_list.pop(0)
        if abs(u)>1:
            u=self.u_list[self.list_lens-2]
        self.u_list.append(u)

        self.r_list.pop(0)
        if abs(r)>3.5:
            r=self.r_list[0]
        self.r_list.append(r)

        self.p_list.pop(0)
        if abs(p)>2:
            p=self.p_list[0]
        self.p_list.append(p)

        v=0
        u=0
        p=0
        r=0
        # [v,u]=self.smoothing_curve()
        for i in range (0,self.list_lens):
            v+=self.v_list[i]/self.list_lens
            u+=self.u_list[i]/self.list_lens
        for i in range (0,2):
            r+=self.r_list[i]/2
            p+=self.p_list[i]/2
        # print('aaaaa',v)
        return [v,u,p,r]

    def smoothing_curve(self):
        observations=np.array([[0,0]])
        for i in range(0,self.list_lens):
            # observations=np.delete(observations,0,0)
            observations=np.append(observations,[[self.v_list[i],self.u_list[i]]],axis=0)
        observations=np.delete(observations,0,axis=0)
        smoothed_state_estimates = self.kf.smooth(observations)[0]
        return smoothed_state_estimates[self.list_lens-1]


"""Тесты для таблиц с курсом доллара."""
from datetime import date, datetime

import pandas as pd
import pytest

from poptimizer.data import ports
from poptimizer.data.domain import events
from poptimizer.data.domain.tables import base, usd

@pytest.fixture(scope="function", name="table")
def create_table():
    """Создает пустую таблицу для тестов."""
    id_ = base.create_id(ports.USD, ports.USD)
    return usd.USD(id_)

def test_update_cond(table):
    """Обновление происходит всегда при поступлении события."""
    assert table._update_cond(object())

@pytest.mark.asyncio
async def test_prepare_df_for_new_table(table, mocker):
    """Если таблица без данных, то осуществляется загрузка с начала."""
    event = events.TradingDayEnded(date(2021, 2, 3))
    fake_gateway = mocker.AsyncMock()
    table._gateway = fake_gateway

    assert await table._prepare_df(event) == fake_gateway.return_value
    fake_gateway.assert_called_once_with(None, "2021-02-03")

@pytest.mark.asyncio
async def test_prepare_df_for_update_table(table, mocker):
    """Если таблица c данных, то осуществляется инкрементальная загрузка."""
    event = events.TradingDayEnded(date(2021, 2, 3))
    fake_gateway = mocker.AsyncMock()
    fake_gateway.return_value = pd.DataFrame(
        [2, 1],
        index=[
            datetime(2020, 12, 14),
            datetime(2020, 12, 15),
        ],
    )
    table._gateway = fake_gateway
    table._df = pd.DataFrame(
        [3, 2],
        index=[
            datetime(2020, 12, 13),
            datetime(2020, 12, 14),
        ],
    )

    new_df = await table._prepare_df(event)
    pd.testing.assert_frame_equal(
        new_df,
        pd.DataFrame(
            [3, 2, 1],
            index=[
                datetime(2020, 12, 13),
                datetime(2020, 12, 14),
                datetime(2020, 12, 15),
            ],
        ),
    )
    fake_gateway.assert_called_once_with("2020-12-14", "2021-02-03")

def test_validate_new_df(mocker, table):
    """Осуществляется проверка на уникальность и согласованность данных."""
    mocker.patch.object(base, "check_unique_increasing_index")
    mocker.patch.object(base, "check_dfs_mismatch")

    table._validate_new_df(mocker.sentinel)

    base.check_unique_increasing_index.assert_called_once_with(mocker.sentinel)
    base.check_dfs_mismatch.assert_called_once_with(table.id_, None, mocker.sentinel)

def test_new_events(table, mocker):
    """Возвращает событие обновления курса."""
    table._df = mocker.Mock()
    new_events = table._new_events(events.TradingDayEnded(date=date(2020, 2, 5)))

    assert new_events == [
        events.USDUpdated(
            date=date(2020, 2, 5),
            usd=table._df.copy.return_value,
        ),
    ]


# -*- python -*-
#
#       dtk function implementation
#
#       2010 INRIA - CIRAD - INRA
#
#       File author(s): Eric Moscardi <eric.moscardi@sophia.inria.fr>
#
#       Distributed under the Cecill-C License.
#       See accompanying file LICENSE.txt or copy at
#           http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html
#
#       OpenAlea WebSite : http://openalea.gforge.inria.fr
#

#dtkCorePath = "/home/pradal/local/inria/modules"

import os
#dtkPath = os.getenv('DTKPYTHONPATH',dtkCorePath)

#try:
#    sys.path.insert(0, dtkPath)
#    del sys.modules['core']
#    del core
#except: pass

from qtpy import QtWidgets
import dtkcore as core
import sip

from openalea.core import *

class DtkNode(Node):
    """

    """
    def __init__(self, inputs, outputs):
        super(DtkNode,self).__init__(inputs, outputs)
        self.dtk_factory = None
        self._data = None

    def data(self, name='dtkData'):
        factory = self.dtk_factory

        if factory is None:
            self._data = self.get_input(name)
            factory.setData(self._data)

        data = self.get_input(name)
        if data != self._data:
            self._data = data
            factory.setData(self._data)

    def setProperty(self):
        for p in self.dtk_factory.properties():
            self.dtk_factory.setProperty(p, self.get_input(p))

    #@property
    def name(self):
        return self.get_caption()

class dtkProcess(DtkNode):
    """
    """

    def __call__(self, inputs):

        if self.dtk_factory is None:
            self.dtk_factory = core.dtkAbstractProcessFactory.instance().create(self.name())

        self.data('dtkData')
        self.setProperty()

        self.dtk_factory.update()
        return self.dtk_factory.output(),

class dtkView(DtkNode):
    """
    """

    def interact(self, name):
        self.dtk_factory.enableInteractor(name)
        return self.dtk_factory.interactor(name)
    def animate(self, name):
        self.dtk_factory.enableAnimator(name)
        return self.dtk_factory.animator(name)
    def navigate(self, name):
        self.dtk_factory.enableNavigator(name)
        return self.dtk_factory.navigator(name)

    def __call__(self, inputs):

        if self.dtk_factory is None:
            self.dtk_factory = core.dtkAbstractViewFactory.instance().create(self.name())
            #self.dtk_factory.showMaximized()

        self.data('dtkData')
        self.setProperty()

        d = dict(zip(("dtkViewInteractor","dtkViewNavigator","dtkViewAnimator"),
                     (self.interact, self.navigate, self.animate)))
        for dtkview, method in d.items():

            input = self.get_input(dtkview)
            if input:
                name = input['name']
                properties = input['properties']
                interactor = method(name)

                for p, k in properties.items():
                    interactor.setProperty(p, k)

        self.dtk_factory.update()
        self.dtk_factory.reset()

        widget = self.dtk_factory.widget()
        widget = sip.wrapinstance(widget.__long__(), QtWidgets.QWidget)
        widget.show()

#class dtk_Data_Reader_Writer(DtkNode):
class dtkReader(DtkNode):
    """
    """

    def __call__(self, inputs):

        if self.dtk_factory is None:
            #self.dtk_factory = core.dtkAbstractDataFactory.instance().create(self.get_input("dtkDataType"))
            fname = self.get_input("filename")
            readers = core.dtkAbstractDataFactory.instance().readers()
            #if 'Reader' in self.name():
            #    self.dtk_factory.enableReader(self.name())
            #    self.dtk_factory.read(self.get_input("filename"))
            #elif 'Writer' in self.name():
            #    self.dtk_factory.enableWriter(self.name())
            #    self.dtk_factory.write(self.get_input("filename"))
            #else:
            #    return
            for r in readers:
                dataReader = core.dtkAbstractDataFactory.instance().reader(r.first,r.second)
                if (dataReader.canRead(fname)):
                    dataReader.read(fname)
                    self.dtk_factory = dataReader.data()
        return self.dtk_factory

class dtkWriter(DtkNode):
    """
    TODO:: check the behavior is correct...
    """

    def __call__(self, inputs):

        if self.dtk_factory is None:
            fname = self.get_input("filename")
            writers = core.dtkAbstractDataFactory.instance().writers()
            for w in writers:
                dataWriter = core.dtkAbstractDataFactory.instance().writer(w.first,w.second)
                if (dataWriter.canWrite(fname)):
                    dataWriter.write(fname)
                    self.dtk_factory = dataWriter.data()
        return self.dtk_factory

class dtkData(DtkNode):
    """
    """

    def __call__(self, inputs):

        if self.dtk_factory is None:
            self.dtk_factory = core.dtkAbstractDataFactory.instance().create(self.name())

        self.data('data')
        self.setProperty()

        return self.dtk_factory

class dtkInteractor(DtkNode):
    """
    """

    def __call__(self, inputs):

        output = {}
        properties = {}
        output['name'] = self.name()

        for p in range(self.get_nb_input()):
            input_name = self.input_desc[p]['name']
            properties[input_name] = inputs[p]
        output['properties'] = properties
        return output,


__author__ = "Chris"
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
import plotly
import plotly.graph_objects as go
import plotly.express as px
from plotly.subplots import make_subplots
from dython.nominal import associations

def dist_vis(data: pd.core.frame.DataFrame,
             column: str = None,
             bars: int = None,
             separator: str = None,
             fig_title: str = None,
             x_title: str = None,
             legend: bool = False,
             h: int = 600,
             w: int = 750):
    """
    Function to create visuals of distributions with plotly

    Parameters
    ----------
    :param data: dataframe
    :param column: factor to view
    :param bars: number of bins
    :param separator: factor to differentiate the distribution by with color
    :param fig_title: title of figure
    :param x_title: title for x-axis
    :param legend: indicate to use a legend
    :param h: height
    :param w: width
    :return: plotly.graph_objs._figure.Figure
    """
    figure_0 = px.histogram(data, x=column, nbins=bars, color=separator, opacity=0.75)
    figure_0.update_layout(height=h, width=w,
                           title_text=fig_title,
                           showlegend=legend)
    figure_0.update_yaxes(title_text="Number of Records")
    figure_0.update_xaxes(title_text=x_title)

    return figure_0

def comp_dist(data: pd.core.frame.DataFrame,
              fac_1: dict = {},
              fac_2: dict = {}):
    """
    Function to compare distributions

    Parameters
    ----------
    :param data: Pandas Dataframe
    :param fac_1: information around the first factor to display
            {'column_name': None,
            'title': None,
            'x_axis': None}
    :param fac_2: information around the second factor to display
        {'column_name': None,
        'title': None,
        'x_axis': None}
    :return:
    """
    # Define space for figure
    figure_1 = make_subplots(rows=2, cols=1)

    # Define dimensions, title, and legend
    figure_1.update_layout(height=800, width=850,
                           title_text="Skewed Distributions of Continuous Census Data Features",
                           showlegend=False)

    # Create plots
    figure_1.add_trace(
        go.Histogram(x=data[fac_1['column_name']], nbinsx=25,
                     name=fac_1['title']),
        row=1, col=1)
    figure_1.add_trace(
        go.Histogram(x=data[fac_2['column_name']], nbinsx=25,
                     name=fac_2['title']),
        row=2, col=1)

    # Define x-axis titles for plots
    figure_1.update_xaxes(title_text=fac_1['x_axis'], row=1, col=1)
    figure_1.update_xaxes(title_text=fac_2['x_axis'], row=2, col=1)

    # Define y-axis for each plot
    for i in range(1, 3):
        figure_1.update_yaxes(title_text="Number of Records", range=[0, 2000],
                              patch=dict(tickmode='array',
                                         tickvals=[0, 500, 1000, 1500, 2000],
                                         ticktext=[0, 500, 1000, 1500, ">2000"]),
                              row=i, col=1)

    return figure_1


from django.contrib import admin
from .models import Device, Log, MaintainLog,SlicSfp,SlicSfpInfo
from django.contrib.admin.models import LogEntry
from django.contrib.admin.options import ModelAdmin
import datetime

def my_construct_change_message (self, request, form, formsets):
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            ip = x_forwarded_for.split(',')[-1].strip()
        else:
            ip = request.META.get('REMOTE_ADDR')
        change_message = ['User from %s. Changed at %s.' % (ip, str(datetime.datetime.now())[:-7])]
        if form.changed_data:
            for data in form.changed_data:
                try:
                    toData = form.data[data]
                except:
                    toData = 'off'
                fromData = form.initial[data]
                if not fromData:
                    fromData = 'empty'
                if not toData:
                    toData = 'empty'
                change_message.append('Changed %s from %s to %s. ' % (data, fromData, toData))

        if formsets:
            for formset in formsets:
                for added_object in formset.new_objects:
                    change_message.append('Added %(name)s "%(object)s".' % {'name': added_object._meta.verbose_name, 'object': added_object})
                for changed_object, changed_fields in formset.changed_objects:
                    change_message.append('Changed %(list)s for %(name)s "%(object)s".'
                                          % {'list': changed_fields,
                                             'name': changed_object._meta.verbose_name,
                                             'object': changed_object})
                for deleted_object in formset.deleted_objects:
                    change_message.append('Deleted %(name)s "%(object)s".'
                                          % {'name': deleted_object._meta.verbose_name,
                                             'object': deleted_object})
        change_message = ' '.join(change_message)
        return change_message or 'No fields changed.'

ModelAdmin.construct_change_message = my_construct_change_message

# Register your models here.

class DeviceAdmin(admin.ModelAdmin):
    list_display = ('name', 'port', 'lock', 'link', 'owner', 'info')
class SlicSfpInfoAdmin(admin.ModelAdmin):
    list_display = ('MachineName', 'user', 'reserve_number','release_number','info','time')
    list_filter = ('MachineName','user')
admin.site.register(Device, DeviceAdmin)
admin.site.register(Log)
admin.site.register(MaintainLog)
# admin.site.register(NPEDevice)
admin.site.register(SlicSfp)
admin.site.register(SlicSfpInfo,SlicSfpInfoAdmin)
admin.site.register(LogEntry)


# uncompyle6 version 3.7.4
# Python bytecode 2.4 (62061)
# Decompiled from: Python 3.6.9 (default, Apr 18 2020, 01:56:04)
# [GCC 8.4.0]
# Embedded file name: build/bdist.linux-i686/egg/Products/DigestoContentTypes/browser/searchtools.py
# Compiled at: 2009-04-26 22:17:24
from zope.component import getUtility
from zope.interface import implements
from Products.DigestoContentTypes import DigestoContentTypesMessageFactory as _
from Products.DigestoContentTypes.utilities.interfaces import INormativaTypes
from Products.Five.browser import BrowserView
from interfaces import ISearchTools
from Products.CMFCore.utils import getToolByName
from DateTime.DateTime import DateTime

class SearchTools(BrowserView):
    __module__ = __name__
    implements(ISearchTools)

    def search_results(self, request):
        if not request.get('SearchableText', '') and not request.get('getKind', '') and not request.get('getArea', '') and not request.get('getNumber', '') and not request.get('getDate', '') and not request.get('getSource', ''):
            return []
        portal_catalog = getToolByName(self.context, 'portal_catalog')
        query = {'portal_type': 'Normativa', 'SearchableText': request.get('SearchableText', ''), 'getKind': request.get('getKind', ''), 'getArea': request.get('getArea', ''), 'getSource': request.get('getSource', '')}

        def fixyy(year):
            if year >= 0 and year < 20:
                return 2000 + year
            elif year >= 20 and year <= 99:
                return 1900 + year
            else:
                return year

        date = request.get('getDate', '')
        if date:
            try:
                date = fixyy(int(date))
                query['getDate'] = {'query': [DateTime(str(date) + '/01/01'), DateTime(str(date) + '/12/31')], 'range': 'minmax'}
            except:
                query['getDate'] = ''

        stext = request.get('SearchableText', '')
        if stext:
            try:
                words = stext.split(' ')
                words = [ word for word in words if word ]
                if len(words) == 1:
                    num_year = words[0].split('/')
                    if len(num_year) != 2:
                        num_year = words[0].split('-')
                    if len(num_year) == 2:
                        num = int(num_year[0])
                        year = int(num_year[1])
                        year = fixyy(year)
                        query['getDate'] = {'query': [DateTime(str(year) + '/01/01'), DateTime(str(year) + '/12/31')], 'range': 'minmax'}
                        query['getNumber'] = num
                        query['SearchableText'] = ''
                elif len(words) == 2:
                    nt = getUtility(INormativaTypes)
                    normalized_types = nt.get_types()
                    normalized_word = words[0]
                    if normalized_word in normalized_types:
                        num_year = words[1].split('/')
                        if len(num_year) != 2:
                            num_year = words[1].split('-')
                        if len(num_year) == 2:
                            num = int(num_year[0])
                            year = int(num_year[1])
                            year = fixyy(year)
                            query['getDate'] = {'query': [DateTime(str(year) + '/01/01'), DateTime(str(year) + '/12/31')], 'range': 'minmax'}
                            query['getNumber'] = num
                            query['getKind'] = normalized_word
                            query['SearchableText'] = ''
            except:
                pass

        number = request.get('getNumber', '')
        if number and not isinstance(number, int):
            try:
                number = int(number)
                query['getNumber'] = number
            except:
                pass

        if isinstance(number, int):
            numero_normativa = request.get('numero_normativa', '')

            def use_number_as(number, attribute, query):
                temp_results = portal_catalog.searchResults(**query)
                temp_results_modifies = [ getattr(a, attribute) for a in temp_results ]
                i = 0
                while i < len(temp_results_modifies):
                    j = 0
                    while j < len(temp_results_modifies[i]):
                        if not isinstance(temp_results_modifies[i][j], int):
                            temp_results_modifies[i][j] = temp_results_modifies[i][j].getNumber()
                        j = j + 1

                    i = i + 1

                temp_results_tuple = zip(temp_results, temp_results_modifies)
                results = [ a[0] for a in temp_results_tuple if number in a[1] ]
                return results

            if numero_normativa == 'modifies':
                query['getNumber'] = ''
                return use_number_as(number, 'getModifies', query)
            elif numero_normativa == 'repeals':
                query['getNumber'] = ''
                return use_number_as(number, 'getRepeals', query)
            elif numero_normativa == 'isrepealedby':
                query['getNumber'] = ''
                return use_number_as(number, 'getRepealedBy', query)
        if query.get('SearchableText') and not query.get('getKind') and not query.get('getArea') and not query.get('getNumber') and not query.get('getDate') and not query.get('getSource'):
            query['portal_type'] = [
             'Normativa', 'Attachment']
        results = portal_catalog.searchResults(**query)
        return results