from structure import Test, TestFile, TestFileCreatorInterface
from utils import iterable_as_cairo_array, assert_option_is_none

class SignatureProofsTest(TestFileCreatorInterface):
    def __init__(self) -> None:
        super().__init__()

    def test_file(self, python_source_folder: str) -> TestFile:
        tf = TestFile("signature_proofs", python_source_folder)
        tf.add_imports(self.get_imports())
        for l in [3, 12, 100]:
            tf.add_block(self.get_test(l))
        return tf

    def get_imports(self):
        return [
            "core::traits::Into",
            "core::option::OptionTrait",
            "array::ArrayTrait",
            "webauthn_session::signature::ImplSignatureProofs",
        ]

    def get_test(self, length: int):
        body = iterable_as_cairo_array(
            bytes([i % 256 for i in range(length)]), "proofs", "felt252"
        )
        for proof_size in [i + 1 for i in range(length)]:
            value = f"ImplSignatureProofs::try_new(proofs.span(), {proof_size})"
            if length % proof_size == 0:
                proof_count = length // proof_size
                body += "{\n\t"
                body += "\n\t".join(
                    [
                        f"let option = {value}.unwrap();",
                        f"assert(option.len() == {proof_count}, 'Wrong length');",
                        f"assert(option.at(0).len() == {proof_size}, 'Wrong length');",
                        f"assert(*option.at(0).at(0) == 0, 'Should equal');",
                        f"assert(*option.at({proof_count - 1}).at(0) == {(length - proof_size) % 255}, 'Should equal');",
                        f"assert(*option.at({proof_count - 1}).at({proof_size - 1}) == {(length - 1) % 255}, 'Should equal');",
                    ]
                )
                body += "\n}\n"
            else:
                body += assert_option_is_none(value)
        return Test(f"signature_proofs_{length}", body, length * 100000)


from requests_oauthlib import OAuth2Session
from oauthlib.oauth2 import BackendApplicationClient
import logging

class Oauth:
    """
    Utility class for creating the oauth callback function passed into the consumer.
    """

    def __init__(self, auth_config):
        self.token_url = auth_config["oauth.token.endpoint.uri"]
        self.client_id = auth_config["oauth.client.id"]
        self.client_secret = auth_config["oauth.client.secret"]
        self.logger = logging.getLogger(__name__)

    def oauth_cb(self, config_str):
        client = BackendApplicationClient(client_id=self.client_id)
        oauth = OAuth2Session(client=client)
        token_json = oauth.fetch_token(
            token_url=self.token_url, client_id=self.client_id, client_secret=self.client_secret)
        token = token_json["access_token"]
        expires_at = token_json["expires_at"]
        return (token, expires_at)


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
A dialog that allows the user to browse the files and directories on
a remote machine.

It provides a GUI to :class:`pyl2extra.utils.remote.Remote`.
"""
from __future__ import with_statement

__authors__ = "Nicu Tofan"
__copyright__ = "Copyright 2015, Nicu Tofan"
__credits__ = ["Nicu Tofan"]
__license__ = "3-clause BSD"
__maintainer__ = "Nicu Tofan"
__email__ = "nicu.tofan@gmail.com"

import os
from PyQt4 import (QtCore, QtGui)
import sys

from pyl2extra.utils import remote
from pyl2extra.gui.guihelpers import center
from pyl2extra.gui.remote import Remote

class RemoteBrowse(QtGui.QDialog):
    """
    Dialog to allow exploring a remote host.

    Parameters
    ----------
    parent : str, optional
        Parent widget.
    remt : str, optional
        The remote in question.
    """
    def __init__(self, parent=None, remt=None, local_path=None,
                 settings=None):

        if settings is None:
            self.settings = QtCore.QSettings('pyl2extra', 'remote_browse')
        else:
            self.settings = settings

        if remt is None:
            remt = remote.Remote(host='somehost',
                                 user='',
                                 port=22,
                                 password='',
                                 key_file='')
        if local_path is None:
            local_path = os.getcwd()

        #: Remote machine class.
        self.remote = None
        #: Path on local machine.
        self.local_path = local_path

        super(RemoteBrowse, self).__init__(parent)
        self.init_ui()

        self.change_remote(remt)
        self.change_local_path(local_path)
        self.local_tree.resizeColumnToContents(0)

    def init_ui(self):
        """
        Prepares the widgets tor the dialog.
        """
        try:
            size = self.settings.value('RemoteBrowse/size', type=QtCore.QSize)
            self.resize(size)
        except TypeError:
            self.resize(900, 800)

        try:
            point = self.settings.value('RemoteBrowse/pos', type=QtCore.QPoint)
            self.move(point)
        except TypeError:
            center(self)

        self.grid = QtGui.QGridLayout(self)

        info = "The path on local machine"
        self.lbl_local = QtGui.QLabel('Local path')
        self.lbl_local.setWhatsThis(info)
        self.lbl_local.setToolTip(info)
        self.grid.addWidget(self.lbl_local, 0, 0, 1, 1)
        self.le_local = QtGui.QLineEdit()
        self.le_local.setWhatsThis(info)
        self.le_local.setToolTip(info)
        self.le_local.setText(self.local_path)
        self.le_local.editingFinished.connect(self._local_select)
        self.grid.addWidget(self.le_local, 0, 1, 1, 1)

        info = "Files and folders on local machine"
        self.fsmodel = QtGui.QFileSystemModel()
        self.fsmodel.setRootPath(self.local_path)
        self.local_tree = QtGui.QTreeView()
        self.local_tree.setModel(self.fsmodel)
        self.local_tree.setWhatsThis(info)
        self.local_tree.setToolTip(info)
        self.local_tree.selectionModel().currentChanged.connect(
            self._local_item_changed)
        self.grid.addWidget(self.local_tree, 1, 0, 1, 2)

        self.mid_grid = QtGui.QVBoxLayout()

        info = "Choose the remote machine to explore"
        self.b_remote = QtGui.QToolButton()
        self.b_remote.setWhatsThis(info)
        self.b_remote.setToolTip(info)
        self.b_remote.clicked.connect(self._choose_remote)
        self.mid_grid.addWidget(self.b_remote)

        info = "Copy from local machine to remote machine"
        self.b_get = QtGui.QToolButton()
        self.b_get.setWhatsThis(info)
        self.b_get.setToolTip(info)
        self.b_remote.clicked.connect(self._get_file)
        self.mid_grid.addWidget(self.b_get)

        info = "Copy from remote machine to local machine"
        self.b_put = QtGui.QToolButton()
        self.b_put.setWhatsThis(info)
        self.b_put.setToolTip(info)
        self.b_remote.clicked.connect(self._put_file)
        self.mid_grid.addWidget(self.b_put)

        spat = QtGui.QSpacerItem(10, 10,
                                 QtGui.QSizePolicy.Minimum,
                                 QtGui.QSizePolicy.Expanding)
        self.mid_grid.addItem(spat)

        self.grid.addLayout(self.mid_grid, 0, 2, 2, 1)

        info = "The path on remote machine"
        self.lbl_remote = QtGui.QLabel('Remote path')
        self.lbl_remote.setWhatsThis(info)
        self.lbl_remote.setToolTip(info)
        self.grid.addWidget(self.lbl_remote, 0, 3, 1, 1)
        self.le_remote = QtGui.QLineEdit()
        self.le_remote.setWhatsThis(info)
        self.le_remote.setToolTip(info)
        self.le_remote.setText('')
        self.grid.addWidget(self.le_remote, 0, 4, 1, 1)

        info = "Files and folders on remote machine"
        self.remote_tree = QtGui.QTreeWidget()
        self.remote_tree.setWhatsThis(info)
        self.remote_tree.setToolTip(info)
        self.remote_tree.currentItemChanged.connect(self._remote_item_changed)
        self.remote_tree.setHeaderLabels(['Name', 'Type', 'Size',
                                          'Date modified'])
        self.grid.addWidget(self.remote_tree, 1, 3, 1, 2)

    def _choose_remote(self):
        """
        Slot allowing to change the remote machine.
        """
        main_win = Remote()
        main_win.setWindowTitle('Choose the connection parameters')
        if main_win.exec_():
            self.remote = main_win.get()
            self.change_remote(main_win.get())

    def _get_file(self):
        """
        Slot allowing to copy a file from the remote machine.
        """
        pass

    def _put_file(self):
        """
        Slot allowing to copy a file to the remote machine.
        """
        pass

    def _local_item_changed(self, current, previous):
        """
        Slot informed that current file changed.
        """
        if current is None:
            self.le_local.setText('')
        else:
            self.le_local.setText(self.fsmodel.filePath(current))

    def _local_select(self):
        """
        Change current item in local tree.
        """
        self.change_local_path(self.le_local.text())

    def _remote_item_changed(self, current, previous):
        """
        Slot informed that current file changed.
        """
        #if current is None:
        #    self.le_remote.setText('')
        #else:
        #    self.le_remote.setText(self.fsmodel.filePath(current))

    def closeEvent(self, event):
        """
        Build-in close event.
        """
        self.settings.setValue('RemoteBrowse/pos', self.pos())
        self.settings.setValue('RemoteBrowse/size', self.size())

        del self.settings
        event.accept()

    def change_remote(self, remote):
        """
        Change the remote that we're browsing.
        """
        if not self.remote is None:
            self.remote.deactivate()
        self.remote = remote
        if not self.remote is None:
            self.remote.activate()

        b_ok = self.remote.test_connection()
        self.b_get.setEnabled(b_ok)
        self.b_put.setEnabled(b_ok)
        self.lbl_remote.setEnabled(b_ok)
        self.le_remote.setEnabled(b_ok)
        self.remote_tree.setEnabled(b_ok)

        if b_ok:
            self.change_remote_path(self.remote.cwd)
        else:
            self.le_remote.setText('')

    def change_remote_path(self, rpath):
        """
        Change the remote path that we're seeing.
        """
        self.remote.cwd = rpath
        self.le_remote.setText(rpath)

    def change_local_path(self, lpath):
        """
        Change the remote path that we're seeing.
        """
        midx = self.fsmodel.index(lpath)
        if midx.isValid():
            self.local_tree.setCurrentIndex(midx)
            self.local_tree.scrollTo(midx)

def main():
    """
    Test app to run from command line.
    """

    #COMPANY = "pyl2extra"
    #DOMAIN = "pyl2extra.org"
    app_name = "Remote Explorer"

    app = QtGui.QApplication(sys.argv)
    #app.setWindowIcon(QtGui.QIcon(":/icon.png"))

    main_win = RemoteBrowse()
    main_win.setWindowTitle(app_name)
    main_win.show()

    sys.exit(app.exec_())

if __name__ == '__main__':
    main()


class Solution:
    def maxProduct(self, words):
        """
        :type words: List[str]
        :rtype: int
        """
        max_len = {}

        max_product = 0

        ord_a = ord('a')

        for word in words:
            mask = 0
            for char in word:
                mask |= 1 << (ord(char) - ord_a)

            max_len[mask] = max(max_len.get(mask, 0), len(word))

            for key, val in max_len.items():
                if not (mask & key):
                    max_product = max(max_product, len(word) * val)

        return max_product


from django.test import TestCase

from old.controller.servicios import tfg_services
from model.models import Profesor

class TfgServicesTests(TestCase):
    def setUp(self):

        self.prof1_username = 'ejemplo@ugr.es'
        self.prof1_nombre = 'alumno 1'
        self.prof1_apellidos = 'apellido 1 apellido 12'
        self.prof1_departamento = 'departamento 1'

        self.otro_username = 'ejemplo2@ugr.es'
        self.otro_nombre = 'profesor 2'
        self.otro_apellidos = 'apellido 2 apellido 22'
        self.otro_departamento = 'otro departamento'

        self.prof1 = tfg_services.insert_profesor(Profesor(username=self.prof1_username, first_name=self.prof1_nombre,
                                                           last_name=self.prof1_apellidos,
                                                           departamento=self.prof1_departamento))

    def test_delete_profesor_no_existe(self):

        otro_profesor = Profesor(username=self.otro_username, first_name=self.otro_nombre,
                                                         last_name=self.otro_apellidos,
                                                         departamento=self.otro_departamento)
        result = tfg_services.delete_profesor(otro_profesor)
        self.assertEqual(result['status'], False)

    def test_delete_profesor_existe(self):

        profesor = Profesor.objects.get(username=self.prof1_username)
        result = tfg_services.delete_profesor(profesor)
        self.assertEqual(result['status'], True)


import re
from string import punctuation
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
import pymorphy2

def read_doc(text_name):
    result = []
    path = 'C:/Users/57thr/Documents/GitHub/uni_stuff/Year_3/ITvPS/laba8/лаба_8/' + text_name + '.txt'
    string = ""
    f = open(path)
    for line in f.readlines():
        string += line
    all_docs = re.split(r'[\n]+', string)
    sentence = re.split(r'\.', string)
    for par in all_docs:
        if par != "":
            result.append(par)
    return result, sentence

def preprocessing_data(text):
    stop_words = set(stopwords.words('russian') + list(punctuation))
    morph = pymorphy2.MorphAnalyzer()
    text = text.lower()
    text = re.sub('[^а-яА-Я]', ' ', text, flags=re.MULTILINE)
    tokens = word_tokenize(text)
    text = [word for word in tokens if word not in stop_words]
    text = [morph.parse(word)[0].normal_form for word in text]
    text = ' '.join(text)
    return text

def create_dict(text):
    text_dict = {}
    join_text = ' '.join(text)
    for word in join_text.split():
        if word not in text_dict:
            text_dict[word] = join_text.count(word) * sum([1.0 for par in text if word in par]) / (
                        len(text) * len(join_text.split()))
    return text_dict, len(text), len(join_text.split())

def key_words(text_dict, text):
    result = []
    words = ' '.join(text).split()
    for i in range(len(words) - 1):
        if (text_dict[words[i]][1] == "ГОС" or text_dict[words[i]][1] == "ВОС") and text_dict[words[i + 1]][
            1] == "ГОС" or text_dict[words[i + 1]][1] == "ВОС":
            result.append(words[i] + " " + words[i + 1])
    for i in range(len(words) - 2):
        if (text_dict[words[i]][1] == "ГОС" or text_dict[words[i]][1] == "ВОС") and text_dict[words[i + 1]][
            1] == "ГОС" or text_dict[words[i + 1]][1] == "ВОС" and text_dict[words[i + 2]][1] == "ГОС" or \
                text_dict[words[i + 2]][1] == "ВОС":
            result.append(words[i] + " " + words[i + 1] + " " + words[i + 2])
    print(result)
    return result

def key_sentences(text_dict, sentences):
    result = {}
    for s in sentences:
        for ws in preprocessing_data(s).split():
            count = 0
            for i in text_dict.keys():
                if i == ws and i != "Н":
                    count += 1
            result[count / len(set(preprocessing_data(s).split()))] = s
    return result

for i in range(3,):
    text, sentences = read_doc("text_" + str(i))
    text = [preprocessing_data(i) for i in text]
    sentences = [preprocessing_data(i) for i in sentences]
    text_dict, n, N = create_dict(text)
    for word, val in text_dict.items():
        if 9 / (n * N) <= val < 1:
            text_dict[word] = [val, "ГОС"]
        elif ((1 + n / 4) ** 2) / (n * N) <= val < 9 / (n * N):
            text_dict[word] = [val, "ВОС"]
        else:
            text_dict[word] = [val, "Н"]

    print("===============================Текст " + str(i) + "========================================")
    print("______________________________")
    print("1. Ключевые слова + ГОС/ВОС/Н")
    for i, v in text_dict.items():
        print(i, v)

    print("______________________________")
    print("2. Ключевые понятия.")
    key_words(text_dict, text)

    print("______________________________")
    print("3. Реферат на 3 предложения + индекс релевантности. ")
    key_s = key_sentences(text_dict, sentences)
    list_keys = list(key_s.keys())
    list_keys.sort(reverse=True)
    for i in list_keys[:4]:
        print(i, ':', key_s[i])


transacoes = []
saldo = 0
saques_diarios = 0
saques_registrados = []

def deposito(valor):
    global saldo
    if valor > 0:
        saldo += valor
        transacoes.append(f'Depósito: R$ {valor:.2f}')
        print(
            f'Depósito de R$ {valor:.2f} realizado. Novo saldo: R$ {saldo:.2f}')

def saque(valor):
    global saldo
    if saldo >= valor and saques_diarios < 3 and valor <= 500:
        saldo -= valor
        saques_diarios += 1
        transacoes.append(f'Saque: R$ {valor:.2f}')
        print(f'Saque de R$ {valor:.2f} realizado. Novo saldo: R$ {saldo:.2f}')
    elif saldo < valor:
        print('Saldo insuficiente para o saque.')
    elif saques_diarios >= 3:
        print('Limite diário de saques atingido.')
    elif valor > 500:
        print('Limite máximo de R$ 500,00 por saque.')

def extrato():
    print('Extrato:')
    if not transacoes:
        print('Não foram realizadas movimentações.')
    else:
        for transacao in transacoes:
            print(transacao)
    print(f'Saldo atual: R$ {saldo:.2f}')

# Função para exibir o menu e realizar as interações

def exibir_menu():
    print('----- Menu -----')
    print('1. Realizar depósito')
    print('2. Realizar saque')
    print('3. Exibir extrato')
    print('4. Sair')
    print()

# Exemplo de uso das operações com o menu
saldo_inicial = float(input('Digite o saldo inicial: '))
saldo = saldo_inicial

while True:
    exibir_menu()
    opcao = input('Selecione uma opção: ')

    if opcao == '1':
        valor = float(input('Digite o valor do depósito: '))
        deposito(valor)
    elif opcao == '2':
        valor = float(input('Digite o valor do saque: '))
        saque(valor)
    elif opcao == '3':
        extrato()
    elif opcao == '4':
        print('Encerrando o programa...')
        break
    else:
        print('Opção inválida. Por favor, selecione novamente.')
    print()


# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

def solve(r,k):
    x = TreeNode(k)
    ans = r
    if(not r):
        return x
    while(r and (r.left or r.right) ):
        if(r.val < k):
            if(r.right):
                r = r.right
            else:
                r.right = x
                return ans
        else:
            if(r.left):
                r = r.left
            else:
                r.left = x
                return ans
    if(r.val < k):
        r.right = x
    else:
        r.left = x
    return ans

class Solution:
    def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:
        return solve(root,val)


import torch
from utils import save_checkpoint, save_some_examples
import config
from achitecture import Generator
import torch.nn as nn
from dataset_generator import MapDataset
from torch.utils.data import DataLoader
from tqdm import tqdm

dataset = MapDataset()
data_loader = DataLoader(dataset, batch_size=config.BATCH_SIZE, shuffle=True)

model = Generator().to(config.DEVICE)
optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)
criterion = torch.nn.L1Loss()
l_scaler = torch.cuda.amp.GradScaler()
save_some_examples(model, data_loader, 'evaluations')

for epochs in range(config.EPOCHS):
    for idx, (x, y) in tqdm(enumerate(data_loader)):
        x = x.permute((0, 3, 1, 2))
        y_fake = model(x)

        loss = criterion(y_fake, y.permute((0, 3, 1, 2)))

        l_scaler.scale(loss)
        loss.backward()
        l_scaler.step(optimizer)
        l_scaler.update()
        optimizer.zero_grad()

    if epochs % 10 == 0 :
        save_checkpoint(model, optimizer, 'generator.pth.tar')
        save_some_examples(model, data_loader, epochs, 'evaluations')


from django import forms
from .models import Auction,Comment,Bid,Category

class AuctionForm(forms.ModelForm):
    class Meta:
        model = Auction
        exclude = ('user','status',)
        widgets = {
            'title': forms.TextInput(attrs={'class': 'form-control form-control-user','placeholder' :'Enter Title...'}),
            'description': forms.Textarea(attrs={'class': 'form-control form-control-user','placeholder' :'Enter Description...','rows':5}),
            'start_bid': forms.NumberInput(attrs={'class':'form-control form-control-user','placeholder':'0'}),
            'image_url': forms.URLInput(attrs={'class':'form-control form-control-user'}),
            'category' : forms.Select(attrs={'class':'form-control'})
        }

class CommentForm(forms.ModelForm):
    class Meta:
        model = Comment
        exclude = ('user','auction')
        widgets = {
            'message': forms.Textarea(attrs={'class':'form-control form-control-user','placeholder':'Write your comment','rows':5})
        }

class BidForm(forms.ModelForm):
    class Meta:
        model = Bid
        exclude = ('user','auction','won')
        widgets = {
            'price': forms.NumberInput(attrs={'class':'form-control form-control-user','placeholder':'0'})
        }

class CategoryForm(forms.Form):
    categories = forms.ChoiceField(choices=[(cat.pk,cat.name) for cat in Category.objects.all()],widget=forms.RadioSelect(attrs={'class':'form-check-input'}))


# importing the libraries
import numpy as np
import matplotlib as plt
import pandas as pd

# data pre-preocessing
dataset = pd.read_csv('50_Startups.csv')
X = dataset.iloc[:, :-1].values  #independent feature matrix
y = dataset.iloc[: , 4].values  #dependent feature matrix

# Encoding the categorical data
from sklearn.preprocessing import LabelEncoder , OneHotEncoder
labelencoder_X = LabelEncoder()
X[:, 3] = labelencoder_X.fit_transform(X[:,3])
# One hot Encoding
onehotencoder = OneHotEncoder(categorical_features = [3])
X = onehotencoder.fit_transform(X).toarray()

# Avoiding the dummy variable trap
# Although most libraries do it
# Still we are doing it to be double sure in case if some doesn't do!!
X = X[: , 1:]

# Training and splitting the dataset
from sklearn.cross_validation import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X,y, test_size=0.2,  random_state=0)

# Fitting multiple regression to training set
from sklearn.linear_model import LinearRegression
regressor = LinearRegression()
regressor.fit(X_train,y_train)

# Predicting the test results
y_pred = regressor.predict(X_test)

# Building the optimal model using the backward elimination (fastest method)
# We include only those independent variables which greatly affect the dependent variable
import statsmodels.formula.api as sm
# bcz of the constant b0 and x0=1 we need to add a column of 1s
# So we are appending our matrix to 1's column
# bcz we need 1's column in the begining
X = np.append(arr=np.ones((50,1)).astype(int), values=X, axis=1)
X_opt = X[: , [0,1,2,3,4,5]]
regressor_OLS = sm.OLS(endog=y , exog= X_opt).fit()
regressor_OLS.summary()
# OLS = Ordinary least square
# now eliminate the column with highest p value
# Again train the model
# Repeat untill all values are less than significance level
X_opt = X[: , [0,1,3,4,5]]
regressor_OLS = sm.OLS(endog=y , exog= X_opt).fit()
regressor_OLS.summary()
X_opt = X[: , [0,3,4,5]]
regressor_OLS = sm.OLS(endog=y , exog= X_opt).fit()
regressor_OLS.summary()
X_opt = X[: , [0,3,5]]
regressor_OLS = sm.OLS(endog=y , exog= X_opt).fit()
regressor_OLS.summary()
X_opt = X[: , [0,3]]
regressor_OLS = sm.OLS(endog=y , exog= X_opt).fit()
regressor_OLS.summary()

Machine Learning A-Z Template Folder/Part 2 - Regression/Section 5 - Multiple Linear Regression/multiple_linear_regression.py


# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

from marionette_harness import MarionetteTestCase

class TestWindowMaximize(MarionetteTestCase):
    def setUp(self):
        MarionetteTestCase.setUp(self)
        self.max = self.marionette.execute_script(
            """
            return {
              width: window.screen.availWidth,
              height: window.screen.availHeight,
            }""",
            sandbox=None,
        )

        # ensure window is not maximized
        self.marionette.set_window_rect(
            width=self.max["width"] - 100, height=self.max["height"] - 100
        )
        actual = self.marionette.window_rect
        self.assertNotEqual(actual["width"], self.max["width"])
        self.assertNotEqual(actual["height"], self.max["height"])

        self.original_size = actual

    def tearDown(self):
        self.marionette.set_window_rect(
            width=self.original_size["width"], height=self.original_size["height"]
        )

    def test_maximize(self):
        self.marionette.maximize_window()


import MapReduce
import sys
import itertools

mr = MapReduce.MapReduce()

# Part 2
def mapper(record):
    personA = record[0]
    personB = record[1]
    friends = [personB]
    mr.emit_intermediate(personA, friends)

# Part 3
def reducer(key, list_of_values):
    friends_count = len(list(itertools.chain(*list_of_values)))
    mr.emit((key, friends_count))

# Part 4
inputdata = open(sys.argv[1])
mr.execute(inputdata, mapper, reducer)


import datetime
from pathlib import Path
from shutil import copy2 as copy

import mac_tag
import applescript
from peewee import *

DB = SqliteDatabase('DocumentWallet.documentwalletsql')
OUT_PATH = "doc_output"

class BaseModel(Model):
    class Meta:
        database = DB

class Category(BaseModel):
    pk = IntegerField(primary_key=True, column_name='Z_PK')
    name = CharField(column_name='ZNAME')

    class Meta:
        table_name = 'ZCATEGORY'

class SubCategory(BaseModel):
    pk = IntegerField(primary_key=True, column_name='Z_PK')
    name = CharField(column_name='ZNAME')

    class Meta:
        table_name = 'ZSUBCATEGORY'

class Receipt(BaseModel):
    pk = IntegerField(primary_key=True, column_name='Z_PK')
    merchant = CharField(column_name='ZMERCHANT')
    notes = TextField(column_name='ZNOTES')
    path = CharField(column_name='ZPATH')
    category = ForeignKeyField(Category, column_name="ZCATEGORY")
    subcategory = ForeignKeyField(SubCategory, column_name="ZSUBCATEGORY")

    class Meta:
        table_name = 'ZRECEIPT'

class Tag(BaseModel):
    pk = IntegerField(primary_key=True, column_name='Z_PK')
    name = CharField(column_name='ZNAME')

    class Meta:
        table_name = 'ZTAG'

class ReceiptTag(BaseModel):
    receipt = ForeignKeyField(Receipt, column_name="Z_14RECEIPTS1", backref="receipt_tags")
    tag = ForeignKeyField(Tag, column_name="Z_18TAGS", backref="receipt_tags")

    class Meta:
        table_name = 'Z_14TAGS'
        primary_key = False

def file_name(index, receipt):
    if receipt.merchant.strip():
        return f"{index}-{receipt.merchant.strip()}.pdf"
    try:
        return f"{index}-{receipt.category.name}.pdf"
    except Category.DoesNotExist:
        return f"{index}-no-name.pdf"

def create_out_dir(dir_path):
    Path(dir_path).mkdir(parents=True, exist_ok=True)

def collect_tags(receipt):
    tags = []
    try:
        tags.append(receipt.category.name.lower())
    except Category.DoesNotExist:
        pass
    try:
        tags.append(receipt.subcategory.name.lower())
    except SubCategory.DoesNotExist:
        pass

    for rtag in receipt.receipt_tags:
        tags.append(rtag.tag.name.strip().lower())

    return set(tags)

def set_comment(file_path, comment_text):
    applescript.tell.app("Finder", f'set comment of (POSIX file "{file_path}" as alias) to "{comment_text}" as Unicode text')

def run():
    create_out_dir(OUT_PATH)
    query = Receipt.select(Receipt)

    for index, receipt in enumerate(query):
        _file_name = file_name(index, receipt)
        print(f"#{index} " + _file_name)

        new_path = "/".join([OUT_PATH, _file_name])
        copy(receipt.path, new_path)

        if receipt.notes:
            notes = receipt.notes.strip()
            set_comment(new_path, notes)
            print(f"\tNotes:\n\t{notes}")

        tags = collect_tags(receipt)

        mac_tag.update(tags,[new_path])

        print("\tTags added:")
        for tag in tags:
            print(f"\t - {tag}")

if __name__ == "__main__":
    run()


"""Validate sphinx-emf config with pydantic."""

import sys
from typing import Callable, Dict, List

from pydantic import ValidationError

def validate_config(confpy, logger, pydantic_class):
    """Run pydantic on emf_* fields of conf.py."""
    allowed_types = (int, str, List, Dict, Callable)
    all_fields = dir(confpy)
    emf_fields = {}
    for field in all_fields:
        if field.startswith("emf_"):
            value = getattr(confpy, field)
            if isinstance(value, (allowed_types)):
                emf_fields[field] = value
    try:
        config = pydantic_class(**emf_fields)
    except ValidationError as exc:
        logger.error("Config validation failed")
        logger.error(exc)
        sys.exit(1)
    logger.info("Config validation successful")
    return config


import unittest
from itertools import zip_longest

import numpy as np
import pandas as pd

from base_types import ExcelConstants, CellValue, CellPosition, CellOffset, ExcelCell, NeighborCell, \
    NeighborsContainer, CellOffsetAction, Indexes
from value_finders import ExactValueFinder, ExactValuesFinder, RegexFinder, StartWithFinder, EndWithFinder
from position_finders import FirstRowNumFinder, FirstColNumFinder, FirstCellPositionFinder, AllRowNumsFinder, \
    AllCellPositionsFinder, AllColNumsFinder
from data import simple_data, duplicates_data

class TestTDS(unittest.TestCase):
    def setUp(self):
        self.simple_df = pd.DataFrame.from_dict(data=simple_data['data'], columns=simple_data['columns'],
                                                orient='index')
        self.duplicates_df = pd.DataFrame.from_dict(data=duplicates_data['data'], columns=duplicates_data['columns'],
                                                    orient='index')

    @unittest.skip
    def test_cell_position(self):
        cells_offsets_results = [
            (CellOffset(col=-1, row=-1), CellPosition(col=0, row=0)),
            (CellOffset(col=0, row=-1), CellPosition(col=1, row=0)),
            (CellOffset(col=1, row=-1), CellPosition(col=2, row=0)),
            (CellOffset(col=1, row=0), CellPosition(col=2, row=1)),
            (CellOffset(col=1, row=1), CellPosition(col=2, row=2)),
            (CellOffset(col=0, row=1), CellPosition(col=1, row=2)),
            (CellOffset(col=-1, row=1), CellPosition(col=0, row=2)),
            (CellOffset(col=-1, row=0), CellPosition(col=0, row=1)),
            (CellOffset(col=0, row=0), CellPosition(col=1, row=1)),
            (CellOffset(col=-2, row=-2), CellPosition(col=-1, row=-1)),
            (CellOffset(col=1, row=-2), CellPosition(col=2, row=-1)),
            (CellOffset(col=-2, row=1), CellPosition(col=-1, row=2)),
        ]
        for cell_offset, result_cell_position in cells_offsets_results:
            self.assertEqual(CellPosition(col=1, row=1) + cell_offset, result_cell_position)

        cells_positions_results = [
            (CellPosition(col=1, row=1), CellPosition(col=2, row=2)),
            (CellPosition(col=2, row=2), CellPosition(col=3, row=3)),
            (CellPosition(col=1, row=2), CellPosition(col=2, row=3)),
            (CellPosition(col=2, row=1), CellPosition(col=3, row=2)),
        ]
        for cell_position, result_cell_position in cells_positions_results:
            self.assertEqual(CellPosition(col=1, row=1) + cell_position, result_cell_position)

        incomplete_cells_positions_results = [
            (CellPosition(), CellPosition(), CellPosition()),
            (CellPosition(col=1), CellPosition(col=1), CellPosition(col=2)),
            (CellPosition(row=1), CellPosition(row=1), CellPosition(row=2)),
            (CellPosition(col=1), CellPosition(row=1), CellPosition(col=1, row=1)),
            (CellPosition(col=1, row=1), CellPosition(row=1), CellPosition(col=1, row=2)),
            (CellPosition(col=1, row=1), CellPosition(col=1), CellPosition(col=2, row=1)),
        ]
        for first_cell_position, second_cell_position, result_cell_position in incomplete_cells_positions_results:
            self.assertEqual(first_cell_position + second_cell_position, result_cell_position)

        self.assertTrue(CellPosition(col=1))
        self.assertTrue(CellPosition(row=1))
        self.assertTrue(CellPosition(col=1, row=1))
        self.assertFalse(CellPosition())
        self.assertEqual(CellPosition(), CellPosition())
        self.assertNotEqual(CellPosition(), CellPosition(col=1))
        self.assertNotEqual(CellPosition(), CellPosition(row=1))
        self.assertNotEqual(CellPosition(), CellPosition(col=1, row=1))

    @unittest.skip
    def test_cell_rownum_finder(self):
        cell_values_results = [
            (CellValue('SKU'), CellPosition(row=0)),
            (CellValue('*ГЛИЦИН-КАНОН ТБ ПОДЪЯЗЫЧ 1000 МГ №10'), CellPosition(row=5)),
            (CellValue(7458), CellPosition(row=10)),
            (CellValue(274254), CellPosition(row=15)),
            (CellValue(234637), CellPosition(row=20)),
            (CellValue(3012), CellPosition(row=25)),
            (CellValue('Общий итог'), CellPosition(row=0)),
            (CellValue('Qwerty'), CellPosition()),
            (CellValue(-999), CellPosition()),
        ]
        finder = FirstRowNumFinder(df=self.simple_df)
        for cell_value, result_position in cell_values_results:
            finder.value_finder = ExactValueFinder(cell_value=cell_value)
            self.assertEqual(finder.get_position(), result_position)

    @unittest.skip
    def test_cell_colnum_finder(self):
        cell_values_results = [
            (CellValue('SKU'), CellPosition(col=0)),
            (CellValue(2012), CellPosition(col=1)),
            (CellValue(2013), CellPosition(col=2)),
            (CellValue(2014), CellPosition(col=3)),
            (CellValue(2015), CellPosition(col=4)),
            (CellValue(2016), CellPosition(col=5)),
            (CellValue('Общий итог'), CellPosition(col=0)),
            (CellValue('Qwerty'), CellPosition()),
            (CellValue(-999), CellPosition()),

        ]
        finder = FirstColNumFinder(df=self.simple_df)
        for cell_value, result_positions in cell_values_results:
            finder.value_finder = ExactValueFinder(cell_value)
            self.assertEqual(finder.get_position(), result_positions)

    @unittest.skip
    def test_cell_position_finder(self):
        cell_values_results = [
            (CellValue('SKU'), CellPosition(col=0, row=0)),
            (CellValue('Общий итог'), CellPosition(col=6, row=0)),
            (CellValue(7458), CellPosition(col=1, row=10)),
            (CellValue(6059), CellPosition(col=5, row=16)),
            (CellValue('ЭКСХОЛ КАПС 250 МГ №10'), CellPosition(col=0, row=197)),
            (CellValue(105153489.25), CellPosition(col=6, row=204)),
        ]
        finder = FirstCellPositionFinder(df=self.simple_df)
        for cell_value, result_position in cell_values_results:
            finder.value_finder = ExactValueFinder(cell_value)
            self.assertEqual(finder.get_position(), result_position)

    @unittest.skip
    def test_excell_cell(self):
        self.assertEqual(ExcelCell(cell_name='A1').cell_position, CellPosition(col=0, row=0))
        excell_cell = ExcelCell(cell_name='b2')
        self.assertEqual(excell_cell.cell_position, CellPosition(col=1, row=1))
        self.assertLessEqual(ExcelCell(cell_name='A1'), ExcelCell(cell_name='B1'))
        self.assertLessEqual(ExcelCell(cell_name='A1'), ExcelCell(cell_name='A2'))
        self.assertLess(ExcelCell(cell_name='A1'), ExcelCell(cell_name='B2'))
        self.assertEqual(ExcelCell(cell_name='A1'), ExcelCell(cell_name='A1'))

        cells_offsets_results = [
            (CellOffset(col=-1, row=-1), ExcelCell(cell_name='A1')),
            (CellOffset(col=0, row=-1), ExcelCell(cell_name='B1')),
            (CellOffset(col=1, row=-1), ExcelCell(cell_name='C1')),
            (CellOffset(col=1, row=0), ExcelCell(cell_name='C2')),
            (CellOffset(col=1, row=1), ExcelCell(cell_name='C3')),
            (CellOffset(col=0, row=1), ExcelCell(cell_name='B3')),
            (CellOffset(col=-1, row=1), ExcelCell(cell_name='A3')),
            (CellOffset(col=-1, row=0), ExcelCell(cell_name='A2')),
            (CellOffset(col=0, row=0), ExcelCell(cell_name='B2')),
        ]
        for cell_offset, result_excell_cell in cells_offsets_results:
            self.assertEqual(ExcelCell(cell_name='B2') + cell_offset, result_excell_cell)

        self.assertRaises(Exception, ExcelCell, cell_name='b2c')
        self.assertRaises(Exception, ExcelCell, cell_name='2c')
        self.assertRaises(Exception, ExcelCell, cell_name='b')
        self.assertRaises(Exception, ExcelCell, cell_name='1')
        self.assertRaises(Exception, ExcelCell, cell_name='a@')
        self.assertRaises(Exception, ExcelCell, cell_name='a1-')
        self.assertRaises(Exception, ExcelCell, cell_name='aaaaa1')
        self.assertRaises(Exception, ExcelCell, cell_name='ш1')
        self.assertRaises(Exception, ExcelCell, cell_name='a' + str(ExcelConstants.MAX_EXCEL_ROWS_COUNT + 10))

    @unittest.skip
    def test_all_row_nums_finder(self):
        finder = AllRowNumsFinder(df=self.duplicates_df)
        cell_values_results = [
            (
                CellValue('*АРИТЕЛ ПЛЮС ТБ П/О 2,5МГ+6,25МГ №30'),
                [CellPosition(row=1), CellPosition(row=3)]
            ),
            (
                CellValue(1099),
                [CellPosition(row=2), CellPosition(row=7), CellPosition(row=9)]
            ),
            (
                CellValue(''),
                [CellPosition(row=1), CellPosition(row=5), CellPosition(row=12)]
            ),
            (
                CellValue(),
                [CellPosition(row=1), CellPosition(row=5), CellPosition(row=12)]
            ),
            (
                CellValue(0),
                [CellPosition(row=counter) for counter in range(1, 11)]
            ),
            (CellValue('Qwerty'), []),
            (CellValue(-999), [])
        ]
        for cell_value, expected_result_positions in cell_values_results:
            finder.value_finder = ExactValueFinder(cell_value=cell_value)
            fact_result_positions = finder.get_all_positions()
            self.assertEqual(len(expected_result_positions), len(fact_result_positions))
            if fact_result_positions:
                zip_result = zip_longest(fact_result_positions, expected_result_positions)
                for fact_position, expected_position in zip_result:
                    self.assertEqual(fact_position, expected_position)
            else:
                self.assertEqual(fact_result_positions, expected_result_positions)
                self.assertEqual(fact_result_positions, cell_values_results[-1][1])

    @unittest.skip
    def test_all_col_nums_finder(self):
        finder = AllColNumsFinder(df=self.duplicates_df)
        cell_values_results = [
            (
                CellValue('Общий итог'),
                [CellPosition(col=0), CellPosition(col=6)]
            ),
            (
                CellValue(2256),
                [CellPosition(col=1), CellPosition(col=6)]
            ),
            (
                CellValue(''),
                [
                    CellPosition(col=0),
                    CellPosition(col=1),
                    CellPosition(col=2),
                    CellPosition(col=3),
                    CellPosition(col=4),
                    CellPosition(col=5),
                    CellPosition(col=6),
                ]
            ),
            (
                CellValue(),
                [
                    CellPosition(col=0),
                    CellPosition(col=1),
                    CellPosition(col=2),
                    CellPosition(col=3),
                    CellPosition(col=4),
                    CellPosition(col=5),
                    CellPosition(col=6),
                ]
            ),
            (
                CellValue(0),
                [CellPosition(col=counter) for counter in range(2, 6)]
            ),
            (CellValue('Qwerty'), []),
            (CellValue(-999), [])
        ]
        for cell_value, expected_result_positions in cell_values_results:
            finder.value_finder = ExactValueFinder(cell_value=cell_value)
            fact_result_positions = finder.get_all_positions()
            if fact_result_positions:
                zip_result = zip_longest(fact_result_positions, expected_result_positions)
                for fact_position, expected_position in zip_result:
                    self.assertEqual(fact_position, expected_position)
            else:
                self.assertEqual(fact_result_positions, expected_result_positions)
                self.assertEqual(fact_result_positions, cell_values_results[-1][1])

    @unittest.skip
    def test_neighbor(self):
        data_set = [
            (CellPosition(col=0, row=0), CellValue(4302), CellOffset(col=1, row=1), True),
            (CellPosition(col=1, row=1), CellValue('SKU'), CellOffset(col=-1, row=-1), True),
            (CellPosition(col=1, row=1), CellValue(2012), CellOffset(col=0, row=-1), True),
            (CellPosition(col=1, row=1), CellValue(2013), CellOffset(col=1, row=-1), True),
            (CellPosition(col=1, row=1), CellValue(5987), CellOffset(col=1, row=0), True),
            (CellPosition(col=1, row=1), CellValue(3143), CellOffset(col=1, row=1), True),
            (CellPosition(col=1, row=1), CellValue(1099), CellOffset(col=0, row=1), True),
            (
                CellPosition(col=1, row=1),
                CellValue('*АРИТЕЛ ПЛЮС ТБ П/О 5МГ+6,25МГ №30'),
                CellOffset(col=-1, row=1),
                True
            ),
            (
                CellPosition(col=1, row=1),
                CellValue('*АРИТЕЛ ПЛЮС ТБ П/О 2,5МГ+6,25МГ №30'),
                CellOffset(col=-1, row=0),
                True
            ),
            (CellPosition(col=1, row=1), CellValue(4302), CellOffset(col=0, row=0), True),
            (CellPosition(col=0, row=0), CellValue(1), CellOffset(col=1, row=1), False),
        ]
        for cell_position, cell_value, cell_offset, result in data_set:
            neighbor = NeighborCell(df=self.simple_df, cell_value=cell_value, cell_offset=cell_offset)
            self.assertEqual(neighbor.is_neighbor(cell_position), result)

    @unittest.skip
    def test_cell_value(self):
        cell_values_numbers_results = [
            (CellValue(1), CellValue(1)),
            (CellValue(0), CellValue(0)),
            (CellValue(1.0), CellValue(1)),
            (CellValue(0.1), CellValue(0.1)),
            (CellValue(0.10), CellValue(0.1)),
            (CellValue(0.100), CellValue(0.1)),
            (CellValue(0.1000), CellValue(0.1)),
            (CellValue(0.10000), CellValue(0.1)),
            (CellValue(0.100000), CellValue(0.1)),
            (CellValue(0.1000000), CellValue(0.1)),
            (CellValue(0.10000000), CellValue(0.1)),
            (CellValue(0.100000000), CellValue(0.1)),
            (CellValue(0.1000000000), CellValue(0.1)),
            (CellValue(0.11), CellValue(0.11)),
            (CellValue(0.111), CellValue(0.111)),
            (CellValue(0.1111), CellValue(0.1111)),
            (CellValue(0.11111), CellValue(0.11111)),
            (CellValue(0.111111), CellValue(0.111111)),
            (CellValue(0.1111111), CellValue(0.1111111)),
            (CellValue(0.11111111), CellValue(0.11111111)),
            (CellValue(0.111111111), CellValue(0.111111111)),
            (CellValue(0.1111111111), CellValue(0.1111111111)),
            (CellValue(0.1111111111 + 0.1111111111), CellValue(0.2222222222)),
            (CellValue(1 + 1), CellValue(2)),
            (CellValue(1 + 0.11), CellValue(1.11)),
            (CellValue(1 + 0.111), CellValue(1.111)),
            (CellValue(1 + 0.1111), CellValue(1.1111)),
            (CellValue(1 + 0.11111), CellValue(1.11111)),
            (CellValue(1 + 0.111111), CellValue(1.111111)),
            (CellValue(1 + 0.1111111), CellValue(1.1111111)),
            (CellValue(1 + 0.11111111), CellValue(1.11111111)),
            (CellValue(1 + 0.111111111), CellValue(1.111111111)),
            (CellValue(1 + 0.1111111111), CellValue(1.1111111111)),
            (CellValue(1 + 0.1111111111 + 0.1111111111), CellValue(1.2222222222)),
            (CellValue(0.1 + 0.01), CellValue(0.11)),
            (CellValue(0.11 + 0.001), CellValue(0.111)),
            (CellValue(0.11 + 0.0011), CellValue(0.1111)),
            (CellValue(0.1 + 0.01111), CellValue(0.11111)),
            (CellValue(0.111 + 0.000111), CellValue(0.111111)),
            (CellValue(1 * 1.1), CellValue(1.1)),
            (CellValue(1.1 * 1.1), CellValue(1.2100000000000002)),
            (CellValue(1 / 3), CellValue(0.3333333333333333)),
            (CellValue(10.0/5.0), CellValue(2)),
        ]

        cell_values_strings_results = [
            (CellValue('Qwerty'), CellValue('Qwerty')),
            (CellValue('Qwerty '), CellValue('Qwerty ')),
            (CellValue(' Qwerty '), CellValue(' Qwerty ')),
            (CellValue(' Qwerty'), CellValue(' Qwerty')),
            (CellValue('123'), CellValue('123')),
            (CellValue('123A'), CellValue('123A')),
            (CellValue('A123A'), CellValue('A123A')),
            (CellValue('A123'), CellValue('A123')),
            (CellValue(''), CellValue('')),
            (CellValue(), CellValue('')),
            (CellValue(''), CellValue()),
            (CellValue('0'), CellValue('0')),
            (CellValue(' '), CellValue(' ')),
        ]

        for cell_value, result in cell_values_numbers_results:
            self.assertEqual(cell_value, result)
            self.assertEqual(CellValue(cell_value.value / 3), CellValue(result.value / 3))
            self.assertEqual(CellValue(-1 * cell_value.value), CellValue(-1 * result.value))
            self.assertEqual(CellValue(10 * cell_value.value), CellValue(10 * result.value))
            self.assertEqual(CellValue(-10 * cell_value.value), CellValue(-10 * result.value))

        for value in np.arange(0, 2, 0.3):
            self.assertEqual(CellValue(value), CellValue(value))
            self.assertEqual(CellValue(value * 0.1), CellValue(value * 0.1))
            self.assertEqual(CellValue(value / 3), CellValue(value / 3))
            self.assertEqual(CellValue(value + 10), CellValue(value + 10))
            self.assertEqual(CellValue(value - 999), CellValue(value - 999))

        for cell_value, result in cell_values_numbers_results:
            self.assertNotEqual(CellValue(-1 * cell_value.value + 1), CellValue(-1 * result.value))
            self.assertNotEqual(CellValue(-1 * cell_value.value + 0.1), CellValue(-1 * result.value))
            self.assertNotEqual(CellValue(10 * cell_value.value + 1), CellValue(10 * result.value))
            self.assertNotEqual(CellValue(10 * cell_value.value + 1.1), CellValue(10 * result.value))
            self.assertNotEqual(CellValue(-10 * cell_value.value + 1), CellValue(-10 * result.value))
            self.assertNotEqual(CellValue(-10 * cell_value.value + 1.1), CellValue(-10 * result.value))

        for cell_value, result in cell_values_strings_results:
            self.assertEqual(cell_value, result)
            str_val = str(cell_value)
            self.assertEqual(CellValue('' + str_val), CellValue('' + str_val))
            self.assertEqual(CellValue('' + str_val + ''), CellValue('' + str_val + ''))
            self.assertEqual(CellValue(str_val + ''), CellValue(str_val + ''))
            self.assertEqual(CellValue(str_val.replace('e', '\n')), CellValue(str_val.replace('e', '\n')))
            self.assertEqual(CellValue(str_val.replace('e', '\t')), CellValue(str_val.replace('e', '\t')))
            self.assertEqual(CellValue(str_val.replace('e', ' ')), CellValue(str_val.replace('e', ' ')))

        # Проверка оператора "in"
        cell_values = [
            CellValue(0),
            CellValue(0.1),
            CellValue(-0.1),
            CellValue(1),
            CellValue(-1),
            CellValue(1.1),
            CellValue(-1.1),
            CellValue('A'),
            CellValue(),
            CellValue(''),
        ]
        for ind in range(len(cell_values)):
            self.assertIn(cell_values[ind], cell_values)
        self.assertNotIn(CellValue(999), cell_values)
        self.assertNotIn(CellValue(-999), cell_values)
        self.assertNotIn(CellValue('Qwerty'), cell_values)

        self.assertTrue(CellValue('A'))
        self.assertTrue(CellValue(' '))
        self.assertTrue(CellValue(1))

        self.assertFalse(CellValue())
        self.assertFalse(CellValue(''))

        # TODO: datetime, datetime + timezone, time, 1E+4, 1.1 != '1.1'

    @unittest.skip
    def test_all_positions(self):
        cell_values_results = [
            (CellValue(4302), [CellPosition(col=1, row=1), CellPosition(col=1, row=3)]),
            (CellValue(2256), [CellPosition(col=1, row=8), CellPosition(col=6, row=8)]),
            (CellValue('Общий итог'), [CellPosition(col=6, row=0), CellPosition(col=0, row=11)]),
            (CellValue(-999), []),
            (CellValue('Qwerty'), []),
            (
                CellValue(''),
                [
                    CellPosition(col=6, row=1),
                    CellPosition(col=5, row=5),
                    CellPosition(col=0, row=12),
                    CellPosition(col=1, row=12),
                    CellPosition(col=2, row=12),
                    CellPosition(col=3, row=12),
                    CellPosition(col=4, row=12),
                    CellPosition(col=5, row=12),
                    CellPosition(col=6, row=12)
                ]
            ),
            (CellValue(0), [
                CellPosition(col=3, row=1),
                CellPosition(col=4, row=1),
                CellPosition(col=5, row=1),
                CellPosition(col=3, row=2),
                CellPosition(col=4, row=2),
                CellPosition(col=5, row=2),
                CellPosition(col=3, row=3),
                CellPosition(col=4, row=3),
                CellPosition(col=5, row=3),
                CellPosition(col=2, row=4),
                CellPosition(col=3, row=4),
                CellPosition(col=4, row=4),
                CellPosition(col=5, row=4),
                CellPosition(col=3, row=5),
                CellPosition(col=4, row=5),
                CellPosition(col=2, row=6),
                CellPosition(col=3, row=6),
                CellPosition(col=4, row=6),
                CellPosition(col=5, row=6),
                CellPosition(col=4, row=7),
                CellPosition(col=5, row=7),
                CellPosition(col=2, row=8),
                CellPosition(col=3, row=8),
                CellPosition(col=4, row=8),
                CellPosition(col=5, row=8),
                CellPosition(col=2, row=9),
                CellPosition(col=3, row=9),
                CellPosition(col=5, row=9),
                CellPosition(col=2, row=10),
                CellPosition(col=3, row=10),
                CellPosition(col=4, row=10),
                CellPosition(col=5, row=10),
            ])
        ]
        finder = AllCellPositionsFinder(df=self.duplicates_df)
        for cell_value, results in cell_values_results:
            finder.value_finder = ExactValueFinder(cell_value=cell_value)
            finder_results = finder.get_all_positions()
            self._check_results(expected_result=results, finder_result=finder_results)

    @unittest.skip
    def test_cell_values_finder(self):
        cell_values_results = [
            (
                [CellValue(3143), CellValue(2525)],
                [CellPosition(col=2, row=2), CellPosition(col=2, row=5), CellPosition(col=2, row=7)]
            ),
            (
                [CellValue('Общий итог'), CellValue()],
                [
                    CellPosition(col=6, row=0),
                    CellPosition(col=6, row=1),
                    CellPosition(col=5, row=5),
                    CellPosition(col=0, row=11),
                    CellPosition(col=0, row=12),
                    CellPosition(col=1, row=12),
                    CellPosition(col=2, row=12),
                    CellPosition(col=3, row=12),
                    CellPosition(col=4, row=12),
                    CellPosition(col=5, row=12),
                    CellPosition(col=6, row=12),
                ]
            ),

        ]
        finder = AllCellPositionsFinder(df=self.duplicates_df)
        for cell_values, results in cell_values_results:
            finder.value_finder = ExactValuesFinder(cell_values=cell_values)
            finder_results = finder.get_all_positions()
            self._check_results(expected_result=results, finder_result=finder_results)

    @unittest.skip
    def test_cell_value_finder_with_neighbors(self):
        cell_values_neighbors_results = [
            (
                CellValue(2525),
                [NeighborCell(df=self.duplicates_df, cell_value=CellValue('Общий итог'), cell_offset=CellOffset(col=-2, row=6))],
                [CellPosition(col=2, row=5)]
            ),
            (
                CellValue(0),
                [NeighborCell(df=self.duplicates_df, cell_value=CellValue(), cell_offset=CellOffset(col=0, row=-1))],
                [CellPosition(col=5, row=6)]
            ),
            (
                CellValue('Общий итог'),
                [NeighborCell(df=self.duplicates_df, cell_value=CellValue(), cell_offset=CellOffset(col=0, row=1))],
                [CellPosition(col=6, row=0), CellPosition(col=0, row=11)]
            ),
            (
                CellValue('Общий итог'),
                [NeighborCell(df=self.duplicates_df, cell_value=CellValue(''), cell_offset=CellOffset(col=0, row=1))],
                [CellPosition(col=6, row=0), CellPosition(col=0, row=11)]
            ),
            (
                CellValue('Общий итог'),
                [
                    NeighborCell(df=self.duplicates_df, cell_value=CellValue(), cell_offset=CellOffset(col=0, row=1)),
                    NeighborCell(df=self.duplicates_df, cell_value=CellValue(), cell_offset=CellOffset(col=1, row=1)),
                ],
                [CellPosition(col=0, row=11)]
            ),
            (
                CellValue('Общий итог'),
                [
                    NeighborCell(df=self.duplicates_df, cell_value=CellValue(), cell_offset=CellOffset(col=0, row=1)),
                    NeighborCell(df=self.duplicates_df, cell_value=CellValue(''), cell_offset=CellOffset(col=1, row=1)),
                ],
                [CellPosition(col=0, row=11)]
            ),
            (
                CellValue('Общий итог'),
                [
                    NeighborCell(df=self.duplicates_df, cell_value=CellValue(''), cell_offset=CellOffset(col=0, row=1)),
                    NeighborCell(df=self.duplicates_df, cell_value=CellValue(''), cell_offset=CellOffset(col=1, row=1)),
                ],
                [CellPosition(col=0, row=11)]
            ),
            (
                CellValue('Общий итог'),
                [
                    NeighborCell(df=self.duplicates_df, cell_value=CellValue(''), cell_offset=CellOffset(col=0, row=1)),
                    NeighborCell(df=self.duplicates_df, cell_value=CellValue(), cell_offset=CellOffset(col=1, row=1)),
                ],
                [CellPosition(col=0, row=11)]
            ),

        ]
        finder = AllCellPositionsFinder(df=self.duplicates_df)
        for cell_value, neighbors, results in cell_values_neighbors_results:
            finder.value_finder = ExactValueFinder(cell_value=cell_value)
            finder.neighbors_container = NeighborsContainer(neighbors=neighbors)
            finder_results = finder.get_all_positions()
            self._check_results(expected_result=results, finder_result=finder_results)

    @unittest.skip
    def test_cell_values_finder_with_neighbors(self):
        cell_values_neighbors_results = [
            (
                [CellValue(3143), CellValue(2525)],
                [NeighborCell(df=self.duplicates_df, cell_value=CellValue(4690), cell_offset=CellOffset(col=-1, row=0))],
                [CellPosition(col=2, row=5)]
            ),
        ]
        finder = AllCellPositionsFinder(df=self.duplicates_df)
        for cell_values, neighbors, results in cell_values_neighbors_results:
            finder.value_finder = ExactValuesFinder(cell_values=cell_values)
            finder.neighbors_container = NeighborsContainer(neighbors=neighbors)
            finder_results = finder.get_all_positions()
            self._check_results(expected_result=results, finder_result=finder_results)

    @unittest.skip
    def test_regex_cell_value_pattern(self):
        patterns_results = [
            (
                '.*КАНОН.*\d{4}.*',
                [CellPosition(col=0, row=5)]
            ),
            (
                '.*АРИТЕЛ ПЛЮС(?!.*2,5).*',
                [CellPosition(col=0, row=2), CellPosition(col=0, row=7), CellPosition(col=0, row=10)]
            ),
        ]
        finder = AllCellPositionsFinder(df=self.duplicates_df)
        for pattern, results in patterns_results:
            finder.value_finder = RegexFinder(cell_value=CellValue(pattern))
            finder_results = finder.get_all_positions()
            self._check_results(expected_result=results, finder_result=finder_results)

    @unittest.skip
    def test_cell_value_finder_with_offset(self):
        cell_values_results = [
            (CellValue('SKU'), CellOffset(col=1, row=0), [CellPosition(col=1, row=0)]),
            (CellValue('SKU'), CellOffset(col=-10, row=-10), []),
            (
                CellValue('Общий итог'),
                CellOffset(col=0, row=1),
                [
                    CellPosition(col=6, row=1),
                    CellPosition(col=0, row=12),
                ]
            ),
            (CellValue('Общий итог'), CellOffset(col=0, row=2), [CellPosition(col=6, row=2)]),
        ]
        finder = AllCellPositionsFinder(df=self.duplicates_df)
        for cell_value, cell_offset, results in cell_values_results:
            finder.value_finder = ExactValueFinder(cell_value=cell_value)
            finder.cell_offset_action = CellOffsetAction(cell_offset=cell_offset)
            finder_results = finder.get_all_positions()
            self._check_results(expected_result=results, finder_result=finder_results)

    @unittest.skip
    def test_startwith(self):
        patterns_results = [
            (
                '*',
                [
                    CellPosition(col=0, row=1), CellPosition(col=0, row=2), CellPosition(col=0, row=3),
                    CellPosition(col=0, row=4), CellPosition(col=0, row=5), CellPosition(col=0, row=6),
                    CellPosition(col=0, row=7), CellPosition(col=0, row=8), CellPosition(col=0, row=9),
                    CellPosition(col=0, row=10), CellPosition(col=0, row=11), CellPosition(col=0, row=12),
                    CellPosition(col=0, row=13), CellPosition(col=0, row=14), CellPosition(col=0, row=15),
                ]
            ),
            (
                'НЕБИВОЛОЛ-',
                [CellPosition(col=0, row=132), CellPosition(col=0, row=133)]
            ),
            (
                '102',
                []
            ),
            # TODO ДОбавить ещё проверки. Вариант котороый есть ив текстовой ячейке и числовой
        ]
        finder = AllCellPositionsFinder(df=self.simple_df)
        for value, results in patterns_results:
            finder.value_finder = StartWithFinder(cell_value=CellValue(value))
            finder_results = finder.get_all_positions()
            self._check_results(expected_result=results, finder_result=finder_results)

    @unittest.skip
    def test_endwith(self):
        patterns_results = [
            (
                '2,5МГ+6,25МГ №30',
                [CellPosition(col=0, row=1), CellPosition(col=0, row=3)]
            ),
            (
                '25',
                []
            ),
            # TODO ДОбавить ещё проверки. Вариант котороый есть ив текстовой ячейке и числовой
        ]
        finder = AllCellPositionsFinder(df=self.duplicates_df)
        for value, results in patterns_results:
            finder.value_finder = EndWithFinder(cell_value=CellValue(value))
            finder_results = finder.get_all_positions()
            self._check_results(expected_result=results, finder_result=finder_results)

    @unittest.skip
    def test_regex_finder_with_offset_neighbors(self):
        patterns_results = [
            (
                '^\*АРИТЕЛ.*',

            )
        ]

    def test_indexes(self):
        indexes_results = [
            ('a,', ['A']),
            ('a;', ['A']),
            (';a;', ['A']),
            (';a', ['A']),
            (',a', ['A']),
            (',a,', ['A']),
            ('a b C', ['A', 'B', 'C']),
            ('a B-e', ['A', 'B', 'C', 'D', 'E']),
            ('a B:    -e', ['A', 'B', 'C', 'D', 'E']),
            ('a B-   :e', ['A', 'B', 'C', 'D', 'E']),
            ('B:e a', ['B', 'C', 'D', 'E', 'A']),
            ('b:E ,, a', ['B', 'C', 'D', 'E', 'A']),
            ('b-:E ,; A', ['B', 'C', 'D', 'E', 'A']),
            ('b:E;A', ['B', 'C', 'D', 'E', 'A']),
            ('b-E A-c', ['B', 'C', 'D', 'E', 'A', 'B', 'C']),
            ('b-E A:c', ['B', 'C', 'D', 'E', 'A', 'B', 'C']),
            ('T b-E A:c T', ['T', 'B', 'C', 'D', 'E', 'A', 'B', 'C', 'T']),
            (' r,,, X  ----:-  -  Z t ;;; o', ['R', 'X', 'Y', 'Z', 'T', 'O']),
            ('a a a a a', ['A', 'A', 'A', 'A', 'A']),

            ('1 2 3', [1, 2, 3]),
            ('1;2,3', [1, 2, 3]),
            ('1;,;2,,3', [1, 2, 3]),
            ('1  -    3', [1, 2, 3]),
            ('1  -    3 6', [1, 2, 3, 6]),
            ('1-    3 6', [1, 2, 3, 6]),
            ('1   -3 6', [1, 2, 3, 6]),
            (' , 1  -    3 6 , ', [1, 2, 3, 6]),
            (' , 1  -:    3 6 ; ', [1, 2, 3, 6]),
            (' ,,, 1  ----:-  -  3 6 ;;; ', [1, 2, 3, 6]),
            (' 7,,, 1  ----:-  -  3 6 ;;; 9', [7, 1, 2, 3, 6, 9]),
            ('1 1 1 1 1', [1, 1, 1, 1, 1]),
        ]
        for value, result in indexes_results:
            try:
                indexes = Indexes(value)
            except:
                print(value, result)
            self.assertEqual(indexes.get_all_indexes(), result)

        bad_indexes = [
            'a b C, 1,2,3',
            'a b ,-F',
            'a b ;-F',
            'a b ,:F',
            'a b ;:F',
            'a b F-',
            'a b F-,',
            'a b F-;',
            'a b F-,G',
            'a b F,-G',
            'a b F:',
            'a b F:,',
            'a b F:;',
            'a b F:,G',
            'a b F,:G',
            'a b F:',
            'a b :F',
            ':',
            '-',
            ';',
            ' ',
            ',',
            ' : ',
            ' - ',
            ' ; ',
            '    ',
            ' , ',
            '1, 2, 2:f'
            '1, 2, 2-f'
            '1 2 ,-7',
            '1 2 ;-7',
            '1 2 ,:7',
            '1 2 ;:7',
            '1 2 7-',
            '1 2 7-,',
            '1 2 7-;',
            '1 2 7-,9',
            '1 2 7,-9',
            '1 2 7:',
            '1 2 7:,',
            '1 2 7:;',
            '1 2 7:,9',
            '1 2 7,:9',
            '1 2 7:',
            '1 2 :7',

            '4-1',
            'G-a',
            '1 111111111111',
            'a aaaaaaaaaaaa',
            'a ' * 200,
            '1 ' * 200,

        ]
        for value in bad_indexes:
            try:
                self.assertRaises(Exception, Indexes, indexes=value)
            except:
                print(value)

    def _check_results(self, expected_result: list, finder_result: list):
        self.assertEqual(len(expected_result), len(finder_result))
        for index, finder_cell_position in enumerate(finder_result):
            self.assertEqual(expected_result[index], finder_cell_position)


#x=3
#while x>0:
#    print(x)
#    x = x-1
#print('Happy New Years!')

#for i in [5, 4, 3, 2, 1]:
#    print(i)
#print('Happy New Years!')

#print('I like the following colors: ')
#colors = ['blue', 'red', 'yellow']
#for i in colors:
#    print(i)

count = 0
sum = 0
print('Enter a series of numbers and type "done" when finished: ')
while True:
    user = input('> ')
    if user == 'done':
        break

    try:
        fuser = float(user)
    except:
        print('invalid input')
        continue

    count = count + 1
    sum = sum + fuser

print('Count:' , count)
print('Sum:' , sum)
print('Average:' , sum/count)


from utils.utils import ci, si

def add_from_edge_list(iter_g, edge_list):
    for e in edge_list:
        iter_g.add_edge(*e)

def pick_this_edge_pair(edge, k, nid2rank):
    src, dst, t = edge
    if t in ["wr", "ww", 'cb']:
        if nid2rank[ci(src)] + k < nid2rank[si(dst)]:
            return True
    elif t == "rw":
        if nid2rank[si(src)] + k < nid2rank[ci(dst)]:
            return True
    else:
        assert False

    return False

def k_bounded_constraints(k, G, iter_G, nid2rank):
    num_add_edges = 0
    num_dec_conns = 0
    _, _, conn, _ = G.get_4tuples()
    _, _, iter_conn, _ = iter_G.get_4tuples()

    for e1, e2 in conn:  # edge set 1,
        ret1 = pick_this_edge_pair(e1, k, nid2rank)
        ret2 = pick_this_edge_pair(e2, k, nid2rank)
        if ret1 and ret2: # contradiction
            return False
        elif ret1 and (not ret2):
            iter_conn.remove((e1, e2))
            iter_G.add_edge(*e1)
            num_add_edges += len(e1)
            num_dec_conns += 1
        elif ret2 and (not ret1):
            iter_conn.remove((e1, e2))
            iter_G.add_edge(*e2)

            num_add_edges += len(e2)
            num_dec_conns += 1
        else:
            continue

    print(f"Added {num_add_edges} edges while removed {num_dec_conns} constraints")
    return True


"""
Plotly3D Network Graph Generator

DaCapo Brainscience, Inc.

Created by Eli Murphy

January, 2023
"""

import json
from urllib.request import urlopen
import requests
import urllib.request
import igraph as ig

import chart_studio.plotly as py
from plotly.offline import iplot
import plotly.graph_objs as go

data = []

# with urllib.request.urlopen("https://raw.githubusercontent.com/plotly/datasets/master/miserables.json") as response:
#    html = response.read()
# data = json.loads(html)

data = {'nodes': [{'name': 'Mike', 'group': 1},{'name': 'Chloe', 'group': 1},{'name': 'Eli', 'group': 1}], 'links': [{'source': 1, 'target': 0, 'value': 1},{'source': 0, 'target': 2, 'value': 1},{'source': 1, 'target': 2, 'value': 1}]}

print(data)

print(data.keys())

N=len(data['nodes'])
print(N)

L=len(data['links'])
Edges=[(data['links'][k]['source'], data['links'][k]['target']) for k in range(L)]

G=ig.Graph(Edges, directed=True)

print(data['nodes'][0])

G=ig.Graph(Edges, directed=True)
layt=G.layout('kk', dim=3) # plot network with the Kamada-Kawai layout algorithm
print(G)
print(layt[:3])
print(Edges[:3])

labels=[]
group=[]

for node in data['nodes']:
  labels.append(node['name'])
  group.append(node['group'])

print(labels[:3])
print(group[:3])

Xn=[]
Yn=[]
Zn=[]

for k in range(N):
  Xn+=[layt[k][0]]
  Yn+=[layt[k][1]]
  Zn+=[layt[k][2]]

Xe=[]
Ye=[]
Ze=[]

for e in Edges:
  Xe+=[layt[e[0]][0],layt[e[1]][0],None]# x-coordinates of edge ends
  Ye+=[layt[e[0]][1],layt[e[1]][1],None]
  Ze+=[layt[e[0]][2],layt[e[1]][2],None]
print(Xe[:3])
print(Ye[:3])
print(Ze[:3])

trace1=go.Scatter3d(x=Xe, y=Ye, z=Ze, mode='lines', line=dict(color='rgb(125,125,125)', width=1),hoverinfo='none')

trace2=go.Scatter3d(x=Xn, y=Yn, z=Zn, mode='markers', name='actors',
                   marker=dict(symbol='circle', size=6, color=group, colorscale='Viridis',
                      line=dict(color='rgb(50,50,50)', width=0.5)), text=labels, hoverinfo='text')

etext = [f'weight={w}' for w in edge_weights]

trace3 = go.Scatter3d(x=xtp, y=ytp, z=ztp,
                      mode='markers',
                      marker =dict(color='rgb(125,125,125)', size=1), #set the same color as for the edge lines
                      text = etext, hoverinfo='text')
axis=dict(showbackground=False, showline=False, zeroline=False, showgrid=False, showticklabels=False, title='')

layout = go.Layout(
         title="Network of coappearances of characters in Victor Hugo's novel<br> Les Miserables (3D visualization)",
         width=1000,
         height=1000,
         showlegend=False,
         scene=dict(
             xaxis=dict(axis),
             yaxis=dict(axis),
             zaxis=dict(axis),
        ))

data=[trace1, trace2, trace3]

fig=go.Figure(data=data, layout=layout)

iplot(fig, filename='Les-Miserables')


import sys
sys.path.append('../')

import numpy as np
from math import sqrt
from sklearn.metrics import r2_score
from sklearn.decomposition import PCA
from statsmodels.multivariate.cancorr import CanCorr
from low_rank_rnns import helpers

def pearson_corr(a, b):
    mu1 = a.mean()
    mu2 = b.mean()
    return ((a - mu1) * (b - mu2)).mean() / sqrt(((a - mu1)**2).mean() * ((b - mu2)**2).mean())

def pearson_corr_list(vecs1, vecs2):
    """
    returns the mean Pearson correlation between 2 lists of matching vectors, with corrected signs
    """
    vecs1_norm = np.vstack([v / np.linalg.norm(v) for v in vecs1])
    signs = [np.sign(np.mean(v1 * v2)) for v1, v2, in zip(vecs1, vecs2)]
    vecs2_norm = np.vstack([s * v / np.linalg.norm(v) for s, v in zip(signs, vecs2)])
    return pearson_corr(vecs1_norm, vecs2_norm)

def r2_nets_pair(net1, net2, inputs, rates=False, traj1=None):
    """
    R2 of trajectories produced by net2 (predicted) with respect to those of net1 (true)
    :param inputs: torch tensor of shape (n_trials x timesteps x n_input_channels)
    :param rates: bool, if True compute r2 of firing rates.
    :return:
    """
    if traj1 is None:
        out1, traj1 = net1.forward(inputs, return_dynamics=True)
        if rates:
            traj1 = net1.non_linearity(traj1)
        traj1 = traj1.detach().numpy().ravel()

    out2, traj2 = net2.forward(inputs, return_dynamics=True)
    if rates:
        traj2 = net2.non_linearity(traj2)
    traj2 = traj2.detach().numpy().ravel()

    if traj1.shape != traj2.shape:
        raise Exception(f'Error: incompatible shapes compared {traj1.shape} vs {traj2.shape}')
    return r2_score(traj1, traj2)

def r2_idneurons(X1, X2, return_all=False):
    X1 = helpers.flatten_trajectory(X1)
    X2 = helpers.flatten_trajectory(X2)
    r2s = [r2_score(X1[:, i], X2[:, i]) for i in range(X1.shape[-1])]
    if return_all:
        return np.array(r2s)
    else:
        return np.mean(r2s)

def var_exp_ratio(y, yest):
    sse = np.sum((y-yest)**2)
    tot = np.sum(y**2)
    return 1-(sse/tot)

def pca_fit(X, n_components=20):
    pca = PCA(n_components=n_components)
    pca.fit(X)
    return pca

def align(X1, X2, m, pca1=None, pca2=None):
    if pca1 is None:
        pca1 = PCA(n_components=m).fit(X1)
    if pca2 is None:
        pca2 = PCA(n_components=m).fit(X2)

    # Define latent spaces
    proj1 = pca1.components_[:m]
    L1 = X1 @ proj1.T
    proj2 = pca2.components_[:m]
    L2 = X2 @ proj2.T

    # Find aligned projections
    cc = CanCorr(L1, L2)
    al1 = cc.y_cancoef
    al2 = cc.x_cancoef
    Ltilde1 = L1 @ al1
    Ltilde2 = L2 @ al2

    return Ltilde1, Ltilde2, proj1.T @ al1, proj2.T @ al2, cc.cancorr

#%% Cross-validated PCA
"""
Adapted from Joao Barbosa, https://colab.research.google.com/drive/1BPdZZvw-h1mAZkPK6_5LjBBfgezqSGaY?usp=sharing#scrollTo=klugDpK70WoJ
"""

def cvpca_do_split_(D, frac=0.9, shuffle=True):
    n_sep = int(frac * D.shape[0])
    m_sep = int(frac * D.shape[1])
    if shuffle:
        idx_row_train = np.random.choice(np.arange(D.shape[0]), n_sep, replace=False)
        idx_col_train = np.random.choice(np.arange(D.shape[1]), m_sep, replace=False)
        idx_row_test = np.setdiff1d(np.arange(D.shape[0]), idx_row_train)
        idx_col_test = np.setdiff1d(np.arange(D.shape[1]), idx_col_train)
    else:
        idx_row_train = np.arange(n_sep)
        idx_col_train = np.arange(m_sep)
        idx_row_test = np.arange(n_sep, D.shape[0])
        idx_col_test = np.arange(m_sep, D.shape[1])
    X = D[:, idx_col_train]
    Y = D[:, idx_col_test]
    X_train, X_test = X[idx_row_train, :], X[idx_row_test, :]
    Y_train, Y_test = Y[idx_row_train, :], Y[idx_row_test, :]
    return X_train, Y_train, X_test, Y_test, idx_row_train, idx_col_train, idx_row_test, idx_col_test

def cvPCA(D, frac=0.9, n_components=None, shuffle=True):
    X_train, Y_train, X_test, Y_test, idx_row_train, idx_col_train, idx_row_test, idx_col_test = \
        cvpca_do_split_(D, frac, shuffle)
    n_sep, m_sep = X_train.shape
    _, s, V_train = np.linalg.svd(np.concatenate([X_train, Y_train], axis=1), full_matrices=False)

    if n_components is None:
        n_components = D.shape[1]

    var_exps = []
    for dim in range(1, n_components + 1):
        V_train_x = V_train[:dim, :m_sep]
        V_train_y = V_train[:dim, m_sep:]

        pX = X_test @ V_train_x.T  # shape n_test x dim
        y_hat = pX @ V_train_y  # shape n_test x m_test
        var_exps.append(r2_score(Y_test.ravel(), y_hat.ravel()))

    optimal_dim = np.argmax(var_exps) + 1
    idx_V = np.argsort(np.concatenate([idx_col_train, idx_col_test]))
    return var_exps, optimal_dim, var_exps[optimal_dim - 1], V_train[:, idx_V][:n_components]


from collections import deque

case = int(input())

for c in range(case):
    queue = deque()
    n, m = map(int, input().split())
    dump = list(map(int, input().split()))
    max = 0
    for j in dump:
        queue.append(j)
        if j >= max : max = j
    count = 0
    while queue:
        data = queue.popleft()
        if max == data:
            count += 1
            if m == 0:
                print(count)
                break
            else :
                max = 0
                for j in queue:
                    if j >= max: max = j
                if m == 0: m = len(queue)-1
                else: m -= 1
        else :
            queue.append(data)
            if m == 0: m = len(queue)-1
            else: m -= 1


import datetime
import time

import numpy
import picamera
import picamera.array

import events

VECTORS=10
THRESHOLD=88

# 45 rows

class DetectMotion(picamera.array.PiMotionAnalysis):

    def __init__(self, camera, event_queue):
        super().__init__(camera)
        self.event_queue = event_queue
        self.first = True

    def analyze(self, a):
        #a = a[15:18]
        a = numpy.sqrt(
            numpy.square(a['x'].astype(numpy.float)) +
            numpy.square(a['y'].astype(numpy.float))
        ).clip(0, 255).astype(numpy.uint8)
        # If there're more than 10 vectors with a magnitude greater
        # than 60, then say we've detected motion
        if (a > THRESHOLD).sum() > VECTORS:
            if self.first:
                self.first = False
            else:
                print('picam')
                self.event_queue.put(
                    (events.EventTypes.PICAM_MOTION, datetime.datetime.now()))
                self.first = True

def run_picamera_loop(event_queue, thread_kill):
    with picamera.PiCamera() as camera:
        with DetectMotion(camera, event_queue) as output:
            camera.resolution = (640, 480)
            event_queue.put((events.EventTypes.IGNORE_PERIOD, datetime.datetime.now()))
            camera.start_recording(
                '/dev/null', format='h264', motion_output=output)
            while not thread_kill.is_kill():
                camera.wait_recording()
                time.sleep(.2)
            camera.stop_recording()


#!/usr/bin/env python
# encoding: utf-8
#
# bpt.py
#
# Created by José Sánchez-Gallego on 19 Jan 2017.

from __future__ import division
from __future__ import print_function
from __future__ import absolute_import

from packaging.version import parse
import warnings

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

from mpl_toolkits.axes_grid1 import ImageGrid

from marvin.core.exceptions import MarvinDeprecationWarning, MarvinError
from marvin.utils.plot import bind_to_figure

__ALL__ = ('get_snr', 'kewley_sf_nii', 'kewley_sf_sii', 'kewley_sf_oi',
           'kewley_comp_nii', 'kewley_agn_sii', 'kewley_agn_oi',
           'bpt_kewley06')

def get_snr(snr_min, emission_line, default=3):
    """Convenience function to get the minimum SNR for a certain emission line.

    If ``snr_min`` is a dictionary and ``emision_line`` is one of the keys,
    returns that value. If the emission line is not included in the dictionary,
    returns ``default``. If ``snr_min`` is a float, returns that value
    regardless of the ``emission_line``.

    """

    if not isinstance(snr_min, dict):
        return snr_min

    if emission_line in snr_min:
        return snr_min[emission_line]
    else:
        return default

def get_masked(maps, emline, snr=1):
    """Convenience function to get masked arrays without negative values."""

    gflux = maps['emline_gflux_' + emline]
    gflux_masked = gflux.masked

    # Masks spaxels with flux <= 0
    gflux_masked.mask |= (gflux_masked.data <= 0)

    # Masks all spaxels that don't reach the cutoff SNR
    gflux_masked.mask |= gflux.snr < snr
    gflux_masked.mask |= gflux.ivar == 0

    return gflux_masked

def _get_kewley06_axes(use_oi=True):
    """Creates custom axes for displaying Kewley06 plots."""

    fig = plt.figure(None, (8.5, 10))
    fig.clf()

    plt.subplots_adjust(top=0.99, bottom=0.08, hspace=0.01)

    # The axes for the three classification plots
    imgrid_kwargs = {'add_all': True} if parse(matplotlib.__version__) < parse('3.5.0') else {}
    grid_bpt = ImageGrid(fig, 211,
                         nrows_ncols=(1, 3) if use_oi else (1, 2),
                         direction='row',
                         axes_pad=0.1,
                         label_mode='L',
                         share_all=False, **imgrid_kwargs)

    # The axes for the galaxy display
    gal_bpt = ImageGrid(fig, 212, nrows_ncols=(1, 1))

    # Plots the classification boundary lines
    xx_sf_nii = np.linspace(-1.281, 0.045, int(1e4))
    xx_sf_sii = np.linspace(-2, 0.315, int(1e4))
    xx_sf_oi = np.linspace(-2.5, -0.7, int(1e4))

    xx_comp_nii = np.linspace(-2, 0.4, int(1e4))

    xx_agn_sii = np.array([-0.308, 1.0])
    xx_agn_oi = np.array([-1.12, 0.5])

    grid_bpt[0].plot(xx_sf_nii, kewley_sf_nii(xx_sf_nii), 'k--', zorder=90)
    grid_bpt[1].plot(xx_sf_sii, kewley_sf_sii(xx_sf_sii), 'r-', zorder=90)
    if use_oi:
        grid_bpt[2].plot(xx_sf_oi, kewley_sf_oi(xx_sf_oi), 'r-', zorder=90)

    grid_bpt[0].plot(xx_comp_nii, kewley_comp_nii(xx_comp_nii), 'r-', zorder=90)

    grid_bpt[1].plot(xx_agn_sii, kewley_agn_sii(xx_agn_sii), 'b-', zorder=80)
    if use_oi:
        grid_bpt[2].plot(xx_agn_oi, kewley_agn_oi(xx_agn_oi), 'b-', zorder=80)

    # Adds captions
    grid_bpt[0].text(-1, -0.5, 'SF', ha='center', fontsize=12, zorder=100, color='c')
    grid_bpt[0].text(0.5, 0.5, 'AGN', ha='left', fontsize=12, zorder=100)
    grid_bpt[0].text(-0.08, -1.2, 'Comp', ha='left', fontsize=12, zorder=100, color='g')

    grid_bpt[1].text(-1.2, -0.5, 'SF', ha='center', fontsize=12, zorder=100)
    grid_bpt[1].text(-1, 1.2, 'Seyfert', ha='left', fontsize=12, zorder=100, color='r')
    grid_bpt[1].text(0.3, -1, 'LINER', ha='left', fontsize=12, zorder=100, color='m')

    if use_oi:
        grid_bpt[2].text(-2, -0.5, 'SF', ha='center', fontsize=12, zorder=100)
        grid_bpt[2].text(-1.5, 1, 'Seyfert', ha='left', fontsize=12, zorder=100)
        grid_bpt[2].text(-0.1, -1, 'LINER', ha='right', fontsize=12, zorder=100)

    # Sets the ticks, ticklabels, and other details
    xtick_limits = ((-2, 1), (-1.5, 1), (-2.5, 0.5))
    axes = [0, 1, 2] if use_oi else [0, 1]

    for ii in axes:

        grid_bpt[ii].get_xaxis().set_tick_params(direction='in')
        grid_bpt[ii].get_yaxis().set_tick_params(direction='in')

        grid_bpt[ii].set_xticks(np.arange(xtick_limits[ii][0], xtick_limits[ii][1] + 0.5, 0.5))
        grid_bpt[ii].set_xticks(np.arange(xtick_limits[ii][0],
                                          xtick_limits[ii][1] + 0.1, 0.1), minor=True)
        grid_bpt[ii].set_yticks(np.arange(-1.5, 2.0, 0.5))
        grid_bpt[ii].set_yticks(np.arange(-1.5, 1.6, 0.1), minor=True)

        grid_bpt[ii].grid(which='minor', alpha=0.2)
        grid_bpt[ii].grid(which='major', alpha=0.5)

        grid_bpt[ii].set_xlim(xtick_limits[ii][0], xtick_limits[ii][1])

        grid_bpt[ii].set_ylim(-1.5, 1.6)
        if use_oi:
            grid_bpt[ii].set_ylim(-1.5, 1.8)

        grid_bpt[ii].spines['top'].set_visible(True)

        if ii in [0, 1]:
            if not use_oi and ii == 1:
                continue
            grid_bpt[ii].get_xticklabels()[-1].set_visible(False)

    grid_bpt[0].set_ylabel(r'log([OIII]/H$\beta$)')

    grid_bpt[0].set_xlabel(r'log([NII]/H$\alpha$)')
    grid_bpt[1].set_xlabel(r'log([SII]/H$\alpha$)')
    if use_oi:
        grid_bpt[2].set_xlabel(r'log([OI]/H$\alpha$)')

    gal_bpt[0].grid(False)

    return fig, grid_bpt, gal_bpt[0]

def kewley_sf_nii(log_nii_ha):
    """Star forming classification line for log([NII]/Ha)."""
    return 0.61 / (log_nii_ha - 0.05) + 1.3

def kewley_sf_sii(log_sii_ha):
    """Star forming classification line for log([SII]/Ha)."""
    return 0.72 / (log_sii_ha - 0.32) + 1.3

def kewley_sf_oi(log_oi_ha):
    """Star forming classification line for log([OI]/Ha)."""
    return 0.73 / (log_oi_ha + 0.59) + 1.33

def kewley_comp_nii(log_nii_ha):
    """Composite classification line for log([NII]/Ha)."""
    return 0.61 / (log_nii_ha - 0.47) + 1.19

def kewley_agn_sii(log_sii_ha):
    """Seyfert/LINER classification line for log([SII]/Ha)."""
    return 1.89 * log_sii_ha + 0.76

def kewley_agn_oi(log_oi_ha):
    """Seyfert/LINER classification line for log([OI]/Ha)."""
    return 1.18 * log_oi_ha + 1.30

def bpt_kewley06(maps, snr_min=3, return_figure=True, use_oi=True, **kwargs):
    """Returns a classification of ionisation regions, as defined in Kewley+06.

    Makes use of the classification system defined by
    `Kewley et al. (2006) <https://ui.adsabs.harvard.edu/#abs/2006MNRAS.372..961K/abstract>`_
    to return classification masks for different ionisation mechanisms. If ``return_figure=True``,
    produces and returns a matplotlib figure with the classification plots (based on
    Kewley+06 Fig. 4) and the 2D spatial distribution of classified spaxels (i.e., a map of the
    galaxy in which each spaxel is colour-coded based on its emission mechanism).

    While it is possible to call this function directly, its normal use will be via the
    :func:`~marvin.tools.maps.Maps.get_bpt` method.

    Parameters:
        maps (a Marvin :class:`~marvin.tools.maps.Maps` object)
            The Marvin Maps object that contains the emission line maps to be used to determine
            the BPT classification.
        snr_min (float or dict):
            The signal-to-noise cutoff value for the emission lines used to generate the BPT
            diagram. If ``snr_min`` is a single value, that signal-to-noise will be used for all
            the lines. Alternatively, a dictionary of signal-to-noise values, with the
            emission line channels as keys, can be used.
            E.g., ``snr_min={'ha': 5, 'nii': 3, 'oi': 1}``. If some values are not provided,
            they will default to ``SNR>=3``. Note that the value ``sii`` will be applied to both
            ``[SII 6718]`` and ``[SII 6732]``.
        return_figure (bool):
            If ``True``, it also returns the matplotlib figure_ of the BPT diagram plot,
            which can be used to modify the style of the plot.
        use_oi (bool):
            If ``True``, uses the OI diagnostic diagram for spaxel classification.

    Returns:
        bpt_return:
            ``bpt_kewley06`` returns a dictionary of dictionaries of classification masks.
            The classification masks (not to be confused with bitmasks) are boolean arrays with the
            same shape as the Maps or Cube (without the spectral dimension) that can be used
            to select spaxels belonging to a certain excitation process (e.g., star forming).
            The returned dictionary has the following keys: ``'sf'`` (star forming), ``'comp'``
            (composite), ``'agn'``, ``'seyfert'``, ``'liner'``, ``'invalid'``
            (spaxels that are masked out at the DAP level), and ``'ambiguous'`` (good spaxels that
            do not fall in any  classification or fall in more than one). Each key provides access
            to a new dictionary with keys ``'nii'`` (for the constraints in the diagram NII/Halpha
            vs OIII/Hbeta),  ``'sii'`` (SII/Halpha vs OIII/Hbeta), ``'oi'`` (OI/Halpha vs
            OIII/Hbeta; only if ``use_oi=True``), and ``'global'``, which applies all the previous
            constraints at once. The ``'ambiguous'`` mask only contains the ``'global'``
            subclassification, while the ``'comp'`` dictionary only contains ``'nii'``.
            ``'nii'`` is not available for ``'seyfert'`` and ``'liner'``. All the global masks are
            unique (a spaxel can only belong to one of them) with the exception of ``'agn'``, which
            intersects with ``'seyfert'`` and ``'liner'``. Additionally, if ``return_figure=True``,
            ``bpt_kewley06`` will also return the matplotlib figure for the generated plot, and a
            list of axes for each one of the subplots.

    Example:
        >>> maps_8485_1901 = Maps(plateifu='8485-1901')
        >>> bpt_masks, fig, axes = bpt_kewley06(maps_8485_1901)

        Gets the global mask for star forming spaxels

        >>> sf = bpt_masks['sf']['global']

        Gets the seyfert mask based only on the SII/Halpha vs OIII/Hbeta diagnostics

        >>> seyfert_sii = bpt_masks['seyfert']['sii']

    """

    if 'snr' in kwargs:
        warnings.warn('snr is deprecated. Use snr_min instead. '
                      'snr will be removed in a future version of marvin',
                      MarvinDeprecationWarning)
        snr_min = kwargs.pop('snr')

    if len(kwargs.keys()) > 0:
        raise MarvinError('unknown keyword {0}'.format(list(kwargs.keys())[0]))

    # Gets the necessary emission line maps
    oiii = get_masked(maps, 'oiii_5008', snr=get_snr(snr_min, 'oiii'))
    nii = get_masked(maps, 'nii_6585', snr=get_snr(snr_min, 'nii'))
    ha = get_masked(maps, 'ha_6564', snr=get_snr(snr_min, 'ha'))
    hb = get_masked(maps, 'hb_4862', snr=get_snr(snr_min, 'hb'))
    oi = get_masked(maps, 'oi_6302', snr=get_snr(snr_min, 'oi'))

    sii_6718 = get_masked(maps, 'sii_6718', snr=get_snr(snr_min, 'sii'))
    sii_6732 = get_masked(maps, 'sii_6732', snr=get_snr(snr_min, 'sii'))
    sii = sii_6718 + sii_6732

    # Calculate masked logarithms
    log_oiii_hb = np.ma.log10(oiii / hb)
    log_nii_ha = np.ma.log10(nii / ha)
    log_sii_ha = np.ma.log10(sii / ha)
    log_oi_ha = np.ma.log10(oi / ha)

    # Calculates masks for each emission mechanism according to the paper boundaries.
    # The log_nii_ha < 0.05, log_sii_ha < 0.32, etc are necessary because the classification lines
    # diverge and we only want the region before the asymptota.
    sf_mask_nii = ((log_oiii_hb < kewley_sf_nii(log_nii_ha)) & (log_nii_ha < 0.05)).filled(False)
    sf_mask_sii = ((log_oiii_hb < kewley_sf_sii(log_sii_ha)) & (log_sii_ha < 0.32)).filled(False)
    sf_mask_oi = ((log_oiii_hb < kewley_sf_oi(log_oi_ha)) & (log_oi_ha < -0.59)).filled(False)
    sf_mask = sf_mask_nii & sf_mask_sii & sf_mask_oi if use_oi else sf_mask_nii & sf_mask_sii

    comp_mask = ((log_oiii_hb > kewley_sf_nii(log_nii_ha)) & (log_nii_ha < 0.05)).filled(False) & \
                ((log_oiii_hb < kewley_comp_nii(log_nii_ha)) & (log_nii_ha < 0.465)).filled(False)
    comp_mask &= (sf_mask_sii & sf_mask_oi) if use_oi else sf_mask_sii

    agn_mask_nii = ((log_oiii_hb > kewley_comp_nii(log_nii_ha)) |
                    (log_nii_ha > 0.465)).filled(False)
    agn_mask_sii = ((log_oiii_hb > kewley_sf_sii(log_sii_ha)) |
                    (log_sii_ha > 0.32)).filled(False)
    agn_mask_oi = ((log_oiii_hb > kewley_sf_oi(log_oi_ha)) |
                   (log_oi_ha > -0.59)).filled(False)
    agn_mask = agn_mask_nii & agn_mask_sii & agn_mask_oi if use_oi else agn_mask_nii & agn_mask_sii

    seyfert_mask_sii = agn_mask & (kewley_agn_sii(log_sii_ha) < log_oiii_hb).filled(False)
    seyfert_mask_oi = agn_mask & (kewley_agn_oi(log_oi_ha) < log_oiii_hb).filled(False)
    seyfert_mask = seyfert_mask_sii & seyfert_mask_oi if use_oi else seyfert_mask_sii

    liner_mask_sii = agn_mask & (kewley_agn_sii(log_sii_ha) > log_oiii_hb).filled(False)
    liner_mask_oi = agn_mask & (kewley_agn_oi(log_oi_ha) > log_oiii_hb).filled(False)
    liner_mask = liner_mask_sii & liner_mask_oi if use_oi else liner_mask_sii

    # The invalid mask is the combination of spaxels that are invalid in all of the emission maps
    invalid_mask_nii = ha.mask | oiii.mask | nii.mask | hb.mask
    invalid_mask_sii = ha.mask | oiii.mask | sii.mask | hb.mask
    invalid_mask_oi = ha.mask | oiii.mask | oi.mask | hb.mask

    invalid_mask = ha.mask | oiii.mask | nii.mask | hb.mask | sii.mask
    if use_oi:
        invalid_mask |= oi.mask

    # The ambiguous mask are spaxels that are not invalid but don't fall into any of the
    # emission mechanism classifications.
    ambiguous_mask = ~(sf_mask | comp_mask | seyfert_mask | liner_mask) & ~invalid_mask

    sf_classification = {'global': sf_mask,
                         'nii': sf_mask_nii,
                         'sii': sf_mask_sii}

    comp_classification = {'global': comp_mask,
                           'nii': comp_mask}

    agn_classification = {'global': agn_mask,
                          'nii': agn_mask_nii,
                          'sii': agn_mask_sii}

    seyfert_classification = {'global': seyfert_mask,
                              'sii': seyfert_mask_sii}

    liner_classification = {'global': liner_mask,
                            'sii': liner_mask_sii}

    invalid_classification = {'global': invalid_mask,
                              'nii': invalid_mask_nii,
                              'sii': invalid_mask_sii}

    ambiguous_classification = {'global': ambiguous_mask}

    if use_oi:
        sf_classification['oi'] = sf_mask_oi
        agn_classification['oi'] = agn_mask_oi
        seyfert_classification['oi'] = seyfert_mask_oi
        liner_classification['oi'] = liner_mask_oi
        invalid_classification['oi'] = invalid_mask_oi

    bpt_return_classification = {'sf': sf_classification,
                                 'comp': comp_classification,
                                 'agn': agn_classification,
                                 'seyfert': seyfert_classification,
                                 'liner': liner_classification,
                                 'invalid': invalid_classification,
                                 'ambiguous': ambiguous_classification}

    if not return_figure:
        return bpt_return_classification

    # Does all the plotting
    with plt.style.context('seaborn-darkgrid'):
        fig, grid_bpt, gal_bpt = _get_kewley06_axes(use_oi=use_oi)

    sf_kwargs = {'marker': 's', 's': 12, 'color': 'c', 'zorder': 50, 'alpha': 0.7, 'lw': 0.0,
                 'label': 'Star-forming'}
    sf_handler = grid_bpt[0].scatter(log_nii_ha[sf_mask], log_oiii_hb[sf_mask], **sf_kwargs)
    grid_bpt[1].scatter(log_sii_ha[sf_mask], log_oiii_hb[sf_mask], **sf_kwargs)

    comp_kwargs = {'marker': 's', 's': 12, 'color': 'g', 'zorder': 45, 'alpha': 0.7, 'lw': 0.0,
                   'label': 'Composite'}
    comp_handler = grid_bpt[0].scatter(log_nii_ha[comp_mask], log_oiii_hb[comp_mask],
                                       **comp_kwargs)
    grid_bpt[1].scatter(log_sii_ha[comp_mask], log_oiii_hb[comp_mask], **comp_kwargs)

    seyfert_kwargs = {'marker': 's', 's': 12, 'color': 'r', 'zorder': 40, 'alpha': 0.7, 'lw': 0.0,
                      'label': 'Seyfert'}
    seyfert_handler = grid_bpt[0].scatter(log_nii_ha[seyfert_mask], log_oiii_hb[seyfert_mask],
                                          **seyfert_kwargs)
    grid_bpt[1].scatter(log_sii_ha[seyfert_mask], log_oiii_hb[seyfert_mask], **seyfert_kwargs)

    liner_kwargs = {'marker': 's', 's': 12, 'color': 'm', 'zorder': 35, 'alpha': 0.7, 'lw': 0.0,
                    'label': 'LINER'}
    liner_handler = grid_bpt[0].scatter(log_nii_ha[liner_mask], log_oiii_hb[liner_mask],
                                        **liner_kwargs)
    grid_bpt[1].scatter(log_sii_ha[liner_mask], log_oiii_hb[liner_mask], **liner_kwargs)

    amb_kwargs = {'marker': 's', 's': 12, 'color': '0.6', 'zorder': 30, 'alpha': 0.7, 'lw': 0.0,
                  'label': 'Ambiguous '}
    amb_handler = grid_bpt[0].scatter(log_nii_ha[ambiguous_mask], log_oiii_hb[ambiguous_mask],
                                      **amb_kwargs)
    grid_bpt[1].scatter(log_sii_ha[ambiguous_mask], log_oiii_hb[ambiguous_mask], **amb_kwargs)

    if use_oi:
        grid_bpt[2].scatter(log_oi_ha[sf_mask], log_oiii_hb[sf_mask], **sf_kwargs)
        grid_bpt[2].scatter(log_oi_ha[comp_mask], log_oiii_hb[comp_mask], **comp_kwargs)
        grid_bpt[2].scatter(log_oi_ha[seyfert_mask], log_oiii_hb[seyfert_mask], **seyfert_kwargs)
        grid_bpt[2].scatter(log_oi_ha[liner_mask], log_oiii_hb[liner_mask], **liner_kwargs)
        grid_bpt[2].scatter(log_oi_ha[ambiguous_mask], log_oiii_hb[ambiguous_mask], **amb_kwargs)

    # Creates the legend
    grid_bpt[0].legend([sf_handler, comp_handler, seyfert_handler, liner_handler, amb_handler],
                       ['Star-forming', 'Composite', 'Seyfert', 'LINER', 'Ambiguous'], ncol=2,
                       loc='upper left', frameon=True, labelspacing=0.1, columnspacing=0.1,
                       handletextpad=0.1, fontsize=9)

    # Creates a RGB image of the galaxy, and sets the colours of the spaxels to match the
    # classification masks
    gal_rgb = np.zeros((ha.shape[0], ha.shape[1], 3), dtype=np.uint8)

    for ii in [1, 2]:  # Cyan
        gal_rgb[:, :, ii][sf_mask] = 255

    gal_rgb[:, :, 1][comp_mask] = 128  # Green

    gal_rgb[:, :, 0][seyfert_mask] = 255  # Red

    # Magenta
    gal_rgb[:, :, 0][liner_mask] = 255
    gal_rgb[:, :, 2][liner_mask] = 255

    for ii in [0, 1, 2]:
        gal_rgb[:, :, ii][invalid_mask] = 255  # White
        gal_rgb[:, :, ii][ambiguous_mask] = 169  # Grey

    # Shows the image.
    gal_bpt.imshow(gal_rgb, origin='lower', aspect='auto', interpolation='nearest')

    gal_bpt.set_xlim(0, ha.shape[1] - 1)
    gal_bpt.set_ylim(0, ha.shape[0] - 1)
    gal_bpt.set_xlabel('x [spaxels]')
    gal_bpt.set_ylabel('y [spaxels]')

    axes = grid_bpt.axes_all + [gal_bpt]

    # Adds custom method to create figure
    for ax in axes:
        setattr(ax.__class__, 'bind_to_figure', _bind_to_figure)

    return (bpt_return_classification, fig, axes)

def _bind_to_figure(self, fig=None):
    """Copies axes to a new figure.

    Uses ``marvin.utils.plot.utils.bind_to_figure`` with a number
    of tweaks.

    """

    new_figure = bind_to_figure(self, fig=fig)

    if new_figure.axes[0].get_ylabel() == '':
        new_figure.axes[0].set_ylabel('log([OIII]/H$\\beta$)')

    return new_figure